emacs-diffs
[Top][All Lists]
Advanced

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

feature/pgtk 3e30047 1/2: Merge branch 'master' of git.sv.gnu.org:/srv/g


From: Yuuki Harano
Subject: feature/pgtk 3e30047 1/2: Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk
Date: Sun, 13 Dec 2020 12:06:34 -0500 (EST)

branch: feature/pgtk
commit 3e30047ce3a81dd0879973012abbf570d3215dfd
Merge: aea5dbe fe50a8b
Author: Yuuki Harano <masm+github@masm11.me>
Commit: Yuuki Harano <masm+github@masm11.me>

    Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk
---
 .gitlab-ci.yml                                     |   2 +-
 admin/nt/dist-build/build-dep-zips.py              |   1 -
 doc/emacs/maintaining.texi                         |  10 +
 doc/emacs/misc.texi                                |  25 +-
 doc/emacs/rmail.texi                               |   6 +-
 doc/lispref/backups.texi                           |   6 +-
 doc/lispref/display.texi                           |  44 ++-
 doc/lispref/internals.texi                         |  18 +-
 doc/lispref/keymaps.texi                           |   7 +-
 doc/lispref/os.texi                                |  16 +-
 doc/lispref/streams.texi                           |  18 +-
 doc/lispref/text.texi                              |  16 ++
 doc/lispref/variables.texi                         |  10 +-
 doc/misc/calc.texi                                 |   8 +-
 doc/misc/cl.texi                                   |  13 +-
 doc/misc/efaq.texi                                 |  61 ++---
 doc/misc/gnus.texi                                 |  55 +++-
 etc/NEWS                                           | 110 +++++++-
 etc/grep.txt                                       |   6 +
 etc/publicsuffix.txt                               | 108 ++++----
 lib-src/etags.c                                    |   1 +
 lisp/apropos.el                                    |   4 +-
 lisp/array.el                                      |  34 +--
 lisp/battery.el                                    |  10 +-
 lisp/buff-menu.el                                  |   4 +-
 lisp/button.el                                     |  14 +
 lisp/calc/calc-bin.el                              |  52 +---
 lisp/calc/calc-comb.el                             |  10 +-
 lisp/calc/calc-ext.el                              |  30 +-
 lisp/calc/calc-funcs.el                            |   4 +-
 lisp/calc/calc-graph.el                            |   2 +-
 lisp/calc/calc-macs.el                             |   8 -
 lisp/calc/calc-math.el                             |  16 +-
 lisp/calc/calc.el                                  |   2 +-
 lisp/calc/calccomp.el                              |  37 ++-
 lisp/calendar/calendar.el                          |   2 +-
 lisp/calendar/diary-lib.el                         |  23 +-
 lisp/chistory.el                                   |   2 +-
 lisp/comint.el                                     |  32 ++-
 lisp/cus-edit.el                                   |  11 +-
 lisp/dabbrev.el                                    |  10 +-
 lisp/desktop.el                                    |   8 +-
 lisp/dframe.el                                     |   8 +-
 lisp/dired-aux.el                                  |  10 +-
 lisp/dired-x.el                                    |   4 +-
 lisp/dired.el                                      |  14 +-
 lisp/doc-view.el                                   |   2 +-
 lisp/ebuff-menu.el                                 |   7 +-
 lisp/edmacro.el                                    |   6 +-
 lisp/emacs-lisp/bytecomp.el                        | 131 +++++----
 lisp/emacs-lisp/cl-generic.el                      |  14 +-
 lisp/emacs-lisp/eldoc.el                           |   1 -
 lisp/emacs-lisp/elint.el                           |  10 +-
 lisp/emacs-lisp/ert.el                             |   2 +-
 lisp/emacs-lisp/lisp-mode.el                       |   8 +-
 lisp/emacs-lisp/memory-report.el                   | 303 +++++++++++++++++++++
 lisp/emacs-lisp/package.el                         |  16 +-
 lisp/emacs-lisp/pcase.el                           |   3 +-
 lisp/emacs-lisp/thunk.el                           |   2 +-
 lisp/emulation/edt.el                              |   2 +-
 lisp/emulation/viper-cmd.el                        |  14 +-
 lisp/emulation/viper.el                            |   2 +-
 lisp/epa-file.el                                   |   3 +-
 lisp/epg.el                                        |   7 +
 lisp/face-remap.el                                 |   4 +-
 lisp/files.el                                      |  17 +-
 lisp/filesets.el                                   |   3 +-
 lisp/find-dired.el                                 |  15 +-
 lisp/find-lisp.el                                  |  30 +-
 lisp/finder.el                                     |   2 +-
 lisp/font-core.el                                  |   8 +-
 lisp/font-lock.el                                  |  27 +-
 lisp/format.el                                     |   5 +-
 lisp/gnus/gnus-agent.el                            |   8 +-
 lisp/gnus/gnus-art.el                              |  35 ++-
 lisp/gnus/gnus-cus.el                              |  34 +--
 lisp/gnus/gnus-group.el                            |   5 +-
 lisp/gnus/gnus-msg.el                              |  21 +-
 lisp/gnus/gnus-registry.el                         |  72 +++--
 lisp/gnus/gnus-salt.el                             |  10 +-
 lisp/gnus/gnus-score.el                            |   6 +-
 lisp/gnus/gnus-search.el                           |  41 ++-
 lisp/gnus/gnus-srvr.el                             |   3 +-
 lisp/gnus/gnus-start.el                            |  13 +-
 lisp/gnus/gnus-sum.el                              |  67 +++--
 lisp/gnus/gnus-topic.el                            |  23 +-
 lisp/gnus/gnus-undo.el                             |   4 +-
 lisp/gnus/gnus-win.el                              |   4 +-
 lisp/gnus/gnus.el                                  |  54 ++--
 lisp/gnus/message.el                               |  91 +++----
 lisp/gnus/mm-view.el                               |   2 +-
 lisp/gnus/mml.el                                   |   4 +-
 lisp/gnus/nndiary.el                               |   8 +-
 lisp/gnus/nnfolder.el                              |   6 +-
 lisp/gnus/nnheader.el                              |   2 +-
 lisp/gnus/nnimap.el                                |  14 +-
 lisp/gnus/nnml.el                                  |   4 +-
 lisp/gnus/spam.el                                  |  26 +-
 lisp/help-fns.el                                   |   3 +-
 lisp/help-mode.el                                  |   8 +-
 lisp/hexl.el                                       |  10 +-
 lisp/ibuffer.el                                    |  47 ++--
 lisp/icomplete.el                                  |  11 +-
 lisp/ido.el                                        |   5 +-
 lisp/ielm.el                                       |  28 +-
 lisp/image.el                                      |  45 +--
 lisp/image/exif.el                                 |   2 +-
 lisp/info.el                                       |   6 +-
 lisp/international/characters.el                   |   9 +-
 lisp/international/isearch-x.el                    |  15 +-
 lisp/international/robin.el                        |   3 +-
 lisp/isearch.el                                    |  13 +-
 lisp/language/korea-util.el                        |  15 +-
 lisp/language/korean.el                            |   1 +
 lisp/leim/quail/hangul.el                          |   2 +-
 lisp/leim/quail/uni-input.el                       |   3 +-
 lisp/locate.el                                     |  10 +-
 lisp/mail/rmail.el                                 |   7 +-
 lisp/mail/rmailsum.el                              |   7 +
 lisp/man.el                                        |   8 +-
 lisp/master.el                                     |   3 +-
 lisp/minibuffer.el                                 |   6 +-
 lisp/net/rcirc.el                                  |  36 ++-
 lisp/net/socks.el                                  |   6 +-
 lisp/net/tramp-adb.el                              |   6 +-
 lisp/net/tramp-gvfs.el                             |  11 +-
 lisp/net/tramp-sh.el                               | 252 ++++++++++-------
 lisp/net/tramp-smb.el                              |   6 +-
 lisp/net/tramp.el                                  |   4 +-
 lisp/newcomment.el                                 |  68 ++---
 lisp/outline.el                                    |   2 +-
 lisp/pcomplete.el                                  |   4 +-
 lisp/play/dunnet.el                                | 200 ++++++--------
 lisp/proced.el                                     |   6 +-
 lisp/progmodes/cc-engine.el                        |  60 ++--
 lisp/progmodes/cfengine.el                         |  46 ++--
 lisp/progmodes/compile.el                          |  70 ++---
 lisp/progmodes/cperl-mode.el                       | 206 ++++++--------
 lisp/progmodes/dcl-mode.el                         |  12 +-
 lisp/progmodes/elisp-mode.el                       |  13 +-
 lisp/progmodes/etags.el                            |  77 +++---
 lisp/progmodes/executable.el                       |   2 +-
 lisp/progmodes/f90.el                              |  41 ++-
 lisp/progmodes/flymake-cc.el                       |   2 +-
 lisp/progmodes/fortran.el                          | 104 +++----
 lisp/progmodes/gdb-mi.el                           |  39 ++-
 lisp/progmodes/grep.el                             |  35 ++-
 lisp/progmodes/gud.el                              |  72 ++---
 lisp/progmodes/hideif.el                           |  16 +-
 lisp/progmodes/hideshow.el                         |   2 +-
 lisp/progmodes/icon.el                             |  33 ++-
 lisp/progmodes/inf-lisp.el                         |   9 +-
 lisp/progmodes/ld-script.el                        |   7 +-
 lisp/progmodes/make-mode.el                        |  30 +-
 lisp/progmodes/meta-mode.el                        |  50 ++--
 lisp/progmodes/mixal-mode.el                       |  22 +-
 lisp/progmodes/modula2.el                          |  16 +-
 lisp/progmodes/perl-mode.el                        |  39 ++-
 lisp/progmodes/project.el                          |  14 +-
 lisp/progmodes/ps-mode.el                          |  26 +-
 lisp/progmodes/python.el                           | 152 +++++------
 lisp/progmodes/simula.el                           |  32 +--
 lisp/progmodes/sql.el                              |  63 ++---
 lisp/progmodes/subword.el                          |   2 +-
 lisp/progmodes/tcl.el                              |  64 +++--
 lisp/progmodes/which-func.el                       |   2 +-
 lisp/progmodes/xref.el                             |  31 ++-
 lisp/progmodes/xscheme.el                          |  18 +-
 lisp/recentf.el                                    |   6 +-
 lisp/replace.el                                    |   2 +-
 lisp/reveal.el                                     |   2 +-
 lisp/ruler-mode.el                                 |   4 +-
 lisp/scroll-lock.el                                |   2 +-
 lisp/server.el                                     |  26 +-
 lisp/shell.el                                      |  46 ++--
 lisp/simple.el                                     |  57 ++--
 lisp/skeleton.el                                   |  13 +-
 lisp/speedbar.el                                   |  21 +-
 lisp/startup.el                                    |   4 +-
 lisp/strokes.el                                    |  18 +-
 lisp/subr.el                                       |  69 +++--
 lisp/svg.el                                        |  13 +
 lisp/tab-bar.el                                    |   2 +
 lisp/tar-mode.el                                   |  32 +--
 lisp/term.el                                       |  39 ++-
 lisp/textmodes/bibtex-style.el                     |  12 +-
 lisp/textmodes/bibtex.el                           |  30 +-
 lisp/textmodes/table.el                            |   2 +
 lisp/textmodes/tex-mode.el                         |   9 +-
 lisp/thumbs.el                                     |   5 +-
 lisp/timezone.el                                   |   2 +-
 lisp/tool-bar.el                                   |   3 +-
 lisp/tree-widget.el                                |   7 +-
 lisp/tutorial.el                                   |  14 +
 lisp/url/url-cookie.el                             |   2 +-
 lisp/url/url-http.el                               |  12 +-
 lisp/url/url-util.el                               |   4 +-
 lisp/vc/ediff-ptch.el                              |   3 +
 lisp/vc/log-edit.el                                |  25 +-
 lisp/vc/vc-git.el                                  |   2 +-
 lisp/vc/vc-hg.el                                   |  11 +-
 lisp/vc/vc.el                                      |  19 +-
 lisp/wdired.el                                     |  16 +-
 lisp/whitespace.el                                 |  29 +-
 lisp/window.el                                     |   6 +-
 lisp/xwidget.el                                    |   2 +-
 lwlib/lwlib-utils.c                                |  15 +-
 src/charset.c                                      |   4 +-
 src/chartab.c                                      |   6 +-
 src/data.c                                         |   5 +-
 src/emacs-module.c                                 |   8 +-
 src/emacs.c                                        |  13 +-
 src/eval.c                                         |  24 +-
 src/fileio.c                                       |   7 +-
 src/fns.c                                          |  70 ++++-
 src/frame.c                                        |  12 +-
 src/image.c                                        | 125 +++++++--
 src/keyboard.c                                     |  61 +----
 src/keyboard.h                                     |   1 -
 src/lisp.h                                         |  33 +--
 src/nsterm.m                                       |  10 +-
 src/process.c                                      |  43 ---
 src/regex-emacs.c                                  |  17 +-
 src/termhooks.h                                    |   1 -
 src/thread.h                                       |   1 -
 src/w32gui.h                                       |   1 +
 src/w32term.c                                      |  30 +-
 src/window.c                                       |  56 +++-
 src/xdisp.c                                        |  98 ++++---
 src/xterm.c                                        |   4 -
 test/README                                        |   3 +-
 test/lisp/abbrev-tests.el                          |   5 +-
 test/lisp/allout-tests.el                          |   6 +-
 test/lisp/emacs-lisp/bytecomp-tests.el             |  69 +++++
 test/lisp/emacs-lisp/edebug-tests.el               |   5 +-
 test/lisp/emacs-lisp/ert-tests.el                  |  10 +
 .../faceup-resources/faceup-test-mode.el           |   4 +-
 test/lisp/emacs-lisp/gv-tests.el                   |  11 +-
 test/lisp/emacs-lisp/memory-report-tests.el        |  57 ++++
 test/lisp/epg-tests.el                             |   3 +-
 test/lisp/filenotify-tests.el                      |  80 ++++--
 test/lisp/net/rcirc-tests.el                       |  12 +
 test/lisp/vc/vc-tests.el                           |   3 +-
 test/manual/indent/perl.perl                       |  14 +
 test/src/casefiddle-tests.el                       |   3 +-
 test/src/data-tests.el                             |   2 +-
 test/src/emacs-module-resources/mod-test.c         |  30 ++
 test/src/emacs-module-tests.el                     |  20 ++
 test/src/eval-tests.el                             |  50 ++++
 test/src/fns-tests.el                              |  16 ++
 test/src/regex-emacs-tests.el                      |  64 +++++
 251 files changed, 3645 insertions(+), 2406 deletions(-)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index f4e08d5..bab2573 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -91,7 +91,7 @@ test-filenotify-gio:
     - ./autogen.sh autoconf
     - ./configure --without-makeinfo --with-file-notification=gfile
     - make bootstrap
-    - make -C test autorevert-tests filenotify-tests
+    - make -k -C test autorevert-tests filenotify-tests
 
 test-gnustep:
   stage: test
diff --git a/admin/nt/dist-build/build-dep-zips.py 
b/admin/nt/dist-build/build-dep-zips.py
index 7047d28..bc5f65f 100755
--- a/admin/nt/dist-build/build-dep-zips.py
+++ b/admin/nt/dist-build/build-dep-zips.py
@@ -18,7 +18,6 @@
 ## along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
 import argparse
 import multiprocessing as mp
-import glob
 import os
 import shutil
 import re
diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi
index 1f10b68..aa4513e 100644
--- a/doc/emacs/maintaining.texi
+++ b/doc/emacs/maintaining.texi
@@ -2199,12 +2199,22 @@ Display the reference on the current line.
 Move to the next reference and display it in the other window
 (@code{xref-next-line}).
 
+@item N
+@findex xref-next-group
+Move to the first reference of the next reference group and display it
+in the other window (@code{xref-next-group}).
+
 @item p
 @itemx ,
 @findex xref-prev-line
 Move to the previous reference and display it in the other window
 (@code{xref-prev-line}).
 
+@item P
+@findex xref-prev-group
+Move to the first reference of the previous reference group and
+display it in the other window (@code{xref-prev-group}).
+
 @item C-o
 @findex xref-show-location-at-point
 Display the reference on the current line in the other window
diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi
index 5b5134b..c2c382e 100644
--- a/doc/emacs/misc.texi
+++ b/doc/emacs/misc.texi
@@ -1893,6 +1893,12 @@ with @kbd{C-x #}.  But @kbd{C-x #} is the way to tell
 window or a frame, @kbd{C-x #} always displays the next server buffer
 in that window or in that frame.
 
+@vindex server-client-instructions
+  When @command{emacsclient} connects, the server will normally output
+a message that says how to exit the client frame.  If
+@code{server-client-instructions} is set to @code{nil}, this message
+is inhibited.
+
 @node emacsclient Options
 @subsection @code{emacsclient} Options
 @cindex @code{emacsclient} options
@@ -2255,13 +2261,18 @@ off.
 @vindex ps-print-color-p
   If your printer doesn't support colors, you should turn off color
 processing by setting @code{ps-print-color-p} to @code{nil}.  By
-default, if the display supports colors, Emacs produces hardcopy output
-with color information; on black-and-white printers, colors are emulated
-with shades of gray.  This might produce illegible output, even if your
-screen colors only use shades of gray.
-
-  Alternatively, you can set @code{ps-print-color-p} to @code{black-white} to
-print colors on black/white printers.
+default, if the display supports colors, Emacs produces hardcopy
+output with color information; on black-and-white printers, colors are
+emulated with shades of gray.  This might produce barely-readable or
+even illegible output, even if your screen colors only use shades of
+gray.
+
+@vindex ps-black-white-faces
+  Alternatively, you can set @code{ps-print-color-p} to @code{black-white}
+to have colors display better on black/white printers.  This works by
+using information in @code{ps-black-white-faces} to express colors by
+customizable list of shades of gray, augmented by bold and italic
+face attributes.
 
 @vindex ps-use-face-background
   By default, PostScript printing ignores the background colors of the
diff --git a/doc/emacs/rmail.texi b/doc/emacs/rmail.texi
index 14ee062..467c526 100644
--- a/doc/emacs/rmail.texi
+++ b/doc/emacs/rmail.texi
@@ -1273,9 +1273,9 @@ temporary buffer to display the current @acronym{MIME} 
message.
 
 @findex rmail-epa-decrypt
 @cindex encrypted mails (reading in Rmail)
-  If the current message is an encrypted one, use the command @kbd{M-x
-rmail-epa-decrypt} to decrypt it, using the EasyPG library
-(@pxref{Top,, EasyPG, epa, EasyPG Assistant User's Manual}).
+  If the current message is an encrypted one, use the command
+@kbd{C-c C-d} (@code{rmail-epa-decrypt}) to decrypt it, using the
+EasyPG library (@pxref{Top,, EasyPG, epa, EasyPG Assistant User's Manual}).
 
   You can highlight and activate URLs in the Rmail buffer using Goto
 Address mode:
diff --git a/doc/lispref/backups.texi b/doc/lispref/backups.texi
index 3792795..c20ef68 100644
--- a/doc/lispref/backups.texi
+++ b/doc/lispref/backups.texi
@@ -706,7 +706,11 @@ contents and the file contents are identical before the 
revert
 operation, reverting preserves all the markers.  If they are not
 identical, reverting does change the buffer; in that case, it preserves
 the markers in the unchanged text (if any) at the beginning and end of
-the buffer.  Preserving any additional markers would be problematical.
+the buffer.  Preserving any additional markers would be problematic.
+
+When reverting from non-file sources, markers are usually not
+preserved, but this is up to the specific @code{revert-buffer-function}
+implementation.
 @end deffn
 
 @defvar revert-buffer-in-progress-p
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index f86baf5..2b3119e 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -2632,10 +2632,12 @@ appearance of @var{face} will again be determined by 
its default face
 spec.
 
 @cindex @code{eval-defun}, and @code{defface} forms
+@cindex @code{eval-last-sexp}, and @code{defface} forms
 As an exception, if you evaluate a @code{defface} form with
-@kbd{C-M-x} in Emacs Lisp mode (@code{eval-defun}), a special feature
-of @code{eval-defun} overrides any custom face specs on the face,
-causing the face to reflect exactly what the @code{defface} says.
+@kbd{C-M-x} (@code{eval-defun}) or with @kbd{C-x C-e}
+(@code{eval-last-sexp}) in Emacs Lisp mode, a special feature of these
+commands overrides any custom face specs on the face, causing the face
+to reflect exactly what the @code{defface} says.
 
 The @var{spec} argument is a @dfn{face spec}, which states how the
 face should appear on different kinds of terminals.  It should be an
@@ -5898,6 +5900,26 @@ string containing the image data as raw bytes.  
@var{image-type} should be a
 @end lisp
 @end defun
 
+@defun svg-embed-base-uri-image svg relative-filename &rest args
+To @var{svg} add an embedded (raster) image placed at
+@var{relative-filename}.  @var{relative-filename} is searched inside
+@code{file-name-directory} of the @code{:base-uri} svg image property.
+This improves the performance of embedding large images.
+
+@lisp
+;; Embeding /tmp/subdir/rms.jpg and /tmp/another/rms.jpg
+(svg-embed-base-uri-image svg "subdir/rms.jpg"
+           :width "100px" :height "100px"
+           :x "50px" :y "75px")
+(svg-embed-base-uri-image svg "another/rms.jpg"
+           :width "100px" :height "100px"
+           :x "75px" :y "50px")
+(svg-image svg :scale 1.0
+           :base-uri "/tmp/dummy"
+           :width 175 :height 175)
+@end lisp
+@end defun
+
 @defun svg-clip-path svg &rest args
 Add a clipping path to @var{svg}.  If applied to a shape via the
 @var{:clip-path} property, parts of that shape which lie outside of
@@ -6575,6 +6597,12 @@ except when you explicitly clear it.  This mode can be 
useful for
 debugging.
 @end defvar
 
+@defun image-cache-size
+This function returns the total size of the current image cache, in
+bytes.  An image of size 200x100 with 24 bits per color will have a
+cache size of 60000 bytes, for instance.
+@end defun
+
 @node Xwidgets
 @section Embedded Native Widgets
 @cindex xwidget
@@ -6879,6 +6907,16 @@ This inserts a button with the label @var{label} at 
point, using text
 properties.
 @end defun
 
+@defun button-buttonize string callback &optional data
+Sometimes it's more convenient to make a string into a button without
+inserting it into a buffer immediately, for instance when creating
+data structures that may then, later, be inserted into a buffer.  This
+function makes @var{string} into such a string, and @var{callback}
+will be called when the user clicks on the button.  The optional
+@var{data} parameter will be used as the parameter when @var{callback}
+is called.  If @code{nil}, the button is used as the parameter instead.
+@end defun
+
 @node Manipulating Buttons
 @subsection Manipulating Buttons
 @cindex manipulating buttons
diff --git a/doc/lispref/internals.texi b/doc/lispref/internals.texi
index bb25983..28a5fdb 100644
--- a/doc/lispref/internals.texi
+++ b/doc/lispref/internals.texi
@@ -615,6 +615,19 @@ during garbage collection so far in this Emacs session, as 
a
 floating-point number.
 @end defvar
 
+@defun memory-report
+It can sometimes be useful to see where Emacs is using memory (in
+various variables, buffers, and caches).  This command will open a new
+buffer (called @samp{"*Memory Report*"}) that will give an overview,
+in addition to listing the ``largest'' buffers and variables.
+
+All the data here is approximate, because there's really no consistent
+way to compute the size of a variable.  For instance, two variables
+may share parts of a data structure, and this will be counted twice,
+but this command may still give a useful high-level overview of which
+parts of Emacs is using memory.
+@end defun
+
 @node Stack-allocated Objects
 @section Stack-allocated Objects
 
@@ -1851,7 +1864,10 @@ byte, is @var{len}.  The original string in @var{str} 
can be either an
 it can include embedded null bytes, and doesn't have to end in a
 terminating null byte at @code{@var{str}[@var{len}]}.  The function
 raises the @code{overflow-error} error condition if @var{len} is
-negative or exceeds the maximum length of an Emacs string.
+negative or exceeds the maximum length of an Emacs string.  If
+@var{len} is zero, then @var{str} can be @code{NULL}, otherwise it
+must point to valid memory.  For nonzero @var{len}, @code{make_string}
+returns unique mutable string objects.
 @end deftypefn
 
 @deftypefn Function emacs_value make_unibyte_string (emacs_env *@var{env}, 
const char *@var{str}, ptrdiff_t @var{len})
diff --git a/doc/lispref/keymaps.texi b/doc/lispref/keymaps.texi
index 130ff0d..6635f50 100644
--- a/doc/lispref/keymaps.texi
+++ b/doc/lispref/keymaps.texi
@@ -2167,9 +2167,10 @@ string.  Thus, the string need not be a constant.
 
 The third element, @var{real-binding}, can be the command to execute
 (in which case you get a normal menu item).  It can also be a keymap,
-which will result in a submenu.  Finally, it can be @code{nil}, in
-which case you will get a non-selectable menu item.  This is mostly
-useful when creating separator lines and the like.
+which will result in a submenu, and @var{item-name} is used as the
+submenu name.  Finally, it can be @code{nil}, in which case you will
+get a non-selectable menu item.  This is mostly useful when creating
+separator lines and the like.
 
 The tail of the list, @var{item-property-list}, has the form of a
 property list which contains other information.
diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi
index f897cfa..bc60220 100644
--- a/doc/lispref/os.texi
+++ b/doc/lispref/os.texi
@@ -2633,14 +2633,14 @@ calls @var{function} with no arguments, or 
@samp{--eval=@var{form}}.
 
   Any Lisp program output that would normally go to the echo area,
 either using @code{message}, or using @code{prin1}, etc., with
-@code{t} as the stream, goes instead to Emacs's standard descriptors
-when in batch mode: @code{message} writes to the standard error
-descriptor, while @code{prin1} and other print functions write to the
-standard output.  Similarly, input that would normally come from the
-minibuffer is read from the standard input descriptor.  Thus, Emacs
-behaves much like a noninteractive application program.  (The echo
-area output that Emacs itself normally generates, such as command
-echoing, is suppressed entirely.)
+@code{t} as the stream (@pxref{Output Streams}), goes instead to
+Emacs's standard descriptors when in batch mode: @code{message} writes
+to the standard error descriptor, while @code{prin1} and other print
+functions write to the standard output.  Similarly, input that would
+normally come from the minibuffer is read from the standard input
+descriptor.  Thus, Emacs behaves much like a noninteractive
+application program.  (The echo area output that Emacs itself normally
+generates, such as command echoing, is suppressed entirely.)
 
 Non-ASCII text written to the standard output or error descriptors is
 by default encoded using @code{locale-coding-system} (@pxref{Locales})
diff --git a/doc/lispref/streams.texi b/doc/lispref/streams.texi
index 0534afb..5b4be83 100644
--- a/doc/lispref/streams.texi
+++ b/doc/lispref/streams.texi
@@ -123,13 +123,13 @@ came from.  In this case, it makes no difference what 
value
 @code{t} used as a stream means that the input is read from the
 minibuffer.  In fact, the minibuffer is invoked once and the text
 given by the user is made into a string that is then used as the
-input stream.  If Emacs is running in batch mode, standard input is used
-instead of the minibuffer.  For example,
+input stream.  If Emacs is running in batch mode (@pxref{Batch Mode}),
+standard input is used instead of the minibuffer.  For example,
 @example
 (message "%s" (read t))
 @end example
-will read a Lisp expression from standard input and print the result
-to standard output.
+will in batch mode read a Lisp expression from standard input and
+print the result to standard output.
 
 @item @code{nil}
 @cindex @code{nil} input stream
@@ -392,13 +392,15 @@ is responsible for storing the characters wherever you 
want to put them.
 
 @item @code{t}
 @cindex @code{t} output stream
-The output characters are displayed in the echo area.
+The output characters are displayed in the echo area.  If Emacs is
+running in batch mode (@pxref{Batch Mode}), the output is written to
+the standard output descriptor instead.
 
 @item @code{nil}
 @cindex @code{nil} output stream
-@code{nil} specified as an output stream means to use the value of
-@code{standard-output} instead; that value is the @dfn{default output
-stream}, and must not be @code{nil}.
+@code{nil} specified as an output stream means to use the value of the
+@code{standard-output} variable instead; that value is the
+@dfn{default output stream}, and must not be @code{nil}.
 
 @item @var{symbol}
 A symbol as output stream is equivalent to the symbol's function
diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi
index c6ca4ee..b712768 100644
--- a/doc/lispref/text.texi
+++ b/doc/lispref/text.texi
@@ -2931,6 +2931,22 @@ used instead.  Here is an example:
 @end example
 @end defvar
 
+@defun object-intervals OBJECT
+This function returns a copy of the intervals (i.e., text properties)
+in @var{object} as a list of intervals.  @var{object} must be a string
+or a buffer.  Altering the structure of this list does not change the
+intervals in the object.
+
+@example
+(object-intervals (propertize "foo" 'face 'bold))
+     @result{} ((0 3 (face bold)))
+@end example
+
+Each element in the returned list represents one interval.  Each
+interval has three parts: The first is the start, the second is the
+end, and the third part is the text property itself.
+@end defun
+
 @node Changing Properties
 @subsection Changing Text Properties
 @cindex changing text properties
diff --git a/doc/lispref/variables.texi b/doc/lispref/variables.texi
index 095ea9d..b9ff074 100644
--- a/doc/lispref/variables.texi
+++ b/doc/lispref/variables.texi
@@ -481,10 +481,12 @@ form occurs in a @code{let} form with lexical binding 
enabled), then
 effect until its binding construct exits.  @xref{Variable Scoping}.
 
 @cindex @code{eval-defun}, and @code{defvar} forms
-When you evaluate a top-level @code{defvar} form with @kbd{C-M-x} in
-Emacs Lisp mode (@code{eval-defun}), a special feature of
-@code{eval-defun} arranges to set the variable unconditionally, without
-testing whether its value is void.
+@cindex @code{eval-last-sexp}, and @code{defvar} forms
+When you evaluate a top-level @code{defvar} form with @kbd{C-M-x}
+(@code{eval-defun}) or with @kbd{C-x C-e} (@code{eval-last-sexp}) in
+Emacs Lisp mode, a special feature of these two commands arranges to
+set the variable unconditionally, without testing whether its value is
+void.
 
 If the @var{doc-string} argument is supplied, it specifies the
 documentation string for the variable (stored in the symbol's
diff --git a/doc/misc/calc.texi b/doc/misc/calc.texi
index 6a6f585..1fa13e9 100644
--- a/doc/misc/calc.texi
+++ b/doc/misc/calc.texi
@@ -28047,13 +28047,7 @@ defined as the distance that light will travel in a 
vacuum in
 vacuum is exactly 299792458 m/s.  Many other units have been
 redefined in terms of fundamental physical processes; a second, for
 example, is currently defined as 9192631770 periods of a certain
-radiation related to the cesium-133 atom.  The only SI unit that is not
-based on a fundamental physical process (although there are efforts to
-change this) is the kilogram, which was originally defined as the mass
-of one liter of water, but is now defined as the mass of the
-international prototype of the kilogram (IPK), a cylinder of platinum-iridium
-kept at the Bureau international des poids et mesures in Sèvres,
-France.  (There are several copies of the IPK throughout the world.)
+radiation related to the cesium-133 atom.
 The British imperial units, once defined in terms of physical objects,
 were redefined in 1963 in terms of SI units.  The US customary units,
 which were the same as British units until the British imperial system
diff --git a/doc/misc/cl.texi b/doc/misc/cl.texi
index 084edd1..742be28 100644
--- a/doc/misc/cl.texi
+++ b/doc/misc/cl.texi
@@ -1097,10 +1097,9 @@ by @var{x} if specified.
 
 @defmac cl-pushnew x place @t{&key :test :test-not :key}
 This macro inserts @var{x} at the front of the list stored in
-@var{place}, but only if @var{x} was not @code{eql} to any
-existing element of the list.  The optional keyword arguments
-are interpreted in the same way as for @code{cl-adjoin}.
-@xref{Lists as Sets}.
+@var{place}, but only if @var{x} isn't present in the list already.
+The optional keyword arguments are interpreted in the same way as for
+@code{cl-adjoin}.  @xref{Lists as Sets}.
 @end defmac
 
 @defmac cl-shiftf place@dots{} newvalue
@@ -3796,8 +3795,10 @@ This is a destructive version of @code{cl-sublis}.
 @section Lists as Sets
 
 @noindent
-These functions perform operations on lists that represent sets
-of elements.
+These functions perform operations on lists that represent sets of
+elements.  All these functions (unless otherwise specified) default to
+using @code{eql} as the test function, but that can be modified by the
+@code{:test} parameter.
 
 @defun cl-member item list @t{&key :test :test-not :key}
 This function searches @var{list} for an element matching @var{item}.
diff --git a/doc/misc/efaq.texi b/doc/misc/efaq.texi
index 1bc9d41..462eb4c 100644
--- a/doc/misc/efaq.texi
+++ b/doc/misc/efaq.texi
@@ -512,10 +512,10 @@ This chapter tells you how to get help with Emacs.
 @cindex Help system, entering the
 
 Type @kbd{C-h t} to invoke the self-paced tutorial.  Just typing
-@kbd{C-h} enters the help system.  Starting with Emacs 22, the tutorial
-is available in many foreign languages such as French, German, Japanese,
-Russian, etc.  Use @kbd{M-x help-with-tutorial-spec-language @key{RET}}
-to choose your language and start the tutorial.
+@kbd{C-h} enters the help system.  The tutorial is available in many
+foreign languages such as French, German, Japanese, Russian, etc.  Use
+@kbd{M-x help-with-tutorial-spec-language @key{RET}} to choose your
+language and start the tutorial.
 
 Your system administrator may have changed @kbd{C-h} to act like
 @key{DEL} to deal with local keyboards.  You can use @kbd{M-x
@@ -966,9 +966,9 @@ latest features, you may want to stick to the releases.
 
 The following sections list some of the major new features in the last
 few Emacs releases.  For full details of the changes in any version of
-Emacs, type @kbd{C-h C-n} (@kbd{M-x view-emacs-news}).  As of Emacs 22,
-you can give this command a prefix argument to read about which features
-were new in older versions.
+Emacs, type @kbd{C-h C-n} (@kbd{M-x view-emacs-news}).  You can give
+this command a prefix argument to read about which features were new
+in older versions.
 
 @node New in Emacs 26
 @section What is different about Emacs 26?
@@ -1725,14 +1725,6 @@ buffer by default, put this in your @file{.emacs} file:
            (setq abbrev-mode t)))
 @end lisp
 
-@noindent If your Emacs version is older then 22.1, you will also need to use:
-
-@lisp
-(condition-case ()
-   (quietly-read-abbrev-file)
-  (file-error nil))
-@end lisp
-
 @node Associating modes with files
 @section How do I make Emacs use a certain major mode for certain files?
 @cindex Associating modes with files
@@ -2583,16 +2575,14 @@ effective way of doing that.  Emacs automatically 
intercepts the compile
 error messages, inserts them into a special buffer called
 @file{*compilation*}, and lets you visit the locus of each message in
 the source.  Type @kbd{C-x `} to step through the offending lines one by
-one (starting with Emacs 22, you can also use @kbd{M-g M-p} and
-@kbd{M-g M-n} to go to the previous and next matches directly).  Click
-@kbd{mouse-2} or press @key{RET} on a message text in the
-@file{*compilation*} buffer to go to the line whose number is mentioned
-in that message.
+one (you can also use @kbd{M-g M-p} and @kbd{M-g M-n} to go to the
+previous and next matches directly).  Click @kbd{mouse-2} or press
+@key{RET} on a message text in the @file{*compilation*} buffer to go
+to the line whose number is mentioned in that message.
 
 But if you indeed need to go to a certain text line, type @kbd{M-g M-g}
-(which is the default binding of the @code{goto-line} function starting
-with Emacs 22).  Emacs will prompt you for the number of the line and go
-to that line.
+(which is the default binding of the @code{goto-line} function).
+Emacs will prompt you for the number of the line and go to that line.
 
 You can do this faster by invoking @code{goto-line} with a numeric
 argument that is the line's number.  For example, @kbd{C-u 286 M-g M-g}
@@ -2825,13 +2815,13 @@ Add the following line to your @file{.emacs} file:
 @cindex @code{ls} in Shell mode
 
 In many systems, @code{ls} is aliased to @samp{ls --color}, which
-prints using ANSI color escape sequences.  Emacs version 21.1 and
-later includes the @code{ansi-color} package, which lets Shell mode
-recognize these escape sequences.  In Emacs 23.2 and later, the
-package is enabled by default; in earlier versions you can enable it
-by typing @kbd{M-x ansi-color-for-comint-mode} in the Shell buffer, or
-by adding @code{(add-hook 'shell-mode-hook
-'ansi-color-for-comint-mode-on)} to your init file.
+prints using ANSI color escape sequences.  Emacs includes the
+@code{ansi-color} package, which lets Shell mode recognize these
+escape sequences.  In Emacs 23.2 and later, the package is enabled by
+default; in earlier versions you can enable it by typing @kbd{M-x
+ansi-color-for-comint-mode} in the Shell buffer, or by adding
+@code{(add-hook 'shell-mode-hook 'ansi-color-for-comint-mode-on)} to
+your init file.
 
 @node Fullscreen mode on MS-Windows
 @section How can I start Emacs in fullscreen mode on MS-Windows?
@@ -3210,12 +3200,11 @@ arbitrary Emacs Lisp code evaluated when the file is 
visited.
 Obviously, there is a potential for Trojan horses to exploit this
 feature.
 
-As of Emacs 22, Emacs has a list of local variables that are known to
-be safe to set.  If a file tries to set any variable outside this
-list, it asks the user to confirm whether the variables should be set.
-You can also tell Emacs whether to allow the evaluation of Emacs Lisp
-code found at the bottom of files by setting the variable
-@code{enable-local-eval}.
+Emacs has a list of local variables that are known to be safe to set.
+If a file tries to set any variable outside this list, it asks the
+user to confirm whether the variables should be set. You can also tell
+Emacs whether to allow the evaluation of Emacs Lisp code found at the
+bottom of files by setting the variable @code{enable-local-eval}.
 
 @xref{File Variables,,, emacs, The GNU Emacs Manual}.
 
diff --git a/doc/misc/gnus.texi b/doc/misc/gnus.texi
index 4aa07ce..3743b49 100644
--- a/doc/misc/gnus.texi
+++ b/doc/misc/gnus.texi
@@ -5028,10 +5028,37 @@ Nothing if the article is a root and lots of spaces if 
it isn't (it
 pushes everything after it off the screen).
 @item [
 Opening bracket, which is normally @samp{[}, but can also be @samp{<}
-for adopted articles (@pxref{Customizing Threading}).
+for adopted articles (@pxref{Customizing Threading}).  This can be
+customized using following settings:
+
+@table @code
+@item gnus-sum-opening-bracket
+@vindex gnus-sum-opening-bracket
+Opening bracket for normal (non-adopted) articles.  The default is
+@samp{[}.
+
+@item gnus-sum-opening-bracket-adopted
+@vindex gnus-sum-opening-bracket-adopted
+Opening bracket for adopted articles.  The default is @samp{<}.
+
+@end table
+
 @item ]
 Closing bracket, which is normally @samp{]}, but can also be @samp{>}
-for adopted articles.
+for adopted articles.  This can be customised using following settings:
+
+@table @code
+@item gnus-sum-closing-bracket
+@vindex gnus-sum-closing-bracket
+Closing bracket for normal (non-adopted) articles.  The default is
+@samp{]}.
+
+@item gnus-sum-closing-bracket-adopted
+@vindex gnus-sum-opening-bracket-adopted
+Closing bracket for adopted articles.  The default is @samp{>}.
+
+@end table
+
 @item >
 One space for each thread level.
 @item <
@@ -26260,6 +26287,16 @@ registry will keep.  If the registry has reached or 
exceeded this
 size, it will reject insertion of new entries.
 @end defvar
 
+@defvar gnus-registry-register-all
+If this option is non-nil, the registry will register all messages, as
+you see them.  This is important to making split-to-parent and
+Message-ID references work correctly, as the registry needs to know
+where all messages are, but it can slow down group opening and the
+saving of Gnus.  If this option is nil, entries must be created
+manually, for instance by storing a custom flag or keyword for the
+message.
+@end defvar
+
 @defvar gnus-registry-prune-factor
 This option (a float between 0 and 1) controls how much the registry
 is cut back during pruning.  In order to prevent constant pruning, the
@@ -26349,8 +26386,14 @@ have to put a rule like this:
       "mail")
 @end lisp
 
-in your fancy split setup.  In addition, you may want to customize the
-following variables.
+in your fancy split setup.
+
+If @code{gnus-registry-register-all} is non-nil (the default), the
+registry will perform splitting for all messages.  If it is nil,
+splitting will only happen for children of messages you've explicitly
+registered.
+
+In addition, you may want to customize the following variables.
 
 @defvar gnus-registry-track-extra
 This is a list of symbols, so it's best to change it from the
@@ -26423,7 +26466,9 @@ Store @code{value} under @code{key} for message 
@code{id}.
 @end defun
 
 @defun gnus-registry-get-id-key (id key)
-Get the data under @code{key} for message @code{id}.
+Get the data under @code{key} for message @code{id}.  If the option
+@code{gnus-registry-register-all} is non-nil, this function will also
+create an entry for @code{id} if one doesn't exist.
 @end defun
 
 @defvar gnus-registry-extra-entries-precious
diff --git a/etc/NEWS b/etc/NEWS
index 525ed8b..909473f 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -88,6 +88,13 @@ useful on systems such as FreeBSD which ships only with 
"etc/termcap".
 ** Minibuffer scrolling is now conservative by default.
 This is controlled by the new variable 'scroll-minibuffer-conservatively'.
 
+In addition, there is a new variable
+`redisplay-adhoc-scroll-in-resize-mini-windows` to disable the
+ad-hoc auto-scrolling when resizing minibuffer windows.  It has been
+found that its heuristic can be counter productive in some corner
+cases, tho the cure may be worse than the disease.  This said, the
+effect should be negligible in the vast majority of cases anyway.
+
 +++
 ** Improved handling of minibuffers on switching frames.
 By default, when you switch to another frame, an active minibuffer now
@@ -192,6 +199,11 @@ have been replaced with "chat.freenode.net" throughout 
Emacs.
 These functions return the connection local value of the respective
 variables.  This can be used for remote hosts.
 
+** Emacs now prints a backtrace when signaling an error in batch mode.
+This makes debugging Emacs Lisp scripts run in batch mode easier.  To
+get back the old behavior, set the new variable
+'backtrace-on-error-noninteractive' to a nil value.
+
 
 * Editing Changes in Emacs 28.1
 
@@ -270,6 +282,11 @@ preserving markers, properties and overlays.  The new 
variable
 number of seconds that 'revert-buffer-with-fine-grain' should spend
 trying to be non-destructive.
 
++++
+** New command 'memory-report'.
+This command opens a new buffer called "*Memory Report*" and gives a
+summary of where Emacs is using memory currently.
+
 ** Outline
 
 +++
@@ -282,6 +299,18 @@ the buffer cycles the whole buffer between "only top-level 
headings",
 
 * Changes in Specialized Modes and Packages in Emacs 28.1
 
+** Loading dunnet.el in batch mode doesn't start the game any more
+Instead you need to do 'emacs -f dun-batch' to start the game in
+batch mode.
+
+** Emacs Server
+
++++
+*** New user option 'server-client-instructions'.
+When emacsclient connects, Emacs will (by default) output a message
+about how to exit the client frame.  If 'server-client-instructions'
+is set to nil, this message is inhibited.
+
 ** Python mode
 
 *** 'C-c C-r' can now be used on arbitrary regions.
@@ -489,6 +518,26 @@ tags to be considered as well.
 ** Gnus
 
 +++
+*** New user option 'gnus-registry-register-all'.
+
+If non-nil (the default), create registry entries for all messages.
+If nil, don't automatically create entries, they must be created
+manually.
+
++++
+*** New user options to customise the summary line specs %[ and %].
+Four new options introduced in customisation group
+'gnus-summary-format'.  These are 'gnus-sum-opening-bracket',
+'gnus-sum-closing-bracket', 'gnus-sum-opening-bracket-adopted', and
+'gnus-sum-closing-bracket-adopted'.  Their default values are '[', ']',
+'<', '>' respectively. These variables control the appearance of '%['
+and '%]' specs in the summary line format.  '%[' will normally display
+the value of 'gnus-sum-opening-bracket', but can also be
+'gnus-sum-opening-bracket-adopted' for the adopted articles.  '%]' will
+normally display the value of 'gnus-sum-closing-bracket', but can also
+be 'gnus-sum-closing-bracket-adopted' for the adopted articles.
+
++++
 *** New user option 'gnus-paging-select-next'.
 This controls what happens when using commands like 'SPC' and 'DEL' to
 page the current article.  If non-nil (the default), go to the
@@ -1077,6 +1126,22 @@ If 'shr-width' is non-nil, it overrides this variable.
 ** Images
 
 ---
+** Can explicitly specify base_uri for svg images.
+':base-uri' image property can be used to explicitly specify base_uri
+for embedded images into svg. ':base-uri' is supported for both file
+and data svg images.
+
++++
+** 'svg-embed-base-uri-image' added to embed images
+'svg-embed-base-uri-image' can be used to embed images located
+relatively to 'file-name-directory' of the ':base-uri' svg image property.
+This works much faster then 'svg-embed'.
+
++++
+*** New function 'image-cache-size'.
+This function returns the size of the current image cache, in bytes.
+
+---
 *** Animated images stop automatically under high CPU pressure sooner.
 Previously, an animated image would stop animating if any single image
 took more than two seconds to display.  The new algorithm maintains a
@@ -1192,6 +1257,11 @@ So far Grep and ripgrep are supported.  ripgrep seems to 
offer better
 performance in certain cases, in particular for case-insensitive
 searches.
 
++++
+*** New commands 'xref-prev-group' and 'xref-next-group'.
+These commands are bound respectively to 'P' and 'N', and navigate to
+the first item of the previous or next group in the "*xref*" buffer.
+
 ** json.el
 
 ---
@@ -1350,8 +1420,41 @@ This face is used for error messages from 'diff'.
 *** New command 'diff-refresh-hunk'.
 This new command (bound to 'C-c C-l') regenerates the current hunk.
 
+** Buttons
+
++++
+*** New minor mode 'button-mode'.
+This minor mode does nothing else than install 'button-buffer-map' as
+a minor mode map (which binds the 'TAB' / 'S-TAB' key bindings to navigate
+to buttons), and can be used in any view-mode-like buffer that has
+buttons in it.
+
++++
+*** New utility function 'button-buttonize'.
+This function takes a string and returns a string propertized in a way
+that makes it a valid button.
+
+
 ** Miscellaneous
 
++++
+*** New function 'object-intervals'.
+This function returns a copy of the list of intervals (i.e., text
+properties) in the object in question (which must either be a string
+or a buffer).
+
+---
+*** 'hexl-mode' scrolling commands now heed 'next-screen-context-lines'.
+Previously, 'hexl-scroll-down' and 'hexl-scroll-up' would scroll
+up/down an entire window, but they now work more like the standard
+scrolling commands.
+
+---
+*** Errors in 'kill-emacs-hook' no longer prevent Emacs from shutting down.
+If a function in that hook signals an error in an interactive Emacs,
+the user will be prompted on whether to continue.  If the user doesn't
+answer within five seconds, Emacs will continue shutting down anyway.
+
 ---
 *** iso-transl is now preloaded.
 This means that keystrokes like 'Alt-[' are defined by default,
@@ -1450,13 +1553,6 @@ both modes are on).
 This works like 'report-emacs-bug', but is more geared towards sending
 patches to the Emacs issue tracker.
 
-+++
-*** New minor mode 'button-mode'.
-This minor mode does nothing else than install 'button-buffer-map' as
-a minor mode map (which binds the 'TAB' / 'S-TAB' key bindings to navigate
-to buttons), and can be used in any view-mode-like buffer that has
-buttons in it.
-
 ---
 *** 'icomplete-show-matches-on-no-input' behavior change.
 Previously, choosing a different completion with commands like 'C-.'
diff --git a/etc/grep.txt b/etc/grep.txt
index 19a3b4b..3dc4aac 100644
--- a/etc/grep.txt
+++ b/etc/grep.txt
@@ -85,6 +85,12 @@ git --no-pager grep -inH -p -e "org-element-map"
 lisp/org/org.el=20969=(defun org-fill-paragraph (&optional 
justify)
 lisp/org/org.el:21047:               (org-element-map
 
+* ripgrep
+
+rg -nH --color always --no-heading -e grep-match-regexp
+lisp/progmodes/grep.el:608:        (while 
(re-search-forward grep-match-regexp end 1)
+Binary file emacs.info matches (found "\u{0}" byte around offset 2222525)
+
 * unknown greps
 
 grep -nH -e "xyzxyz" ../info/*
diff --git a/etc/publicsuffix.txt b/etc/publicsuffix.txt
index bcde672..1ede2b9 100644
--- a/etc/publicsuffix.txt
+++ b/etc/publicsuffix.txt
@@ -1152,7 +1152,7 @@ gov.gr
 // gs : https://en.wikipedia.org/wiki/.gs
 gs
 
-// gt : http://www.gt/politicas_de_registro.html
+// gt : https://www.gt/sitio/registration_policy.php?lang=en
 gt
 com.gt
 edu.gt
@@ -4703,6 +4703,7 @@ nl
 // Norid geographical second level domains : 
https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-b/
 // Norid category second level domains : 
https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-c/
 // Norid category second-level domains managed by parties other than Norid : 
https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-d/
+// RSS feed: https://teknisk.norid.no/en/feed/
 no
 // Norid category second level domains : 
https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-c/
 fhs.no
@@ -7110,7 +7111,7 @@ org.zw
 
 // newGTLDs
 
-// List of new gTLDs imported from 
https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 
2020-10-08T17:45:32Z
+// List of new gTLDs imported from 
https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 
2020-11-30T20:26:10Z
 // This list is auto-generated, don't edit it manually.
 // aaa : 2015-02-26 American Automobile Association, Inc.
 aaa
@@ -7328,7 +7329,7 @@ author
 // auto : 2014-11-13 XYZ.COM LLC
 auto
 
-// autos : 2014-01-09 DERAutos, LLC
+// autos : 2014-01-09 XYZ.COM LLC
 autos
 
 // avianca : 2015-01-08 Avianca Holdings S.A.
@@ -7337,7 +7338,7 @@ avianca
 // aws : 2015-06-25 Amazon Registry Services, Inc.
 aws
 
-// axa : 2013-12-19 AXA SA
+// axa : 2013-12-19 AXA Group Operations SAS
 axa
 
 // azure : 2014-12-18 Microsoft Corporation
@@ -7478,7 +7479,7 @@ bmw
 // bnpparibas : 2014-05-29 BNP Paribas
 bnpparibas
 
-// boats : 2014-12-04 DERBoats, LLC
+// boats : 2014-12-04 XYZ.COM LLC
 boats
 
 // boehringer : 2015-07-09 Boehringer Ingelheim International GmbH
@@ -7517,7 +7518,7 @@ bot
 // boutique : 2013-11-14 Binky Moon, LLC
 boutique
 
-// box : 2015-11-12 .BOX INC.
+// box : 2015-11-12 Intercap Registry Inc.
 box
 
 // bradesco : 2014-12-18 Banco Bradesco S.A.
@@ -8501,7 +8502,7 @@ homedepot
 // homegoods : 2015-07-16 The TJX Companies, Inc.
 homegoods
 
-// homes : 2014-01-09 DERHomes, LLC
+// homes : 2014-01-09 XYZ.COM LLC
 homes
 
 // homesense : 2015-07-16 The TJX Companies, Inc.
@@ -8651,9 +8652,6 @@ java
 // jcb : 2014-11-20 JCB Co., Ltd.
 jcb
 
-// jcp : 2015-04-23 JCP Media, Inc.
-jcp
-
 // jeep : 2015-07-30 FCA US LLC.
 jeep
 
@@ -9077,7 +9075,7 @@ moscow
 // moto : 2015-06-04 Motorola Trademark Holdings, LLC
 moto
 
-// motorcycles : 2014-01-09 DERMotorcycles, LLC
+// motorcycles : 2014-01-09 XYZ.COM LLC
 motorcycles
 
 // mov : 2014-01-30 Charleston Road Registry Inc.
@@ -9242,7 +9240,7 @@ one
 // ong : 2014-03-06 Public Interest Registry
 ong
 
-// onl : 2013-09-16 I-Registry Ltd.
+// onl : 2013-09-16 iRegistry GmbH
 onl
 
 // online : 2015-01-15 DotOnline Inc.
@@ -9539,7 +9537,7 @@ reviews
 // rexroth : 2015-06-18 Robert Bosch GMBH
 rexroth
 
-// rich : 2013-11-21 I-Registry Ltd.
+// rich : 2013-11-21 iRegistry GmbH
 rich
 
 // richardli : 2015-05-14 Pacific Century Asset Management (HK) Limited
@@ -9758,9 +9756,6 @@ show
 // showtime : 2015-08-06 CBS Domains Inc.
 showtime
 
-// shriram : 2014-01-23 Shriram Capital Ltd.
-shriram
-
 // silk : 2015-06-25 Amazon Registry Services, Inc.
 silk
 
@@ -10073,7 +10068,7 @@ travelers
 // travelersinsurance : 2015-03-26 Travelers TLD, LLC
 travelersinsurance
 
-// trust : 2014-10-16 NCC Group Domain Services, Inc.
+// trust : 2014-10-16 UNR Corp.
 trust
 
 // trv : 2015-03-26 Travelers TLD, LLC
@@ -10595,7 +10590,7 @@ vermögensberatung
 // xyz : 2013-12-05 XYZ.COM LLC
 xyz
 
-// yachts : 2014-01-09 DERYachts, LLC
+// yachts : 2014-01-09 XYZ.COM LLC
 yachts
 
 // yahoo : 2015-04-02 Yahoo! Domain Services Inc.
@@ -10680,12 +10675,6 @@ barsy.ca
 // Submitted by Werner Kaltofen <wk@all-inkl.com>
 kasserver.com
 
-// Algorithmia, Inc. : algorithmia.com
-// Submitted by Eli Perelman <eperelman@algorithmia.io>
-*.algorithmia.com
-!teams.algorithmia.com
-!test.algorithmia.com
-
 // Altervista: https://www.altervista.org
 // Submitted by Carlo Cannas <tech_staff@altervista.it>
 altervista.org
@@ -10868,6 +10857,10 @@ bnr.la
 // Submitted by Paul Crowder <paul.crowder@blackbaud.com>
 blackbaudcdn.net
 
+// Blatech : http://www.blatech.net
+// Submitted by Luke Bratch <luke@bratch.co.uk>
+of.je
+
 // Boomla : https://boomla.com
 // Submitted by Tibor Halter <thalter@boomla.com>
 boomla.net
@@ -10981,10 +10974,6 @@ c.la
 // Submitted by B. Blechschmidt <hostmaster@certmgr.org>
 certmgr.org
 
-// Citrix : https://citrix.com
-// Submitted by Alex Stoddard <alex.stoddard@citrix.com>
-xenapponazure.com
-
 // Civilized Discourse Construction Kit, Inc. : https://www.discourse.org/
 // Submitted by Rishabh Nambiar & Michael Brown <team@discourse.org>
 discourse.group
@@ -11073,10 +11062,6 @@ cloudns.pro
 cloudns.pw
 cloudns.us
 
-// Cloudeity Inc : https://cloudeity.com
-// Submitted by Stefan Dimitrov <contact@cloudeity.com>
-cloudeity.net
-
 // CNPY : https://cnpy.gdn
 // Submitted by Angelo Gladding <angelo@lahacker.net>
 cnpy.gdn
@@ -11537,6 +11522,10 @@ ddnss.org
 definima.net
 definima.io
 
+// DigitalOcean : https://digitalocean.com/
+// Submitted by Braxton Huggins <bhuggins@digitalocean.com>
+ondigitalocean.app
+
 // dnstrace.pro : https://dnstrace.pro/
 // Submitted by Chris Partridge <chris@partridge.tech>
 bci.dnstrace.pro
@@ -11802,6 +11791,10 @@ ukco.me
 // submitted by Koen Van Isterdael <k.vanisterdael@fermax.be>
 mydobiss.com
 
+// FH Muenster : https://www.fh-muenster.de
+// Submitted by Robin Naundorf <r.naundorf@fh-muenster.de>
+fh-muenster.io
+
 // Filegear Inc. : https://www.filegear.com
 // Submitted by Jason Zhu <jason@owtware.com>
 filegear.me
@@ -11872,6 +11865,7 @@ usercontent.jp
 gentapps.com
 gentlentapis.com
 lab.ms
+cdn-edges.net
 
 // GitHub, Inc.
 // Submitted by Patrick Toomey <security@github.com>
@@ -11931,9 +11925,10 @@ pagespeedmobilizer.com
 publishproxy.com
 withgoogle.com
 withyoutube.com
-cloudfunctions.net
+*.gateway.dev
 cloud.goog
 translate.goog
+cloudfunctions.net
 
 blogspot.ae
 blogspot.al
@@ -12056,6 +12051,10 @@ ravendb.me
 development.run
 ravendb.run
 
+// Hong Kong Productivity Council: https://www.hkpc.org/
+// Submitted by SECaaS Team <summchan@hkpc.org>
+secaas.hk
+
 // HOSTBIP REGISTRY : https://www.hostbip.com/
 // Submitted by Atanunu Igbunuroghene <publicsuffixlist@hostbip.com>
 bpl.biz
@@ -12165,7 +12164,7 @@ iserv.dev
 // Submitted by Yuji Minagawa <domains-admin@iodata.jp>
 iobb.net
 
-//Jelastic, Inc. : https://jelastic.com/
+// Jelastic, Inc. : https://jelastic.com/
 // Submited by Ihor Kolodyuk <ik@jelastic.com>
 mel.cloudlets.com.au
 cloud.interhostsolutions.be
@@ -12180,6 +12179,9 @@ jele.cloud
 it1.eur.aruba.jenv-aruba.cloud
 it1.jenv-aruba.cloud
 it1-eur.jenv-arubabiz.cloud
+oxa.cloud
+tn.oxa.cloud
+uk.oxa.cloud
 primetel.cloud
 uk.primetel.cloud
 ca.reclaim.cloud
@@ -12250,6 +12252,7 @@ jelastic.regruhosting.ru
 enscaled.sg
 jele.site
 jelastic.team
+orangecloud.tn
 j.layershift.co.uk
 phx.enscaled.us
 mircloud.us
@@ -12327,10 +12330,6 @@ co.technology
 // Submitted by Greg Holland <greg.holland@lmpm.com>
 app.lmpm.com
 
-// Linki Tools UG : https://linki.tools
-// Submitted by Paulo Matos <pmatos@linki.tools>
-linkitools.space
-
 // linkyard ldt: https://www.linkyard.ch/
 // Submitted by Mario Siegenthaler <mario.siegenthaler@linkyard.ch>
 linkyard.cloud
@@ -12369,7 +12368,6 @@ swidnik.pl
 
 // Lug.org.uk : https://lug.org.uk
 // Submitted by Jon Spriggs <admin@lug.org.uk>
-uklugs.org
 glug.org.uk
 lug.org.uk
 lugs.org.uk
@@ -12446,11 +12444,17 @@ eu.meteorapp.com
 co.pl
 
 // Microsoft Corporation : http://microsoft.com
-// Submitted by Mostafa Elzeiny <moelzein@microsoft.com>
+// Submitted by Mitch Webster <miwebst@microsoft.com>
 *.azurecontainer.io
 azurewebsites.net
 azure-mobile.net
 cloudapp.net
+azurestaticapps.net
+centralus.azurestaticapps.net
+eastasia.azurestaticapps.net
+eastus2.azurestaticapps.net
+westeurope.azurestaticapps.net
+westus2.azurestaticapps.net
 
 // minion.systems : http://minion.systems
 // Submitted by Robert Böttinger <r@minion.systems>
@@ -12492,19 +12496,22 @@ cust.retrosnub.co.uk
 ui.nabu.casa
 
 // Names.of.London : https://names.of.london/
-// Submitted by James Stevens <registry@names.of.london> or <james@jrcs.net>
+// Submitted by James Stevens <registry[at]names.of.london> or 
<publiclist[at]jrcs.net>
 pony.club
 of.fashion
-on.fashion
-of.football
 in.london
 of.london
+from.marketing
+with.marketing
 for.men
+repair.men
 and.mom
 for.mom
 for.one
+under.one
 for.sale
-of.work
+that.win
+from.work
 to.work
 
 // NCTU.ME : https://nctu.me/
@@ -12824,6 +12831,12 @@ mypep.link
 // Submitted by Kenneth Van Alstyne <kvanalstyne@perspecta.com>
 perspecta.cloud
 
+// PE Ulyanov Kirill Sergeevich : https://airy.host
+// Submitted by Kirill Ulyanov <k.ulyanov@airy.host>
+lk3.ru
+ra-ru.ru
+zsew.ru
+
 // Planet-Work : https://www.planet-work.com/
 // Submitted by Frédéric VANNIÈRE <f.vanniere@planet-work.com>
 on-web.fr
@@ -12885,6 +12898,10 @@ byen.site
 // Submitted by Kor Nielsen <kor@pubtls.org>
 pubtls.org
 
+// QOTO, Org.
+// Submitted by Jeffrey Phillips Freeman <jeffrey.freeman@qoto.org>
+qoto.io
+
 // Qualifio : https://qualifio.com/
 // Submitted by Xavier De Cock <xdecock@gmail.com>
 qualifioapp.com
@@ -12970,7 +12987,6 @@ hzc.io
 // Revitalised Limited : http://www.revitalised.co.uk
 // Submitted by Jack Price <jack@revitalised.co.uk>
 wellbeingzone.eu
-ptplus.fit
 wellbeingzone.co.uk
 
 // Rochester Institute of Technology : http://www.rit.edu/
@@ -13344,7 +13360,7 @@ wafflecell.com
 // Submitted by Fajar Sodik <official@wapblog.id>
 idnblogger.com
 indowapblog.com
-bloghp.id
+bloger.id
 wblog.id
 wbq.me
 fastblog.net
diff --git a/lib-src/etags.c b/lib-src/etags.c
index 4315771..a1c6837 100644
--- a/lib-src/etags.c
+++ b/lib-src/etags.c
@@ -6063,6 +6063,7 @@ Erlang_functions (FILE *inf)
            {
              free (last);
              last = NULL;
+             allocated = lastlen = 0;
            }
        }
       else
diff --git a/lisp/apropos.el b/lisp/apropos.el
index 595db1d..97314cc 100644
--- a/lisp/apropos.el
+++ b/lisp/apropos.el
@@ -1225,8 +1225,8 @@ as a heading."
          (apropos-print-doc 6 'apropos-face t)
          (apropos-print-doc 5 'apropos-widget t)
          (apropos-print-doc 4 'apropos-plist nil))
-        (set (make-local-variable 'truncate-partial-width-windows) t)
-        (set (make-local-variable 'truncate-lines) t))))
+        (setq-local truncate-partial-width-windows t)
+        (setq-local truncate-lines t))))
   (prog1 apropos-accumulator
     (setq apropos-accumulator ())))    ; permit gc
 
diff --git a/lisp/array.el b/lisp/array.el
index 0d1ac74..0ad565b 100644
--- a/lisp/array.el
+++ b/lisp/array.el
@@ -863,25 +863,25 @@ Entering array mode calls the function `array-mode-hook'."
   (make-local-variable 'array-row)
   (make-local-variable 'array-column)
   (make-local-variable 'array-copy-string)
-  (set (make-local-variable 'array-respect-tabs) nil)
-  (set (make-local-variable 'array-max-row)
-       (read-number "Number of array rows: "))
-  (set (make-local-variable 'array-max-column)
-       (read-number "Number of array columns: "))
-  (set (make-local-variable 'array-columns-per-line)
-       (read-number "Array columns per line: "))
-  (set (make-local-variable 'array-field-width)
-       (read-number "Field width: "))
-  (set (make-local-variable 'array-rows-numbered)
-       (y-or-n-p "Rows numbered? "))
-  (set (make-local-variable 'array-line-length)
-       (* array-field-width array-columns-per-line))
-  (set (make-local-variable 'array-lines-per-row)
-       (+ (floor (1- array-max-column) array-columns-per-line)
-          (if array-rows-numbered 2 1)))
+  (setq-local array-respect-tabs nil)
+  (setq-local array-max-row
+              (read-number "Number of array rows: "))
+  (setq-local array-max-column
+              (read-number "Number of array columns: "))
+  (setq-local array-columns-per-line
+              (read-number "Array columns per line: "))
+  (setq-local array-field-width
+              (read-number "Field width: "))
+  (setq-local array-rows-numbered
+              (y-or-n-p "Rows numbered? "))
+  (setq-local array-line-length
+              (* array-field-width array-columns-per-line))
+  (setq-local array-lines-per-row
+              (+ (floor (1- array-max-column) array-columns-per-line)
+                 (if array-rows-numbered 2 1)))
   (message "")
   (force-mode-line-update)
-  (set (make-local-variable 'truncate-lines) t)
+  (setq-local truncate-lines t)
   (setq overwrite-mode 'overwrite-mode-textual))
 
 
diff --git a/lisp/battery.el b/lisp/battery.el
index e568ab5..f59ad12 100644
--- a/lisp/battery.el
+++ b/lisp/battery.el
@@ -661,10 +661,12 @@ Intended as a UPower PropertiesChanged signal handler."
   (cond ((stringp battery-upower-device)
          (list battery-upower-device))
         (battery-upower-device)
-        ((dbus-call-method :system battery-upower-service
-                           battery-upower-path
-                           battery-upower-interface
-                           "EnumerateDevices"))))
+        ((dbus-ignore-errors
+           (dbus-call-method :system battery-upower-service
+                             battery-upower-path
+                             battery-upower-interface
+                             "EnumerateDevices"
+                             :timeout 1000)))))
 
 (defun battery--upower-state (props state)
   "Merge the UPower battery state in PROPS with STATE.
diff --git a/lisp/buff-menu.el b/lisp/buff-menu.el
index d06ba28..5392519 100644
--- a/lisp/buff-menu.el
+++ b/lisp/buff-menu.el
@@ -269,8 +269,8 @@ In Buffer Menu mode, the following commands are defined:
 \\[revert-buffer]    Update the list of buffers.
 \\[Buffer-menu-toggle-files-only]    Toggle whether the menu displays only 
file buffers.
 \\[Buffer-menu-bury]    Bury the buffer listed on this line."
-  (set (make-local-variable 'buffer-stale-function)
-       (lambda (&optional _noconfirm) 'fast))
+  (setq-local buffer-stale-function
+              (lambda (&optional _noconfirm) 'fast))
   (add-hook 'tabulated-list-revert-hook 'list-buffers--refresh nil t))
 
 (defun buffer-menu (&optional arg)
diff --git a/lisp/button.el b/lisp/button.el
index ba06823..a6f7043 100644
--- a/lisp/button.el
+++ b/lisp/button.el
@@ -613,6 +613,20 @@ button at point is the button to describe."
       (button--describe props)
       t)))
 
+(defun button-buttonize (string callback &optional data)
+  "Make STRING into a button and return it.
+When clicked, CALLBACK will be called with the DATA as the
+function argument.  If DATA isn't present (or is nil), the button
+itself will be used instead as the function argument."
+  (propertize string
+              'face 'button
+              'button t
+              'follow-link t
+              'category t
+              'button-data data
+              'keymap button-map
+              'action callback))
+
 (provide 'button)
 
 ;;; button.el ends here
diff --git a/lisp/calc/calc-bin.el b/lisp/calc/calc-bin.el
index 60dd17e..6d93587 100644
--- a/lisp/calc/calc-bin.el
+++ b/lisp/calc/calc-bin.el
@@ -199,48 +199,16 @@
      (message "Omitting leading zeros on integers"))))
 
 
-(defvar math-power-of-2-cache (list 1 2 4 8 16 32 64 128 256 512 1024))
-(defvar math-big-power-of-2-cache nil)
 (defun math-power-of-2 (n)    ;  [I I] [Public]
-  (if (and (natnump n) (<= n 100))
-      (or (nth n math-power-of-2-cache)
-         (let* ((i (length math-power-of-2-cache))
-                (val (nth (1- i) math-power-of-2-cache)))
-           (while (<= i n)
-             (setq val (math-mul val 2)
-                   math-power-of-2-cache (nconc math-power-of-2-cache
-                                                (list val))
-                   i (1+ i)))
-           val))
-    (let ((found (assq n math-big-power-of-2-cache)))
-      (if found
-         (cdr found)
-       (let ((po2 (math-ipow 2 n)))
-         (setq math-big-power-of-2-cache
-               (cons (cons n po2) math-big-power-of-2-cache))
-         po2)))))
+  (if (natnump n)
+      (ash 1 n)
+    (error "argument must be a natural number")))
 
 (defun math-integer-log2 (n)    ; [I I] [Public]
-  (let ((i 0)
-       (p math-power-of-2-cache)
-       val)
-    (while (and p (Math-natnum-lessp (setq val (car p)) n))
-      (setq p (cdr p)
-           i (1+ i)))
-    (if p
-       (and (equal val n)
-            i)
-      (while (Math-natnum-lessp
-             (prog1
-                 (setq val (math-mul val 2))
-               (setq math-power-of-2-cache (nconc math-power-of-2-cache
-                                                  (list val))))
-             n)
-       (setq i (1+ i)))
-      (and (equal val n)
-          i))))
-
-
+  (and (natnump n)
+       (not (zerop n))
+       (zerop (logand n (1- n)))
+       (logb n)))
 
 
 ;;; Bitwise operations.
@@ -404,7 +372,7 @@
          (math-clip (calcFunc-ash a n (- w)) w)
        (if (Math-integer-negp a)
            (setq a (math-clip a w)))
-       (let ((two-to-sizem1 (math-power-of-2 (1- w)))
+       (let ((two-to-sizem1 (and (not (zerop w)) (math-power-of-2 (1- w))))
              (sh (calcFunc-lsh a n w)))
          (cond ((or (zerop w)
                      (zerop (logand a two-to-sizem1)))
@@ -438,7 +406,7 @@
       (if (Math-integer-negp a)
          (setq a (math-clip a w)))
       (cond ((or (Math-integer-negp n)
-                (not (Math-natnum-lessp n w)))
+                (>= n w))
             (calcFunc-rot a (math-mod n w) w))
            (t
             (math-add (calcFunc-lsh a (- n w) w)
@@ -455,7 +423,7 @@
         (math-reject-arg a 'integerp))
        ((< (or w (setq w calc-word-size)) 0)
         (setq a (math-clip a (- w)))
-        (if (Math-natnum-lessp a (math-power-of-2 (- -1 w)))
+        (if (< a (math-power-of-2 (- -1 w)))
             a
           (math-sub a (math-power-of-2 (- w)))))
         ((math-zerop w)
diff --git a/lisp/calc/calc-comb.el b/lisp/calc/calc-comb.el
index 5aeb8cb..0f6c40a 100644
--- a/lisp/calc/calc-comb.el
+++ b/lisp/calc/calc-comb.el
@@ -815,7 +815,7 @@
                   (error "Argument must be an integer"))
                  ((Math-integer-negp n)
                   '(nil))
-                 ((Math-natnum-lessp n 8000000)
+                 ((< n 8000000)
                   (let ((i -1) v)
                     (while (and (> (% n (setq v (aref math-primes-table
                                                       (setq i (1+ i)))))
@@ -913,7 +913,7 @@
   (if (Math-messy-integerp n)
       (setq n (math-trunc n)))
   (if (Math-natnump n)
-      (if (Math-natnum-lessp 2 n)
+      (if (< 2 n)
          (let (factors res p (i 0))
            (while (and (not (eq n 1))
                        (< i (length math-primes-table)))
@@ -927,7 +927,7 @@
                (setq factors (nconc factors (list p))
                      n (car res)))
              (or (eq n 1)
-                 (Math-natnum-lessp p (car res))
+                 (< p (car res))
                  (setq factors (nconc factors (list n))
                        n 1))
              (setq i (1+ i)))
@@ -946,7 +946,7 @@
   (if (Math-messy-integerp n)
       (setq n (math-trunc n)))
   (if (Math-natnump n)
-      (if (Math-natnum-lessp n 2)
+      (if (< n 2)
          (if (Math-negp n)
              (calcFunc-totient (math-abs n))
            n)
@@ -969,7 +969,7 @@
   (if (Math-messy-integerp n)
       (setq n (math-trunc n)))
   (if (and (Math-natnump n) (not (eq n 0)))
-      (if (Math-natnum-lessp n 2)
+      (if (< n 2)
          (if (Math-negp n)
              (calcFunc-moebius (math-abs n))
            1)
diff --git a/lisp/calc/calc-ext.el b/lisp/calc/calc-ext.el
index 4877fa6..7984c8b 100644
--- a/lisp/calc/calc-ext.el
+++ b/lisp/calc/calc-ext.el
@@ -2417,17 +2417,6 @@ If X is not an error form, return 1."
                (mapcar #'math-normalize (cdr a))))))
 
 
-;;; Normalize a bignum digit list by trimming high-end zeros.  [L l]
-(defun math-norm-bignum (a)
-  (let ((digs a) (last nil))
-    (while digs
-      (or (eq (car digs) 0) (setq last digs))
-      (setq digs (cdr digs)))
-    (and last
-        (progn
-          (setcdr last nil)
-          a))))
-
 ;;; Return 0 for zero, -1 for negative, 1 for positive.  [S n] [Public]
 (defun calcFunc-sign (a &optional x)
   (let ((signs (math-possible-signs a)))
@@ -2542,23 +2531,6 @@ If X is not an error form, return 1."
             0
           2))))
 
-;;; Compare two bignum digit lists, return -1 for A<B, 0 for A=B, 1 for A>B.
-(defun math-compare-bignum (a b)   ; [S l l]
-  (let ((res 0))
-    (while (and a b)
-      (if (< (car a) (car b))
-         (setq res -1)
-       (if (> (car a) (car b))
-           (setq res 1)))
-      (setq a (cdr a)
-           b (cdr b)))
-    (if a
-       (progn
-         (while (eq (car a) 0) (setq a (cdr a)))
-         (if a 1 res))
-      (while (eq (car b) 0) (setq b (cdr b)))
-      (if b -1 res))))
-
 (defun math-compare-lists (a b)
   (cond ((null a) (null b))
        ((null b) nil)
@@ -2685,7 +2657,7 @@ If X is not an error form, return 1."
         (if (Math-integer-negp a) (setq a (math-neg a)))
         (if (Math-integer-negp b) (setq b (math-neg b)))
         (let (c)
-          (if (Math-natnum-lessp a b)
+          (if (< a b)
               (setq c b b a a c))
           (while (and (consp a) (not (eq b 0)))
             (setq c b
diff --git a/lisp/calc/calc-funcs.el b/lisp/calc/calc-funcs.el
index 9ee86e7..fd544f9 100644
--- a/lisp/calc/calc-funcs.el
+++ b/lisp/calc/calc-funcs.el
@@ -410,7 +410,7 @@
    ((and (math-num-integerp b)
         (if (math-negp b)
             (math-reject-arg b 'range)
-          (Math-natnum-lessp (setq b (math-trunc b)) 20)))
+          (< (setq b (math-trunc b)) 20)))
     (and calc-symbolic-mode (or (math-floatp a) (math-floatp b))
         (math-inexact-result))
     (math-mul
@@ -427,7 +427,7 @@
    ((and (math-num-integerp a)
         (if (math-negp a)
             (math-reject-arg a 'range)
-          (Math-natnum-lessp (setq a (math-trunc a)) 20)))
+          (< (setq a (math-trunc a)) 20)))
     (math-sub (or math-current-beta-value (calcFunc-beta a b))
              (calcFunc-betaB (math-sub 1 x) b a)))
    (t
diff --git a/lisp/calc/calc-graph.el b/lisp/calc/calc-graph.el
index 829fa44..b694a82 100644
--- a/lisp/calc/calc-graph.el
+++ b/lisp/calc/calc-graph.el
@@ -351,7 +351,7 @@
         (if (>= ver 3)
             (insert "set surface\nset nocontour\n"
                     "set " (if calc-graph-is-splot "" "no") "parametric\n"
-                    "set notime\nset border\nset ztics\nset zeroaxis\n"
+                    "set notimestamp\nset border\nset ztics\nset zeroaxis\n"
                     "set view 60,30,1,1\nset offsets 0,0,0,0\n"))
         (setq samples-pos (point))
         (insert "\n\n" str))
diff --git a/lisp/calc/calc-macs.el b/lisp/calc/calc-macs.el
index 06ef3ef..a15095e 100644
--- a/lisp/calc/calc-macs.el
+++ b/lisp/calc/calc-macs.el
@@ -29,7 +29,6 @@
 (declare-function math-looks-negp "calc-misc" (a))
 (declare-function math-posp "calc-misc" (a))
 (declare-function math-compare "calc-ext" (a b))
-(declare-function math-compare-bignum "calc-ext" (a b))
 
 
 (defmacro calc-wrapper (&rest body)
@@ -174,13 +173,6 @@
           (eq (nth 1 a) b)
           (= (nth 2 a) 0))))
 
-(defsubst Math-natnum-lessp (a b)
-  (if (consp a)
-      (and (consp b)
-          (= (math-compare-bignum (cdr a) (cdr b)) -1))
-    (or (consp b)
-       (< a b))))
-
 (provide 'calc-macs)
 
 ;;; calc-macs.el ends here
diff --git a/lisp/calc/calc-math.el b/lisp/calc/calc-math.el
index 46172d1..1d0d94e 100644
--- a/lisp/calc/calc-math.el
+++ b/lisp/calc/calc-math.el
@@ -370,18 +370,6 @@ If this can't be done, return NIL."
       (math-isqrt (math-floor a))
     (math-floor (math-sqrt a))))
 
-(defun math-zerop-bignum (a)
-  (and (eq (car a) 0)
-       (progn
-        (while (eq (car (setq a (cdr a))) 0))
-        (null a))))
-
-(defun math-scale-bignum-digit-size (a n)   ; [L L S]
-  (while (> n 0)
-    (setq a (cons 0 a)
-         n (1- n)))
-  a)
-
 ;;; Compute the square root of a number.
 ;;; [T N] if possible, else [F N] if possible, else [C N].  [Public]
 (defun math-sqrt (a)
@@ -666,7 +654,7 @@ If this can't be done, return NIL."
   (let* ((q (math-idivmod a (math-ipow guess (1- math-nri-n))))
         (s (math-add (car q) (math-mul (1- math-nri-n) guess)))
         (g2 (math-idivmod s math-nri-n)))
-    (if (Math-natnum-lessp (car g2) guess)
+    (if (< (car g2) guess)
        (math-nth-root-int-iter a (car g2))
       (cons (and (equal (car g2) guess)
                 (eq (cdr q) 0)
@@ -1615,7 +1603,7 @@ If this can't be done, return NIL."
           (math-natnump b) (not (eq b 0)))
       (if (eq b 1)
          (math-reject-arg x "*Logarithm base one")
-       (if (Math-natnum-lessp x b)
+       (if (< x b)
            0
          (cdr (math-integer-log x b))))
     (math-floor (calcFunc-log x b))))
diff --git a/lisp/calc/calc.el b/lisp/calc/calc.el
index 9d869f3..bb02281 100644
--- a/lisp/calc/calc.el
+++ b/lisp/calc/calc.el
@@ -2100,7 +2100,7 @@ the United States."
           (set-buffer calc-trail-buffer)
           (unless (derived-mode-p 'calc-trail-mode)
              (calc-trail-mode)
-             (set (make-local-variable 'calc-main-buffer) buf)))))
+             (setq-local calc-main-buffer buf)))))
   (or (and calc-trail-pointer
           (eq (marker-buffer calc-trail-pointer) calc-trail-buffer))
       (with-current-buffer calc-trail-buffer
diff --git a/lisp/calc/calccomp.el b/lisp/calc/calccomp.el
index e4f6e98..0631eb4 100644
--- a/lisp/calc/calccomp.el
+++ b/lisp/calc/calccomp.el
@@ -1054,17 +1054,36 @@
                                         (nth 1 a)) 185))
              (calc-language 'flat)
              (low (and (nth 3 a) (math-compose-expr (nth 3 a) 0)))
-             (high (and (nth 4 a) (math-compose-expr (nth 4 a) 0))))
+             (high (and (nth 4 a) (math-compose-expr (nth 4 a) 0)))
+              ;; Check if we have Unicode integral top/bottom parts.
+              (fancy (and (char-displayable-p ?⌠)
+                          (char-displayable-p ?⌡)))
+              ;; If we do, find the most suitable middle part.
+              (fancy-stem (cond ((not fancy))
+                                ;; U+23AE INTEGRAL EXTENSION
+                                ((char-displayable-p ?⎮) "⎮ ")
+                                ;; U+2502 BOX DRAWINGS LIGHT VERTICAL
+                                ((char-displayable-p ?│) "│ ")
+                                ;; U+007C VERTICAL LINE
+                                (t "| "))))
         (list 'horiz
               (if parens "(" "")
-              (append (list 'vcent (if high 3 2))
-                      (and high (list (list 'horiz "  " high)))
-                      '("  /"
-                        " | "
-                        " | "
-                        " | "
-                        "/  ")
-                      (and low (list (list 'horiz low "  "))))
+              (append (list 'vcent (if fancy
+                                        (if high 2 1)
+                                      (if high 3 2)))
+                      (and high (list (if fancy
+                                           (list 'horiz high " ")
+                                         (list 'horiz "  " high))))
+                       (if fancy
+                           (list "⌠ " fancy-stem "⌡ ")
+                        '("  /"
+                          " | "
+                          " | "
+                          " | "
+                          "/  "))
+                      (and low (list (if fancy
+                                          (list 'horiz low " ")
+                                        (list 'horiz low "  ")))))
               expr
               (if over
                   ""
diff --git a/lisp/calendar/calendar.el b/lisp/calendar/calendar.el
index de9b1f3..d262b60 100644
--- a/lisp/calendar/calendar.el
+++ b/lisp/calendar/calendar.el
@@ -1788,7 +1788,7 @@ For a complete description, see the info node 
`Calendar/Diary'.
   (setq buffer-read-only t
         buffer-undo-list t
         indent-tabs-mode nil)
-  (set (make-local-variable 'scroll-margin) 0) ; bug#10379
+  (setq-local scroll-margin 0) ; bug#10379
   (calendar-update-mode-line)
   (make-local-variable 'calendar-mark-ring)
   (make-local-variable 'displayed-month) ; month in middle of window
diff --git a/lisp/calendar/diary-lib.el b/lisp/calendar/diary-lib.el
index fbc13f5..bf1e8eb 100644
--- a/lisp/calendar/diary-lib.el
+++ b/lisp/calendar/diary-lib.el
@@ -839,7 +839,7 @@ LIST-ONLY is non-nil, in which case it just returns the 
list."
                     (goto-char (point-min))
                     (unless list-only
                       (let ((ol (make-overlay (point-min) (point-max) nil t 
nil)))
-                        (set (make-local-variable 'diary-selective-display) t)
+                        (setq-local diary-selective-display t)
                         (overlay-put ol 'invisible 'diary)
                         (overlay-put ol 'evaporate t)))
                     (dotimes (_ number)
@@ -2381,10 +2381,9 @@ return a font-lock pattern matching array of MONTHS and 
marking SYMBOL."
 ;;;###autoload
 (define-derived-mode diary-mode fundamental-mode "Diary"
   "Major mode for editing the diary file."
-  (set (make-local-variable 'font-lock-defaults)
-       '(diary-font-lock-keywords t))
-  (set (make-local-variable 'comment-start) diary-comment-start)
-  (set (make-local-variable 'comment-end) diary-comment-end)
+  (setq-local font-lock-defaults '(diary-font-lock-keywords t))
+  (setq-local comment-start diary-comment-start)
+  (setq-local comment-end diary-comment-end)
   (add-to-invisibility-spec '(diary . nil))
   (add-hook 'after-save-hook #'diary-redraw-calendar nil t)
   ;; In case the file was modified externally, refresh the calendar
@@ -2465,13 +2464,13 @@ Fontify the region between BEG and END, quietly unless 
VERBOSE is non-nil."
 (define-derived-mode diary-fancy-display-mode special-mode
   "Diary"
   "Major mode used while displaying diary entries using Fancy Display."
-  (set (make-local-variable 'font-lock-defaults)
-       '(diary-fancy-font-lock-keywords
-         t nil nil nil
-         (font-lock-fontify-region-function
-          . diary-fancy-font-lock-fontify-region-function)))
-  (set (make-local-variable 'minor-mode-overriding-map-alist)
-       (list (cons t diary-fancy-overriding-map)))
+  (setq-local font-lock-defaults
+              '(diary-fancy-font-lock-keywords
+                t nil nil nil
+                (font-lock-fontify-region-function
+                 . diary-fancy-font-lock-fontify-region-function)))
+  (setq-local minor-mode-overriding-map-alist
+              (list (cons t diary-fancy-overriding-map)))
   (view-mode 1))
 
 ;; Following code from Dave Love <fx@gnu.org>.
diff --git a/lisp/chistory.el b/lisp/chistory.el
index c9aa927..98443bf 100644
--- a/lisp/chistory.el
+++ b/lisp/chistory.el
@@ -140,7 +140,7 @@ The buffer is left in Command History mode."
 Keybindings:
 \\{command-history-mode-map}"
   (lisp-mode-variables nil)
-  (set (make-local-variable 'revert-buffer-function) 'command-history-revert)
+  (setq-local revert-buffer-function 'command-history-revert)
   (set-syntax-table emacs-lisp-mode-syntax-table))
 
 (defcustom command-history-hook nil
diff --git a/lisp/comint.el b/lisp/comint.el
index 2873416..628a93d 100644
--- a/lisp/comint.el
+++ b/lisp/comint.el
@@ -1224,7 +1224,7 @@ Moves relative to START, or `comint-input-ring-index'."
        (process-mark (get-buffer-process (current-buffer))))
    (point-max)))
 
-(defun comint-previous-matching-input (regexp n)
+(defun comint-previous-matching-input (regexp n &optional restore)
   "Search backwards through input history for match for REGEXP.
 \(Previous history elements are earlier commands.)
 With prefix argument N, search for Nth previous match.
@@ -1235,16 +1235,24 @@ If N is negative, find the next or Nth next match."
     ;; Has a match been found?
     (if (null pos)
        (user-error "Not found")
-      ;; If leaving the edit line, save partial input
-      (if (null comint-input-ring-index)       ;not yet on ring
-         (setq comint-stored-incomplete-input
-               (funcall comint-get-old-input)))
-      (setq comint-input-ring-index pos)
-      (unless isearch-mode
-       (let ((message-log-max nil))    ; Do not write to *Messages*.
-         (message "History item: %d" (1+ pos))))
-      (comint-delete-input)
-      (insert (ring-ref comint-input-ring pos)))))
+      (if (and comint-input-ring-index
+               restore
+               (or (and (< n 0)
+                        (< comint-input-ring-index pos))
+                   (and (> n 0)
+                        (> comint-input-ring-index pos))))
+          ;; We have a wrap; restore contents.
+          (comint-restore-input)
+        ;; If leaving the edit line, save partial input
+        (if (null comint-input-ring-index) ;not yet on ring
+           (setq comint-stored-incomplete-input
+                 (funcall comint-get-old-input)))
+        (setq comint-input-ring-index pos)
+        (unless isearch-mode
+         (let ((message-log-max nil))  ; Do not write to *Messages*.
+           (message "History item: %d" (1+ pos))))
+        (comint-delete-input)
+        (insert (ring-ref comint-input-ring pos))))))
 
 (defun comint-next-matching-input (regexp n)
   "Search forwards through input history for match for REGEXP.
@@ -1272,7 +1280,7 @@ If N is negative, search forwards for the -Nth following 
match."
            comint-input-ring-index nil))
     (comint-previous-matching-input
      (concat "^" (regexp-quote comint-matching-input-from-input-string))
-     n)
+     n t)
     (when (eq comint-move-point-for-matching-input 'after-input)
       (goto-char opoint))))
 
diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el
index d3bbcb9..0e4a18c 100644
--- a/lisp/cus-edit.el
+++ b/lisp/cus-edit.el
@@ -2734,11 +2734,15 @@ try matching its doc string against 
`custom-guess-doc-alist'."
                 buttons)
           (insert " ")
           (let* ((format (widget-get type :format))
-                 tag-format value-format)
-            (unless (string-match ":" format)
+                  tag-format)
+             ;; We used to drop the widget tag when creating TYPE, passing
+             ;; everything after the colon (including whitespace characters
+             ;; after it) as the :format for TYPE.  We don't drop the tag
+             ;; anymore, but we should keep an immediate whitespace character,
+             ;; if present, and it's easier to do it here.
+             (unless (string-match ":\\s-?" format)
               (error "Bad format"))
             (setq tag-format (substring format 0 (match-end 0)))
-            (setq value-format (substring format (match-end 0)))
             (push (widget-create-child-and-convert
                    widget 'item
                    :format tag-format
@@ -2753,7 +2757,6 @@ try matching its doc string against 
`custom-guess-doc-alist'."
                   buttons)
             (push (widget-create-child-and-convert
                    widget type
-                   :format value-format
                    :value value)
                   children))))
     (unless (eq custom-buffer-style 'tree)
diff --git a/lisp/dabbrev.el b/lisp/dabbrev.el
index a9df031..c8bb749 100644
--- a/lisp/dabbrev.el
+++ b/lisp/dabbrev.el
@@ -45,7 +45,7 @@
 ;; dabbrev-case-replace                nil             t
 ;;
 ;; Set the variables you want special for your mode like this:
-;; (set (make-local-variable 'dabbrev-case-replace) nil)
+;; (setq-local dabbrev-case-replace nil)
 ;; Then you don't interfere with other modes.
 ;;
 ;; If your mode handles buffers that refers to other buffers
@@ -59,10 +59,10 @@
 
 ;; Example for GNUS (when we write a reply, we want dabbrev to look in
 ;; the article for expansion):
-;; (set (make-local-variable 'dabbrev-friend-buffer-function)
-;;      (lambda (buffer)
-;;         (with-current-buffer buffer
-;;           (memq major-mode '(news-reply-mode gnus-article-mode)))))
+;; (setq-local dabbrev-friend-buffer-function
+;;             (lambda (buffer)
+;;                (with-current-buffer buffer
+;;                  (memq major-mode '(news-reply-mode gnus-article-mode)))))
 
 
 ;; Known bugs and limitations.
diff --git a/lisp/desktop.el b/lisp/desktop.el
index 7a7f1d0..4be3303 100644
--- a/lisp/desktop.el
+++ b/lisp/desktop.el
@@ -1222,7 +1222,13 @@ This function is a no-op when Emacs is running in batch 
mode.
 It returns t if a desktop file was loaded, nil otherwise.
 \n(fn DIRNAME)"
   (interactive "i\nP")
-  (unless noninteractive
+  (if (or noninteractive
+          (and (desktop-owner)
+               (= (desktop-owner) (emacs-pid))))
+      (message "Not reloading the desktop%s"
+               (if noninteractive
+                   ""
+                 "; already loaded"))
     (setq desktop-dirname
           (file-name-as-directory
            (expand-file-name
diff --git a/lisp/dframe.el b/lisp/dframe.el
index 417477b..31e5714 100644
--- a/lisp/dframe.el
+++ b/lisp/dframe.el
@@ -280,7 +280,7 @@ CREATE-HOOK is a hook to run after creating a frame."
 
       ;; Enable mouse tracking in emacs
       (if dframe-track-mouse-function
-         (set (make-local-variable 'track-mouse) t)) ;this could be messy.
+          (setq-local track-mouse t)) ;this could be messy.
 
       ;; Override `temp-buffer-show-hook' so that help and such
       ;; put their stuff into a frame other than our own.
@@ -290,10 +290,8 @@ CREATE-HOOK is a hook to run after creating a frame."
          ;; FIXME: Doesn't this get us into an inf-loop when the
           ;; `temp-buffer-show-function' runs `temp-buffer-show-hook'
           ;; (as is normally the case)?
-         (progn (make-local-variable 'temp-buffer-show-hook)
-                (setq temp-buffer-show-hook temp-buffer-show-function)))
-      (make-local-variable 'temp-buffer-show-function)
-      (setq temp-buffer-show-function 'dframe-temp-buffer-show-function)
+          (setq-local temp-buffer-show-hook temp-buffer-show-function))
+      (setq-local temp-buffer-show-function 'dframe-temp-buffer-show-function)
       ;; If this buffer is killed, we must make sure that we destroy
       ;; the frame the dedicated window is in.
       (add-hook 'kill-buffer-hook (lambda ()
diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el
index 2615519..0f68b47 100644
--- a/lisp/dired-aux.el
+++ b/lisp/dired-aux.el
@@ -259,7 +259,7 @@ the string of command switches used as the third argument 
of `diff'."
      (list
       (minibuffer-with-setup-hook
          (lambda ()
-           (set (make-local-variable 'minibuffer-default-add-function) nil)
+            (setq-local minibuffer-default-add-function nil)
            (setq minibuffer-default defaults))
        (read-file-name (format-prompt "Diff %s with" default current)
                        target-dir default t))
@@ -334,7 +334,7 @@ only in the active region if `dired-mark-region' is 
non-nil."
           (defaults (dired-dwim-target-defaults nil target-dir)))
       (minibuffer-with-setup-hook
          (lambda ()
-           (set (make-local-variable 'minibuffer-default-add-function) nil)
+            (setq-local minibuffer-default-add-function nil)
            (setq minibuffer-default defaults))
        (read-directory-name (format "Compare %s with: "
                                     (dired-current-directory))
@@ -2049,7 +2049,7 @@ Optional arg HOW-TO determines how to treat the target.
         (target (expand-file-name ; fluid variable inside dired-create-files
                  (minibuffer-with-setup-hook
                      (lambda ()
-                       (set (make-local-variable 
'minibuffer-default-add-function) nil)
+                        (setq-local minibuffer-default-add-function nil)
                        (setq minibuffer-default defaults))
                    (dired-mark-read-file-name
                      (format "%s %%s %s: "
@@ -3013,14 +3013,14 @@ is part of a file name (i.e., has the text property 
`dired-filename')."
 (defun dired-isearch-filenames ()
   "Search for a string using Isearch only in file names in the Dired buffer."
   (interactive)
-  (set (make-local-variable 'dired-isearch-filenames) t)
+  (setq-local dired-isearch-filenames t)
   (isearch-forward nil t))
 
 ;;;###autoload
 (defun dired-isearch-filenames-regexp ()
   "Search for a regexp using Isearch only in file names in the Dired buffer."
   (interactive)
-  (set (make-local-variable 'dired-isearch-filenames) t)
+  (setq-local dired-isearch-filenames t)
   (isearch-forward-regexp nil t))
 
 
diff --git a/lisp/dired-x.el b/lisp/dired-x.el
index 55077e7..75e4f46 100644
--- a/lisp/dired-x.el
+++ b/lisp/dired-x.el
@@ -636,7 +636,7 @@ you can relist single subdirs using \\[dired-do-redisplay]."
   (dired-mode dirname (or switches dired-listing-switches))
   (setq mode-name "Virtual Dired"
         revert-buffer-function 'dired-virtual-revert)
-  (set (make-local-variable 'dired-subdir-alist) nil)
+  (setq-local dired-subdir-alist nil)
   (dired-build-subdir-alist)
   (goto-char (point-min))
   (dired-initial-position dirname))
@@ -1226,7 +1226,7 @@ Otherwise obeys the value of 
`dired-vm-read-only-folders'."
                              (and dired-vm-read-only-folders
                                   (not (file-writable-p fil)))))
     ;; So that pressing `v' inside VM does prompt within current directory:
-    (set (make-local-variable 'vm-folder-directory) dir)))
+    (setq-local vm-folder-directory dir)))
 
 (defun dired-rmail ()
   "Run RMAIL on this file."
diff --git a/lisp/dired.el b/lisp/dired.el
index 30b9f5b..c68c4a5 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -2419,6 +2419,10 @@ If the current buffer can be edited with Wdired, (i.e. 
the major
 mode is `dired-mode'), call `wdired-change-to-wdired-mode'.
 Otherwise, toggle `read-only-mode'."
   (interactive)
+  (when (and (not (file-writable-p default-directory))
+             (not (y-or-n-p
+                   "Directory isn't writable; edit anyway? ")))
+    (user-error "Directory %s isn't writable" default-directory))
   (if (derived-mode-p 'dired-mode)
       (wdired-change-to-wdired-mode)
     (read-only-mode 'toggle)))
@@ -2499,6 +2503,10 @@ directory in another window."
 (defun dired-find-file ()
   "In Dired, visit the file or directory named on this line."
   (interactive)
+  (dired--find-file #'find-file (dired-get-file-for-visit)))
+
+(defun dired--find-file (find-file-function file)
+  "Call FIND-FILE-FUNCTION on FILE, but bind some relevant variables."
   ;; Bind `find-file-run-dired' so that the command works on directories
   ;; too, independent of the user's setting.
   (let ((find-file-run-dired t)
@@ -2511,7 +2519,7 @@ directory in another window."
          (if dired-auto-revert-buffer
              nil
            switch-to-buffer-preserve-window-point)))
-    (find-file (dired-get-file-for-visit))))
+    (funcall find-file-function file)))
 
 (defun dired-find-alternate-file ()
   "In Dired, visit file or directory on current line via `find-alternate-file'.
@@ -2547,7 +2555,7 @@ respectively."
              (select-window window)
               (funcall find-dir-func file)))
       (select-window window)
-      (funcall find-file-func (file-name-sans-versions file t)))))
+      (dired--find-file find-file-func (file-name-sans-versions file t)))))
 
 (defun dired-mouse-find-file-other-window (event)
   "In Dired, visit the file or directory name you click on in another window."
@@ -2574,7 +2582,7 @@ Otherwise, display it in another buffer."
 (defun dired-find-file-other-window ()
   "In Dired, visit this file or directory in another window."
   (interactive)
-  (find-file-other-window (dired-get-file-for-visit)))
+  (dired--find-file #'find-file-other-window (dired-get-file-for-visit)))
 
 (defun dired-display-file ()
   "In Dired, display this file or directory in another window."
diff --git a/lisp/doc-view.el b/lisp/doc-view.el
index 9997c1a..f7a7be9 100644
--- a/lisp/doc-view.el
+++ b/lisp/doc-view.el
@@ -2055,7 +2055,7 @@ See the command `doc-view-mode' for more information on 
this mode."
   :init-value nil :keymap doc-view-presentation-mode-map
   (if doc-view-presentation-mode
       (progn
-        (set (make-local-variable 'mode-line-format) nil)
+        (setq-local mode-line-format nil)
         (doc-view-fit-page-to-window)
         ;; (doc-view-convert-all-pages)
         )
diff --git a/lisp/ebuff-menu.el b/lisp/ebuff-menu.el
index 079fce8..cf7b28a 100644
--- a/lisp/ebuff-menu.el
+++ b/lisp/ebuff-menu.el
@@ -202,8 +202,7 @@ Electric Buffer Menu mode is a minor mode which is 
automatically
 enabled and disabled by the \\[electric-buffer-list] command.
 See the documentation of `electric-buffer-list' for details."
   (setq mode-line-buffer-identification "Electric Buffer List")
-  (set (make-local-variable 'Helper-return-blurb)
-       "return to buffer editing"))
+  (setq-local Helper-return-blurb "return to buffer editing"))
 
 (define-obsolete-function-alias 'Electric-buffer-menu-mode
   'electric-buffer-menu-mode "24.3")
@@ -270,8 +269,8 @@ Return to Electric Buffer Menu when done."
   (when (derived-mode-p 'electric-buffer-menu-mode)
     ;; Make sure we have an overlay to use.
     (or electric-buffer-overlay
-       (set (make-local-variable 'electric-buffer-overlay)
-            (make-overlay (point) (point))))
+        (setq-local electric-buffer-overlay
+                    (make-overlay (point) (point))))
     (move-overlay electric-buffer-overlay
                  (line-beginning-position)
                  (line-end-position))
diff --git a/lisp/edmacro.el b/lisp/edmacro.el
index 44cf5aa..8ff766c 100644
--- a/lisp/edmacro.el
+++ b/lisp/edmacro.el
@@ -151,9 +151,9 @@ With a prefix argument, format the macro in a more concise 
way."
        (setq buffer-read-only nil)
        (setq major-mode 'edmacro-mode)
        (setq mode-name "Edit Macro")
-       (set (make-local-variable 'edmacro-original-buffer) oldbuf)
-       (set (make-local-variable 'edmacro-finish-hook) finish-hook)
-       (set (make-local-variable 'edmacro-store-hook) store-hook)
+        (setq-local edmacro-original-buffer oldbuf)
+        (setq-local edmacro-finish-hook finish-hook)
+        (setq-local edmacro-store-hook store-hook)
        (erase-buffer)
        (insert ";; Keyboard Macro Editor.  Press C-c C-c to finish; "
                "press C-x k RET to cancel.\n")
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index 0acd527..e23bb9f 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -144,7 +144,7 @@ is hard-coded in various places in Emacs.)"
   ;; Eg is_elc in Fload.
   :type 'regexp)
 
-(defcustom byte-compile-dest-file-function nil
+(defcustom byte-compile-dest-file-function #'byte-compile--default-dest-file
   "Function for the function `byte-compile-dest-file' to call.
 It should take one argument, the name of an Emacs Lisp source
 file name, and return the name of the compiled file.
@@ -177,14 +177,16 @@ function to do the work.  Otherwise, if FILENAME matches
 `emacs-lisp-file-regexp' (by default, files with the extension \".el\"),
 replaces the matching part (and anything after it) with \".elc\";
 otherwise adds \".elc\"."
-  (if byte-compile-dest-file-function
-      (funcall byte-compile-dest-file-function filename)
-    (setq filename (file-name-sans-versions
-                   (byte-compiler-base-file-name filename)))
-    (cond ((string-match emacs-lisp-file-regexp filename)
-          (concat (substring filename 0 (match-beginning 0)) ".elc"))
-         (t (concat filename ".elc")))))
-)
+  (funcall (or byte-compile-dest-file-function
+               #'byte-compile--default-dest-file)
+           filename)))
+
+(defun byte-compile--default-dest-file (filename)
+  (setq filename (file-name-sans-versions
+                 (byte-compiler-base-file-name filename)))
+  (cond ((string-match emacs-lisp-file-regexp filename)
+        (concat (substring filename 0 (match-beginning 0)) ".elc"))
+       (t (concat filename ".elc"))))
 
 ;; This can be the 'byte-compile property of any symbol.
 (autoload 'byte-compile-inline-expand "byte-opt")
@@ -1809,24 +1811,23 @@ If compilation is needed, this functions returns the 
result of
   (let ((dest (byte-compile-dest-file filename))
         ;; Expand now so we get the current buffer's defaults
         (filename (expand-file-name filename)))
-    (if (if (file-exists-p dest)
-            ;; File was already compiled
-            ;; Compile if forced to, or filename newer
-            (or force
-                (file-newer-than-file-p filename dest))
-          (and arg
-               (or (eq 0 arg)
-                   (y-or-n-p (concat "Compile "
-                                     filename "? ")))))
-        (progn
-          (if (and noninteractive (not byte-compile-verbose))
-              (message "Compiling %s..." filename))
-          (byte-compile-file filename)
-          (when load
-            (load (if (file-exists-p dest) dest filename))))
+    (prog1
+        (if (if (and dest (file-exists-p dest))
+                ;; File was already compiled
+                ;; Compile if forced to, or filename newer
+                (or force
+                    (file-newer-than-file-p filename dest))
+              (and arg
+                   (or (eq 0 arg)
+                       (y-or-n-p (concat "Compile "
+                                         filename "? ")))))
+            (progn
+              (if (and noninteractive (not byte-compile-verbose))
+                  (message "Compiling %s..." filename))
+              (byte-compile-file filename))
+         'no-byte-compile)
       (when load
-       (load (if (file-exists-p dest) dest filename)))
-      'no-byte-compile)))
+        (load (if (and dest (file-exists-p dest)) dest filename))))))
 
 (defun byte-compile--load-dynvars (file)
   (and file (not (equal file ""))
@@ -1936,7 +1937,7 @@ See also `emacs-lisp-byte-compile-and-load'."
          ;; (message "%s not compiled because of `no-byte-compile: %s'"
          ;;       (byte-compile-abbreviate-file filename)
          ;;       (with-current-buffer input-buffer no-byte-compile))
-         (when (file-exists-p target-file)
+         (when (and target-file (file-exists-p target-file))
            (message "%s deleted because of `no-byte-compile: %s'"
                     (byte-compile-abbreviate-file target-file)
                     (buffer-local-value 'no-byte-compile input-buffer))
@@ -1960,36 +1961,50 @@ See also `emacs-lisp-byte-compile-and-load'."
        (with-current-buffer output-buffer
          (goto-char (point-max))
          (insert "\n")                 ; aaah, unix.
-         (if (file-writable-p target-file)
-             ;; We must disable any code conversion here.
-             (progn
-               (let* ((coding-system-for-write 'no-conversion)
-                      ;; Write to a tempfile so that if another Emacs
-                      ;; process is trying to load target-file (eg in a
-                      ;; parallel bootstrap), it does not risk getting a
-                      ;; half-finished file.  (Bug#4196)
-                      (tempfile
-                       (make-temp-file (expand-file-name target-file)))
-                      (default-modes (default-file-modes))
-                      (temp-modes (logand default-modes #o600))
-                      (desired-modes (logand default-modes #o666))
-                      (kill-emacs-hook
-                       (cons (lambda () (ignore-errors
-                                          (delete-file tempfile)))
-                             kill-emacs-hook)))
-                 (unless (= temp-modes desired-modes)
-                   (set-file-modes tempfile desired-modes 'nofollow))
-                 (write-region (point-min) (point-max) tempfile nil 1)
-                 ;; This has the intentional side effect that any
-                 ;; hard-links to target-file continue to
-                 ;; point to the old file (this makes it possible
-                 ;; for installed files to share disk space with
-                 ;; the build tree, without causing problems when
-                 ;; emacs-lisp files in the build tree are
-                 ;; recompiled).  Previously this was accomplished by
-                 ;; deleting target-file before writing it.
-                 (rename-file tempfile target-file t))
-               (or noninteractive (message "Wrote %s" target-file)))
+         (cond
+          ((null target-file) nil)     ;We only wanted the warnings!
+          ((and (file-writable-p target-file)
+                 ;; We attempt to create a temporary file in the
+                 ;; target directory, so the target directory must be
+                 ;; writable.
+                 (file-writable-p (file-name-directory target-file)))
+           ;; We must disable any code conversion here.
+           (let* ((coding-system-for-write 'no-conversion)
+                  ;; Write to a tempfile so that if another Emacs
+                  ;; process is trying to load target-file (eg in a
+                  ;; parallel bootstrap), it does not risk getting a
+                  ;; half-finished file.  (Bug#4196)
+                  (tempfile
+                   (make-temp-file (expand-file-name target-file)))
+                  (default-modes (default-file-modes))
+                  (temp-modes (logand default-modes #o600))
+                  (desired-modes (logand default-modes #o666))
+                  (kill-emacs-hook
+                   (cons (lambda () (ignore-errors
+                                 (delete-file tempfile)))
+                         kill-emacs-hook)))
+             (unless (= temp-modes desired-modes)
+               (set-file-modes tempfile desired-modes 'nofollow))
+             (write-region (point-min) (point-max) tempfile nil 1)
+             ;; This has the intentional side effect that any
+             ;; hard-links to target-file continue to
+             ;; point to the old file (this makes it possible
+             ;; for installed files to share disk space with
+             ;; the build tree, without causing problems when
+             ;; emacs-lisp files in the build tree are
+             ;; recompiled).  Previously this was accomplished by
+             ;; deleting target-file before writing it.
+             (rename-file tempfile target-file t))
+           (or noninteractive (message "Wrote %s" target-file)))
+           ((file-writable-p target-file)
+            ;; In case the target directory isn't writable (see e.g. 
Bug#44631),
+            ;; try writing to the output file directly.  We must disable any
+            ;; code conversion here.
+            (let ((coding-system-for-write 'no-conversion))
+              (with-file-modes (logand (default-file-modes) #o666)
+                (write-region (point-min) (point-max) target-file nil 1)))
+            (or noninteractive (message "Wrote %s" target-file)))
+          (t
            ;; This is just to give a better error message than write-region
            (let ((exists (file-exists-p target-file)))
              (signal (if exists 'file-error 'file-missing)
@@ -1997,7 +2012,7 @@ See also `emacs-lisp-byte-compile-and-load'."
                            (if exists
                                "Cannot overwrite file"
                              "Directory not writable or nonexistent")
-                           target-file))))
+                           target-file)))))
          (kill-buffer (current-buffer)))
        (if (and byte-compile-generate-call-tree
                 (or (eq t byte-compile-generate-call-tree)
diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el
index 02da07d..b37b05b 100644
--- a/lisp/emacs-lisp/cl-generic.el
+++ b/lisp/emacs-lisp/cl-generic.el
@@ -410,8 +410,18 @@ the specializer used will be the one returned by BODY."
 ;;;###autoload
 (defmacro cl-defmethod (name args &rest body)
   "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.
+This it defines an implementation of NAME to use for invocations
+of specific types of arguments.
+
+ARGS is a list of dispatch arguments (see `cl-defun'), but where
+each variable element is either just a single variable name VAR,
+or a list on the form (VAR TYPE).
+
+For instance:
+
+  (cl-defmethod foo (bar (format-string string) &optional zot)
+    (format format-string bar))
+
 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
diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el
index d81060e..6a97684 100644
--- a/lisp/emacs-lisp/eldoc.el
+++ b/lisp/emacs-lisp/eldoc.el
@@ -467,7 +467,6 @@ This holds the results of the last documentation request."
 
 (defun eldoc--format-doc-buffer (docs)
   "Ensure DOCS are displayed in an *eldoc* buffer."
-  (interactive (list t))
   (with-current-buffer (if (buffer-live-p eldoc--doc-buffer)
                            eldoc--doc-buffer
                          (setq eldoc--doc-buffer
diff --git a/lisp/emacs-lisp/elint.el b/lisp/emacs-lisp/elint.el
index ef97c82..79b72ff 100644
--- a/lisp/emacs-lisp/elint.el
+++ b/lisp/emacs-lisp/elint.el
@@ -558,7 +558,8 @@ Return nil if there are no more forms, t otherwise."
     (when . elint-check-conditional-form)
     (unless . elint-check-conditional-form)
     (and . elint-check-conditional-form)
-    (or . elint-check-conditional-form))
+    (or . elint-check-conditional-form)
+    (require . elint-require-form))
   "Functions to call when some special form should be linted.")
 
 (defun elint-form (form env &optional nohandler)
@@ -953,6 +954,13 @@ Does basic handling of `featurep' tests."
           (elint-form form env t))))
   env)
 
+(defun elint-require-form (form _env)
+  "Load `require'd files."
+  (pcase form
+    (`(require ',x)
+     (require x)))
+  nil)
+
 ;;;
 ;;; Message functions
 ;;;
diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el
index 5f29c26..25237fe 100644
--- a/lisp/emacs-lisp/ert.el
+++ b/lisp/emacs-lisp/ert.el
@@ -274,7 +274,7 @@ DATA is displayed to the user and should state the reason 
for skipping."
 It should only be stopped when ran from inside ert--run-test-internal."
   (when (and (not (symbolp debugger))   ; only run on anonymous debugger
              (memq error-symbol '(ert-test-failed ert-test-skipped)))
-    (funcall debugger 'error data)))
+    (funcall debugger 'error (list error-symbol data))))
 
 (defun ert--special-operator-p (thing)
   "Return non-nil if THING is a symbol naming a special operator."
diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el
index 081ef8d..e477ef1 100644
--- a/lisp/emacs-lisp/lisp-mode.el
+++ b/lisp/emacs-lisp/lisp-mode.el
@@ -38,7 +38,7 @@
 (define-abbrev-table 'lisp-mode-abbrev-table ()
   "Abbrev table for Lisp mode.")
 
-(defvar lisp--mode-syntax-table
+(defvar lisp-data-mode-syntax-table
   (let ((table (make-syntax-table))
         (i 0))
     (while (< i ?0)
@@ -77,11 +77,13 @@
     (modify-syntax-entry ?\\ "\\   " table)
     (modify-syntax-entry ?\( "()  " table)
     (modify-syntax-entry ?\) ")(  " table)
+    (modify-syntax-entry ?\[ "(]" table)
+    (modify-syntax-entry ?\] ")[" table)
     table)
   "Parent syntax table used in Lisp modes.")
 
 (defvar lisp-mode-syntax-table
-  (let ((table (make-syntax-table lisp--mode-syntax-table)))
+  (let ((table (make-syntax-table lisp-data-mode-syntax-table)))
     (modify-syntax-entry ?\[ "_   " table)
     (modify-syntax-entry ?\] "_   " table)
     (modify-syntax-entry ?# "' 14" table)
@@ -669,7 +671,7 @@ font-lock keywords will not be case sensitive."
 (define-derived-mode lisp-data-mode prog-mode "Lisp-Data"
   "Major mode for buffers holding data written in Lisp syntax."
   :group 'lisp
-  (lisp-mode-variables t t nil)
+  (lisp-mode-variables nil t nil)
   (setq-local electric-quote-string t)
   (setq imenu-case-fold-search nil))
 
diff --git a/lisp/emacs-lisp/memory-report.el b/lisp/emacs-lisp/memory-report.el
new file mode 100644
index 0000000..04ae87d
--- /dev/null
+++ b/lisp/emacs-lisp/memory-report.el
@@ -0,0 +1,303 @@
+;;; memory-report.el --- Short function summaries  -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020 Free Software Foundation, Inc.
+
+;; Keywords: lisp, help
+
+;; 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:
+
+;; Todo (possibly): Font cache, regexp cache, bidi cache, various
+;; buffer caches (newline cache, free_region_cache, etc), composition
+;; cache, face cache.
+
+;;; Code:
+
+(require 'seq)
+(require 'subr-x)
+(eval-when-compile (require 'cl-lib))
+
+(defvar memory-report--type-size (make-hash-table))
+
+;;;###autoload
+(defun memory-report ()
+  "Generate a report of how Emacs is using memory.
+
+This report is approximate, and will commonly over-count memory
+usage by variables, because shared data structures will usually
+by counted more than once."
+  (interactive)
+  (pop-to-buffer "*Memory Report*")
+  (special-mode)
+  (button-mode 1)
+  (setq truncate-lines t)
+  (message "Gathering data...")
+  (let ((reports (append (memory-report--garbage-collect)
+                         (memory-report--image-cache)
+                         (memory-report--buffers)
+                         (memory-report--largest-variables)))
+        (inhibit-read-only t)
+        summaries details)
+    (message "Gathering data...done")
+    (erase-buffer)
+    (insert (propertize "Estimated Emacs Memory Usage\n\n" 'face 'bold))
+    (dolist (report reports)
+      (if (listp report)
+          (push report summaries)
+        (push report details)))
+    (dolist (summary (seq-sort (lambda (e1 e2)
+                                 (> (cdr e1) (cdr e2)))
+                               summaries))
+      (insert (format "%s  %s\n"
+                      (memory-report--format (cdr summary))
+                      (car summary))))
+    (insert "\n")
+    (dolist (detail (nreverse details))
+      (insert detail "\n")))
+  (goto-char (point-min)))
+
+(defun memory-report-object-size (object)
+  "Return the size of OBJECT in bytes."
+  (unless memory-report--type-size
+    (memory-report--garbage-collect))
+  (memory-report--object-size (make-hash-table :test #'eq) object))
+
+(defun memory-report--size (type)
+  (or (gethash type memory-report--type-size)
+      (gethash 'object memory-report--type-size)))
+
+(defun memory-report--set-size (elems)
+  (setf (gethash 'string memory-report--type-size)
+        (cadr (assq 'strings elems)))
+  (setf (gethash 'cons memory-report--type-size)
+        (cadr (assq 'conses elems)))
+  (setf (gethash 'symbol memory-report--type-size)
+        (cadr (assq 'symbols elems)))
+  (setf (gethash 'object memory-report--type-size)
+        (cadr (assq 'vectors elems)))
+  (setf (gethash 'float memory-report--type-size)
+        (cadr (assq 'floats elems)))
+  (setf (gethash 'buffer memory-report--type-size)
+        (cadr (assq 'buffers elems))))
+
+(defun memory-report--garbage-collect ()
+  (let ((elems (garbage-collect)))
+    (memory-report--set-size elems)
+    (let ((data (list
+                 (list 'strings
+                       (+ (memory-report--gc-elem elems 'strings)
+                          (memory-report--gc-elem elems 'string-bytes)))
+                 (list 'vectors
+                       (+ (memory-report--gc-elem elems 'vectors)
+                          (memory-report--gc-elem elems 'vector-slots)))
+                 (list 'floats (memory-report--gc-elem elems 'floats))
+                 (list 'conses (memory-report--gc-elem elems 'conses))
+                 (list 'symbols (memory-report--gc-elem elems 'symbols))
+                 (list 'intervals (memory-report--gc-elem elems 'intervals))
+                 (list 'buffer-objects
+                       (memory-report--gc-elem elems 'buffers)))))
+      (list (cons "Overall Object Memory Usage"
+                  (seq-reduce #'+ (mapcar (lambda (elem)
+                                            (* (nth 1 elem) (nth 2 elem)))
+                                          elems)
+                              0))
+            (cons "Reserved (But Unused) Object Memory"
+                  (seq-reduce #'+ (mapcar (lambda (elem)
+                                            (if (nth 3 elem)
+                                                (* (nth 1 elem) (nth 3 elem))
+                                              0))
+                                          elems)
+                              0))
+            (with-temp-buffer
+              (insert (propertize "Object Storage\n\n" 'face 'bold))
+              (dolist (object (seq-sort (lambda (e1 e2)
+                                          (> (cadr e1) (cadr e2)))
+                                        data))
+                (insert (format "%s  %s\n"
+                                (memory-report--format (cadr object))
+                                (capitalize (symbol-name (car object))))))
+              (buffer-string))))))
+
+(defun memory-report--largest-variables ()
+  (let ((variables nil))
+    (mapatoms
+     (lambda (symbol)
+       (when (boundp symbol)
+         (let ((size (memory-report--object-size
+                      (make-hash-table :test #'eq)
+                      (symbol-value symbol))))
+           (when (> size 1000)
+             (push (cons symbol size) variables)))))
+     obarray)
+    (list
+     (cons (propertize "Memory Used By Global Variables"
+                       'help-echo "Upper bound; mutually overlapping data from 
different variables are counted several times")
+           (seq-reduce #'+ (mapcar #'cdr variables) 0))
+     (with-temp-buffer
+       (insert (propertize "Largest Variables\n\n" 'face 'bold))
+       (cl-loop for i from 1 upto 20
+                for (symbol . size) in (seq-sort (lambda (e1 e2)
+                                                   (> (cdr e1) (cdr e2)))
+                                                 variables)
+                do (insert (memory-report--format size)
+                           "  "
+                           (symbol-name symbol)
+                           "\n"))
+       (buffer-string)))))
+
+(defun memory-report--object-size (counted value)
+  (if (gethash value counted)
+      0
+    (setf (gethash value counted) t)
+    (memory-report--object-size-1 counted value)))
+
+(cl-defgeneric memory-report--object-size-1 (_counted _value)
+  0)
+
+(cl-defmethod memory-report--object-size-1 (_ (value symbol))
+  ;; Don't count global symbols -- makes sizes of lists of symbols too
+  ;; heavey.
+  (if (intern-soft value obarray)
+      0
+    (memory-report--size 'symbol)))
+
+(cl-defmethod memory-report--object-size-1 (_ (_value buffer))
+  (memory-report--size 'buffer))
+
+(cl-defmethod memory-report--object-size-1 (counted (value string))
+  (+ (memory-report--size 'string)
+     (string-bytes value)
+     (memory-report--interval-size counted (object-intervals value))))
+
+(defun memory-report--interval-size (counted intervals)
+  ;; We get a list back of intervals, but only count the "inner list"
+  ;; (i.e., the actual text properties), and add the size of the
+  ;; intervals themselves.
+  (+ (* (memory-report--size 'interval) (length intervals))
+     (seq-reduce #'+ (mapcar
+                      (lambda (interval)
+                        (memory-report--object-size counted (nth 2 interval)))
+                      intervals)
+                 0)))
+
+(cl-defmethod memory-report--object-size-1 (counted (value list))
+  (let ((total 0)
+        (size (memory-report--size 'cons)))
+    (while value
+      (cl-incf total size)
+      (setf (gethash value counted) t)
+      (when (car value)
+        (cl-incf total (memory-report--object-size counted (car value))))
+      (if (cdr value)
+          (if (consp (cdr value))
+              (setq value (cdr value))
+            (cl-incf total (memory-report--object-size counted (cdr value)))
+            (setq value nil))
+        (setq value nil)))
+    total))
+
+(cl-defmethod memory-report--object-size-1 (counted (value vector))
+  (let ((total (+ (memory-report--size 'vector)
+                  (* (memory-report--size 'object) (length value)))))
+    (cl-loop for elem across value
+             do (setf (gethash elem counted) t)
+             (cl-incf total (memory-report--object-size counted elem)))
+    total))
+
+(cl-defmethod memory-report--object-size-1 (counted (value hash-table))
+  (let ((total (+ (memory-report--size 'vector)
+                  (* (memory-report--size 'object) (hash-table-size value)))))
+    (maphash
+     (lambda (key elem)
+       (setf (gethash key counted) t)
+       (setf (gethash elem counted) t)
+       (cl-incf total (memory-report--object-size counted key))
+       (cl-incf total (memory-report--object-size counted elem)))
+     value)
+    total))
+
+(defun memory-report--format (bytes)
+  (setq bytes (/ bytes 1024.0))
+  (let ((units '("kB" "MB" "GB" "TB")))
+    (while (>= bytes 1024)
+      (setq bytes (/ bytes 1024.0))
+      (setq units (cdr units)))
+    (format "%6.1f%s" bytes (car units))))
+
+(defun memory-report--gc-elem (elems type)
+  (* (nth 1 (assq type elems))
+     (nth 2 (assq type elems))))
+
+(defun memory-report--buffers ()
+  (let ((buffers (mapcar (lambda (buffer)
+                           (cons buffer (memory-report--buffer buffer)))
+                         (buffer-list))))
+    (list (cons "Total Buffer Memory Usage"
+                (seq-reduce #'+ (mapcar #'cdr buffers) 0))
+          (with-temp-buffer
+            (insert (propertize "Largest Buffers\n\n" 'face 'bold))
+            (cl-loop for i from 1 upto 20
+                     for (buffer . size) in (seq-sort (lambda (e1 e2)
+                                                        (> (cdr e1) (cdr e2)))
+                                                      buffers)
+                     do (insert (memory-report--format size)
+                                "  "
+                                (button-buttonize
+                                 (buffer-name buffer)
+                                 #'memory-report--buffer-details buffer)
+                                "\n"))
+            (buffer-string)))))
+
+(defun memory-report--buffer-details (buffer)
+  (with-current-buffer buffer
+    (apply
+     #'message
+     "Buffer text: %s; variables: %s; text properties: %s; overlays: %s"
+     (mapcar #'string-trim (mapcar #'memory-report--format
+                                   (memory-report--buffer-data buffer))))))
+
+(defun memory-report--buffer (buffer)
+  (seq-reduce #'+ (memory-report--buffer-data buffer) 0))
+
+(defun memory-report--buffer-data (buffer)
+  (with-current-buffer buffer
+    (list (save-restriction
+            (widen)
+            (+ (position-bytes (point-max))
+              (- (position-bytes (point-min)))
+              (gap-size)))
+          (seq-reduce #'+ (mapcar (lambda (elem)
+                                    (if (cdr elem)
+                                        (memory-report--object-size
+                                         (make-hash-table :test #'eq)
+                                         (cdr elem))
+                                      0))
+                                  (buffer-local-variables buffer))
+                      0)
+          (memory-report--object-size (make-hash-table :test #'eq)
+                                      (object-intervals buffer))
+          (memory-report--object-size (make-hash-table :test #'eq)
+                                      (overlay-lists)))))
+
+(defun memory-report--image-cache ()
+  (list (cons "Total Image Cache Size" (if (fboundp 'image-cache-size)
+                                           (image-cache-size)
+                                         0))))
+
+(provide 'memory-report)
+
+;;; memory-report.el ends here
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index 9c37ce4..b7c48df 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -1115,14 +1115,15 @@ boundaries."
     ;; Use some headers we've invented to drive the process.
     (let* (;; Prefer Package-Version; if defined, the package author
            ;; probably wants us to use it.  Otherwise try Version.
-           (pkg-version
-            (or (package-strip-rcs-id (lm-header "package-version"))
-                (package-strip-rcs-id (lm-header "version"))))
+           (version-info
+            (or (lm-header "package-version") (lm-header "version")))
+           (pkg-version (package-strip-rcs-id version-info))
            (keywords (lm-keywords-list))
            (homepage (lm-homepage)))
       (unless pkg-version
-        (error
-            "Package lacks a \"Version\" or \"Package-Version\" header"))
+         (if version-info
+             (error "Unrecognized package version: %s" version-info)
+           (error "Package lacks a \"Version\" or \"Package-Version\" 
header")))
       (package-desc-from-define
        file-name pkg-version desc
        (and-let* ((require-lines (lm-header-multiline "package-requires")))
@@ -2112,7 +2113,10 @@ Otherwise return nil."
   (when str
     (when (string-match "\\`[ \t]*[$]Revision:[ \t]+" str)
       (setq str (substring str (match-end 0))))
-    (if (version-to-list str) str)))
+    (let ((l (version-to-list str)))
+      ;; Don't return `str' but (package-version-join (version-to-list str))
+      ;; to make sure we use a "canonical name"!
+      (if l (package-version-join l)))))
 
 (declare-function lm-homepage "lisp-mnt" (&optional file))
 
diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el
index e603900..206f0dd 100644
--- a/lisp/emacs-lisp/pcase.el
+++ b/lisp/emacs-lisp/pcase.el
@@ -409,7 +409,8 @@ of the elements of LIST is performed as if by `pcase-let'.
       (dolist (case cases)
         (unless (or (memq case used-cases)
                     (memq (car case) pcase--dontwarn-upats))
-          (message "Redundant pcase pattern: %S" (car case))))
+          (message "pcase pattern %S shadowed by previous pcase pattern"
+                   (car case))))
       (macroexp-let* defs main))))
 
 (defun pcase--macroexpand (pat)
diff --git a/lisp/emacs-lisp/thunk.el b/lisp/emacs-lisp/thunk.el
index c8e483e..cd42152 100644
--- a/lisp/emacs-lisp/thunk.el
+++ b/lisp/emacs-lisp/thunk.el
@@ -122,7 +122,7 @@ Using `thunk-let' and `thunk-let*' requires 
`lexical-binding'."
   (declare (indent 1) (debug let))
   (cl-reduce
    (lambda (expr binding) `(thunk-let (,binding) ,expr))
-   (nreverse bindings)
+   (reverse bindings)
    :initial-value (macroexp-progn body)))
 
 ;; (defalias 'lazy-let  #'thunk-let)
diff --git a/lisp/emulation/edt.el b/lisp/emulation/edt.el
index b29ad77..f61de92 100644
--- a/lisp/emulation/edt.el
+++ b/lisp/emulation/edt.el
@@ -788,7 +788,7 @@ Argument NUM is the number of lines to delete."
 In select mode, selected text is highlighted."
   (if arg
       (progn
-       (set (make-local-variable 'edt-select-mode) 'edt-select-mode-current)
+        (setq-local edt-select-mode 'edt-select-mode-current)
        (setq rect-start-point (window-point)))
     (progn
       (kill-local-variable 'edt-select-mode)))
diff --git a/lisp/emulation/viper-cmd.el b/lisp/emulation/viper-cmd.el
index dd7648c..938ebb1 100644
--- a/lisp/emulation/viper-cmd.el
+++ b/lisp/emulation/viper-cmd.el
@@ -474,7 +474,7 @@
 
 ;; Modifies mode-line-buffer-identification.
 (defun viper-refresh-mode-line ()
-  (set (make-local-variable 'viper-mode-string)
+  (setq-local viper-mode-string
        (cond ((eq viper-current-state 'emacs-state) viper-emacs-state-id)
              ((eq viper-current-state 'vi-state) viper-vi-state-id)
              ((eq viper-current-state 'replace-state) viper-replace-state-id)
@@ -1865,14 +1865,10 @@ Undo previous insertion and inserts new."
     ;; minibuffer and vice versa. Otherwise, command arguments will affect
     ;; minibuffer ops and insertions from the minibuffer will change those in
     ;; the normal buffers
-    (make-local-variable 'viper-d-com)
-    (make-local-variable 'viper-last-insertion)
-    (make-local-variable 'viper-command-ring)
-    (setq viper-d-com nil
-         viper-last-insertion nil
-         viper-command-ring nil)
-    (funcall hook)
-    ))
+    (setq-local viper-d-com nil)
+    (setq-local viper-last-insertion nil)
+    (setq-local viper-command-ring nil)
+    (funcall hook)))
 
 ;; This is a temp hook that uses free variables viper--init-message and 
viper-initial.
 ;; A dirty feature, but it is the simplest way to have it do the right thing.
diff --git a/lisp/emulation/viper.el b/lisp/emulation/viper.el
index 59ca629..8510928 100644
--- a/lisp/emulation/viper.el
+++ b/lisp/emulation/viper.el
@@ -617,7 +617,7 @@ This startup message appears whenever you load Viper, 
unless you type `y' now."
 
 ;; This hook designed to enable Vi-style editing in comint-based modes."
 (defun viper-comint-mode-hook ()
-  (set (make-local-variable 'require-final-newline) nil)
+  (setq-local require-final-newline nil)
   (setq viper-ex-style-editing nil
        viper-ex-style-motion nil)
   (viper-change-state-to-insert))
diff --git a/lisp/epa-file.el b/lisp/epa-file.el
index 7fd4178..21dc1eb 100644
--- a/lisp/epa-file.el
+++ b/lisp/epa-file.el
@@ -309,7 +309,8 @@ encryption is used."
 If no one is selected, symmetric encryption will be performed.  "
                    recipients)
                 (if epa-file-encrypt-to
-                    (epg-list-keys context recipients)))))
+                     (epg--filter-revoked-keys
+                     (epg-list-keys context recipients))))))
       (error
        (epa-display-error context)
        (if (setq entry (assoc file epa-file-passphrase-alist))
diff --git a/lisp/epg.el b/lisp/epg.el
index 920b853..b27e2c6 100644
--- a/lisp/epg.el
+++ b/lisp/epg.el
@@ -1382,6 +1382,13 @@ NAME is either a string or a list of strings."
       (setq pointer (cdr pointer)))
     keys))
 
+(defun epg--filter-revoked-keys (keys)
+  (seq-remove (lambda (key)
+                (seq-find (lambda (user)
+                            (eq (epg-user-id-validity user) 'revoked))
+                          (epg-key-user-id-list key)))
+              keys))
+
 (defun epg--args-from-sig-notations (notations)
   (apply #'nconc
         (mapcar
diff --git a/lisp/face-remap.el b/lisp/face-remap.el
index 4ccd463..13bbb52 100644
--- a/lisp/face-remap.el
+++ b/lisp/face-remap.el
@@ -446,7 +446,7 @@ local, and sets it to FACE."
     (setq specs (car specs)))
   (if (null specs)
       (buffer-face-mode 0)
-    (set (make-local-variable 'buffer-face-mode-face) specs)
+    (setq-local buffer-face-mode-face specs)
     (buffer-face-mode t)))
 
 ;;;###autoload
@@ -470,7 +470,7 @@ buffer local, and set it to SPECS."
   (if (or (null specs)
          (and buffer-face-mode (equal buffer-face-mode-face specs)))
       (buffer-face-mode 0)
-    (set (make-local-variable 'buffer-face-mode-face) specs)
+    (setq-local buffer-face-mode-face specs)
     (buffer-face-mode t)))
 
 (defun buffer-face-mode-invoke (specs arg &optional interactive)
diff --git a/lisp/files.el b/lisp/files.el
index 2cf77d5..093b5f9 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -597,7 +597,7 @@ settings being applied, but still respect file-local ones.")
 
 ;; This is an odd variable IMO.
 ;; You might wonder why it is needed, when we could just do:
-;; (set (make-local-variable 'enable-local-variables) nil)
+;; (setq-local enable-local-variables nil)
 ;; These two are not precisely the same.
 ;; Setting this variable does not cause -*- mode settings to be
 ;; ignored, whereas setting enable-local-variables does.
@@ -2419,9 +2419,7 @@ Do you want to revisit the file normally now? ")))
       ;; this is a permanent local, the major mode won't eliminate it.
       (and backup-enable-predicate
           (not (funcall backup-enable-predicate buffer-file-name))
-          (progn
-            (make-local-variable 'backup-inhibited)
-            (setq backup-inhibited t)))
+           (setq-local backup-inhibited t))
       (if rawfile
          (progn
            (set-buffer-multibyte nil)
@@ -3520,7 +3518,7 @@ n  -- to ignore the local variables list.")
          (let ((print-escape-newlines t))
            (prin1 (cdr elt) buf))
          (insert "\n"))
-       (set (make-local-variable 'cursor-type) nil)
+        (setq-local cursor-type nil)
        (set-buffer-modified-p nil)
        (goto-char (point-min)))
 
@@ -4492,9 +4490,7 @@ the old visited file has been renamed to the new name 
FILENAME."
     (and buffer-file-name
         backup-enable-predicate
         (not (funcall backup-enable-predicate buffer-file-name))
-        (progn
-          (make-local-variable 'backup-inhibited)
-          (setq backup-inhibited t)))
+         (setq-local backup-inhibited t))
     (let ((oauto buffer-auto-save-file-name))
       (cond ((null filename)
             (setq buffer-auto-save-file-name nil))
@@ -6123,6 +6119,9 @@ This undoes all changes since the file was visited or 
saved.
 With a prefix argument, offer to revert from latest auto-save file, if
 that is more recent than the visited file.
 
+Reverting a buffer will try to preserve markers in the buffer;
+see the Info node `(elisp)Reverting' for details.
+
 This command also implements an interface for special buffers
 that contain text that doesn't come from a file, but reflects
 some other data instead (e.g. Dired buffers, `buffer-list'
@@ -6219,7 +6218,7 @@ Non-file buffers need a custom function."
                ;; Run after-revert-hook as it was before we reverted.
                (setq-default revert-buffer-internal-hook global-hook)
                (if local-hook
-                   (set (make-local-variable 'revert-buffer-internal-hook)
+                   (setq-local revert-buffer-internal-hook
                         local-hook)
                  (kill-local-variable 'revert-buffer-internal-hook))
                (run-hooks 'revert-buffer-internal-hook))
diff --git a/lisp/filesets.el b/lisp/filesets.el
index 883871c..62dc5a5 100644
--- a/lisp/filesets.el
+++ b/lisp/filesets.el
@@ -1336,8 +1336,7 @@ Use the viewer defined in EV-ENTRY (a valid element of
              (progn
                (switch-to-buffer (format "Filesets: %s %s" vwr file))
                (insert output)
-               (make-local-variable 'filesets-output-buffer-flag)
-               (setq filesets-output-buffer-flag t)
+                (setq-local filesets-output-buffer-flag t)
                (set-visited-file-name file t)
                (when oh
                  (run-hooks 'oh))
diff --git a/lisp/find-dired.el b/lisp/find-dired.el
index 18330d8..d2b82bd 100644
--- a/lisp/find-dired.el
+++ b/lisp/find-dired.el
@@ -223,11 +223,10 @@ it finishes, type \\[kill-find]."
       (set-keymap-parent map (current-local-map))
       (define-key map "\C-c\C-k" 'kill-find)
       (use-local-map map))
-    (make-local-variable 'dired-sort-inhibit)
-    (setq dired-sort-inhibit t)
-    (set (make-local-variable 'revert-buffer-function)
-        `(lambda (ignore-auto noconfirm)
-           (find-dired ,dir ,find-args)))
+    (setq-local dired-sort-inhibit t)
+    (setq-local revert-buffer-function
+                `(lambda (ignore-auto noconfirm)
+                   (find-dired ,dir ,find-args)))
     ;; Set subdir-alist so that Tree Dired will work:
     (if (fboundp 'dired-simple-subdir-alist)
        ;; will work even with nested dired format (dired-nstd.el,v 1.15
@@ -235,9 +234,9 @@ it finishes, type \\[kill-find]."
        (dired-simple-subdir-alist)
       ;; else we have an ancient tree dired (or classic dired, where
       ;; this does no harm)
-      (set (make-local-variable 'dired-subdir-alist)
-          (list (cons default-directory (point-min-marker)))))
-    (set (make-local-variable 'dired-subdir-switches) find-ls-subdir-switches)
+      (setq-local dired-subdir-alist
+                  (list (cons default-directory (point-min-marker)))))
+    (setq-local dired-subdir-switches find-ls-subdir-switches)
     (setq buffer-read-only nil)
     ;; Subdir headlerline must come first because the first marker in
     ;; subdir-alist points there.
diff --git a/lisp/find-lisp.el b/lisp/find-lisp.el
index c1be5ff..44a2e6d 100644
--- a/lisp/find-lisp.el
+++ b/lisp/find-lisp.el
@@ -212,21 +212,17 @@ It is a function which takes two arguments, the directory 
and its parent."
 
     (use-local-map (append (make-sparse-keymap) (current-local-map)))
 
-    (make-local-variable 'find-lisp-file-predicate)
-    (setq find-lisp-file-predicate file-predicate)
-    (make-local-variable 'find-lisp-directory-predicate)
-    (setq find-lisp-directory-predicate directory-predicate)
-    (make-local-variable 'find-lisp-regexp)
-    (setq find-lisp-regexp regexp)
-
-    (make-local-variable 'revert-buffer-function)
-    (setq revert-buffer-function
-          (lambda (_ignore1 _ignore2)
-            (find-lisp-insert-directory
-             default-directory
-             find-lisp-file-predicate
-             find-lisp-directory-predicate
-             'ignore)))
+    (setq-local find-lisp-file-predicate file-predicate)
+    (setq-local find-lisp-directory-predicate directory-predicate)
+    (setq-local find-lisp-regexp regexp)
+
+    (setq-local revert-buffer-function
+                (lambda (_ignore1 _ignore2)
+                  (find-lisp-insert-directory
+                   default-directory
+                   find-lisp-file-predicate
+                   find-lisp-directory-predicate
+                   'ignore)))
 
     ;; Set subdir-alist so that Tree Dired will work:
     (if (fboundp 'dired-simple-subdir-alist)
@@ -235,8 +231,8 @@ It is a function which takes two arguments, the directory 
and its parent."
        (dired-simple-subdir-alist)
       ;; else we have an ancient tree dired (or classic dired, where
       ;; this does no harm)
-      (set (make-local-variable 'dired-subdir-alist)
-          (list (cons default-directory (point-min-marker)))))
+      (setq-local dired-subdir-alist
+                  (list (cons default-directory (point-min-marker)))))
     (find-lisp-insert-directory
      dir file-predicate directory-predicate 'ignore)
     (goto-char (point-min))
diff --git a/lisp/finder.el b/lisp/finder.el
index a59a185..98859f6 100644
--- a/lisp/finder.el
+++ b/lisp/finder.el
@@ -448,7 +448,7 @@ FILE should be in a form suitable for passing to 
`locate-library'."
   :syntax-table finder-mode-syntax-table
   (setq buffer-read-only t
        buffer-undo-list t)
-  (set (make-local-variable 'finder-headmark) nil))
+  (setq-local finder-headmark nil))
 
 (defun finder-summary ()
   "Summarize basic Finder commands."
diff --git a/lisp/font-core.el b/lisp/font-core.el
index 098253e..1b15d8c 100644
--- a/lisp/font-core.el
+++ b/lisp/font-core.el
@@ -160,8 +160,8 @@ this function onto `change-major-mode-hook'."
 (defun font-lock-default-function (mode)
   ;; Turn on Font Lock mode.
   (when mode
-    (set (make-local-variable 'char-property-alias-alist)
-        (copy-tree char-property-alias-alist))
+    (setq-local char-property-alias-alist
+                (copy-tree char-property-alias-alist))
     ;; Add `font-lock-face' as an alias for the `face' property.
     (let ((elt (assq 'face char-property-alias-alist)))
       (if elt
@@ -171,8 +171,8 @@ this function onto `change-major-mode-hook'."
   ;; Turn off Font Lock mode.
   (unless mode
     ;; Remove `font-lock-face' as an alias for the `face' property.
-    (set (make-local-variable 'char-property-alias-alist)
-        (copy-tree char-property-alias-alist))
+    (setq-local char-property-alias-alist
+                (copy-tree char-property-alias-alist))
     (let ((elt (assq 'face char-property-alias-alist)))
       (when elt
        (setcdr elt (remq 'font-lock-face (cdr elt)))
diff --git a/lisp/font-lock.el b/lisp/font-lock.el
index e708e69..0e771e8 100644
--- a/lisp/font-lock.el
+++ b/lisp/font-lock.el
@@ -152,8 +152,8 @@
 ;;
 ;;  (add-hook 'foo-mode-hook
 ;;   (lambda ()
-;;     (set (make-local-variable 'font-lock-defaults)
-;;          '(foo-font-lock-keywords t))))
+;;     (setq-local font-lock-defaults
+;;                 '(foo-font-lock-keywords t))))
 
 ;;;; Adding Font Lock support for modes:
 
@@ -173,8 +173,8 @@
 ;;
 ;; and within `bar-mode' there could be:
 ;;
-;;  (set (make-local-variable 'font-lock-defaults)
-;;       '(bar-font-lock-keywords nil t))
+;;  (setq-local font-lock-defaults
+;;              '(bar-font-lock-keywords nil t))
 
 ;; What is fontification for?  You might say, "It's to make my code look nice."
 ;; I think it should be for adding information in the form of cues.  These cues
@@ -733,7 +733,7 @@ see the variables `c-font-lock-extra-types', 
`c++-font-lock-extra-types',
            ;; font-lock-mode it only enabled the font-core.el part, not the
            ;; font-lock-mode-internal.  Try again.
            (font-lock-mode -1)
-           (set (make-local-variable 'font-lock-defaults) '(nil t))
+           (setq-local font-lock-defaults '(nil t))
            (font-lock-mode 1))
         ;; Otherwise set or add the keywords now.
         ;; This is a no-op if it has been done already in this buffer
@@ -933,18 +933,15 @@ The value of this variable is used when Font Lock mode is 
turned on."
      ;; Prepare for jit-lock
      (remove-hook 'after-change-functions
                   #'font-lock-after-change-function t)
-     (set (make-local-variable 'font-lock-flush-function)
-          #'jit-lock-refontify)
-     (set (make-local-variable 'font-lock-ensure-function)
-          #'jit-lock-fontify-now)
+     (setq-local font-lock-flush-function #'jit-lock-refontify)
+     (setq-local font-lock-ensure-function #'jit-lock-fontify-now)
      ;; Prevent font-lock-fontify-buffer from fontifying eagerly the whole
      ;; buffer.  This is important for things like CWarn mode which
      ;; adds/removes a few keywords and does a refontify (which takes ages on
      ;; large files).
-     (set (make-local-variable 'font-lock-fontify-buffer-function)
-          #'jit-lock-refontify)
+     (setq-local font-lock-fontify-buffer-function #'jit-lock-refontify)
      ;; Don't fontify eagerly (and don't abort if the buffer is large).
-     (set (make-local-variable 'font-lock-fontified) t)
+     (setq-local font-lock-fontified t)
      ;; Use jit-lock.
      (jit-lock-register #'font-lock-fontify-region
                         (not font-lock-keywords-only))
@@ -1558,7 +1555,7 @@ START should be at the beginning of a line."
   (unless parse-sexp-lookup-properties
     ;; We wouldn't go through so much trouble if we didn't intend to use those
     ;; properties, would we?
-    (set (make-local-variable 'parse-sexp-lookup-properties) t))
+    (setq-local parse-sexp-lookup-properties t))
   ;; If `font-lock-syntactic-keywords' is a symbol, get the real keywords.
   (when (symbolp font-lock-syntactic-keywords)
     (setq font-lock-syntactic-keywords (font-lock-eval-keywords
@@ -1942,8 +1939,8 @@ Sets various variables using `font-lock-defaults' and
        (set (make-local-variable (car x)) (cdr x)))
       ;; Set up `font-lock-keywords' last because its value might depend
       ;; on other settings.
-      (set (make-local-variable 'font-lock-keywords)
-          (font-lock-eval-keywords keywords))
+      (setq-local font-lock-keywords
+                  (font-lock-eval-keywords keywords))
       ;; Local fontification?
       (while local
        (font-lock-add-keywords nil (car (car local)) (cdr (car local)))
diff --git a/lisp/format.el b/lisp/format.el
index 905ca2d..16456eb 100644
--- a/lisp/format.el
+++ b/lisp/format.el
@@ -237,9 +237,8 @@ For most purposes, consider using `format-encode-region' 
instead."
                   ;; delete the buffer once the write is done, but do
                   ;; it after running to-fn so it doesn't affect
                   ;; write-region calls in to-fn.
-                  (set (make-local-variable
-                        'write-region-post-annotation-function)
-                       'kill-buffer)))
+                  (setq-local write-region-post-annotation-function
+                              #'kill-buffer)))
              nil)
          ;; Otherwise just call function, it will return annotations.
          (funcall to-fn from to orig-buf)))))
diff --git a/lisp/gnus/gnus-agent.el b/lisp/gnus/gnus-agent.el
index 053e7ea..d6802a3 100644
--- a/lisp/gnus/gnus-agent.el
+++ b/lisp/gnus/gnus-agent.el
@@ -454,7 +454,7 @@ manipulated as follows:
                                      (symbol-name major-mode))
                        (match-string 1 (symbol-name major-mode))))
         (mode (intern (format "gnus-agent-%s-mode" buffer))))
-    (set (make-local-variable 'gnus-agent-mode) t)
+    (setq-local gnus-agent-mode t)
     (set mode nil)
     (set (make-local-variable mode) t)
     ;; Set up the menu.
@@ -1056,8 +1056,8 @@ article's mark is toggled."
 (defun gnus-agent-get-undownloaded-list ()
   "Construct list of articles that have not been downloaded."
   (let ((gnus-command-method (gnus-find-method-for-group gnus-newsgroup-name)))
-    (when (set (make-local-variable 'gnus-newsgroup-agentized)
-               (gnus-agent-method-p gnus-command-method))
+    (when (setq-local gnus-newsgroup-agentized
+                      (gnus-agent-method-p gnus-command-method))
       (let* ((alist (gnus-agent-load-alist gnus-newsgroup-name))
              (headers (sort (mapcar (lambda (h)
                                       (mail-header-number h))
@@ -1440,7 +1440,7 @@ downloaded into the agent."
     (let ((file (gnus-agent-lib-file "history")))
       (when (file-exists-p file)
        (nnheader-insert-file-contents file))
-      (set (make-local-variable 'gnus-agent-file-name) file))))
+      (setq-local gnus-agent-file-name file))))
 
 (defun gnus-agent-close-history ()
   (when (gnus-buffer-live-p gnus-agent-current-history)
diff --git a/lisp/gnus/gnus-art.el b/lisp/gnus/gnus-art.el
index 7f594c9..5b50bcb 100644
--- a/lisp/gnus/gnus-art.el
+++ b/lisp/gnus/gnus-art.el
@@ -3850,8 +3850,7 @@ This format is defined by the `gnus-article-time-format' 
variable."
   (unless gnus-article-emphasis-alist
     (let ((name (and gnus-newsgroup-name
                     (gnus-group-real-name gnus-newsgroup-name))))
-      (make-local-variable 'gnus-article-emphasis-alist)
-      (setq gnus-article-emphasis-alist
+      (setq-local gnus-article-emphasis-alist
            (nconc
             (let ((alist gnus-group-highlight-words-alist) elem highlight)
               (while (setq elem (pop alist))
@@ -4495,10 +4494,10 @@ commands:
   (when (gnus-visual-p 'article-menu 'menu)
     (gnus-article-make-menu-bar)
     (when gnus-summary-tool-bar-map
-      (set (make-local-variable 'tool-bar-map) gnus-summary-tool-bar-map)))
+      (setq-local tool-bar-map gnus-summary-tool-bar-map)))
   (gnus-update-format-specifications nil 'article-mode)
-  (set (make-local-variable 'page-delimiter) gnus-page-delimiter)
-  (set (make-local-variable 'gnus-page-broken) nil)
+  (setq-local page-delimiter gnus-page-delimiter)
+  (setq-local gnus-page-broken nil)
   (make-local-variable 'gnus-article-current-summary)
   (make-local-variable 'gnus-article-mime-handles)
   (make-local-variable 'gnus-article-decoded-p)
@@ -4507,13 +4506,12 @@ commands:
   (make-local-variable 'gnus-article-image-alist)
   (make-local-variable 'gnus-article-charset)
   (make-local-variable 'gnus-article-ignored-charsets)
-  (set (make-local-variable 'bookmark-make-record-function)
-       'gnus-summary-bookmark-make-record)
+  (setq-local bookmark-make-record-function 'gnus-summary-bookmark-make-record)
   ;; Prevent Emacs from displaying non-break space with
   ;; `nobreak-space' face.
-  (set (make-local-variable 'nobreak-char-display) nil)
+  (setq-local nobreak-char-display nil)
   ;; Enable `gnus-article-remove-images' to delete images shr.el renders.
-  (set (make-local-variable 'shr-put-image-function) 'gnus-shr-put-image)
+  (setq-local shr-put-image-function 'gnus-shr-put-image)
   (unless gnus-article-show-cursor
     (setq cursor-in-non-selected-windows nil))
   (gnus-set-default-directory)
@@ -4557,7 +4555,7 @@ commands:
                 t)))
        (let ((summary gnus-summary-buffer))
          (with-current-buffer name
-           (set (make-local-variable 'gnus-article-edit-mode) nil)
+            (setq-local gnus-article-edit-mode nil)
            (gnus-article-stop-animations)
            (when gnus-article-mime-handles
              (mm-destroy-parts gnus-article-mime-handles)
@@ -4568,14 +4566,14 @@ commands:
            (setq buffer-read-only t)
            (unless (derived-mode-p 'gnus-article-mode)
              (gnus-article-mode))
-           (set (make-local-variable 'gnus-summary-buffer) summary)
+            (setq-local gnus-summary-buffer summary)
            (setq truncate-lines gnus-article-truncate-lines)
            (current-buffer)))
       (let ((summary gnus-summary-buffer))
        (with-current-buffer (gnus-get-buffer-create name)
          (gnus-article-mode)
          (setq truncate-lines gnus-article-truncate-lines)
-         (set (make-local-variable 'gnus-summary-buffer) summary)
+          (setq-local gnus-summary-buffer summary)
          (gnus-summary-set-local-parameters gnus-newsgroup-name)
          (when article-lapsed-timer
            (gnus-stop-date-timer))
@@ -5036,7 +5034,7 @@ and `gnus-mime-delete-part', and not provided at run-time 
normally."
          (setq gnus-article-mime-handles nil)
          (let ((mbl1 mml-buffer-list))
            (setq mml-buffer-list mbl)
-           (set (make-local-variable 'mml-buffer-list) mbl1))
+            (setq-local mml-buffer-list mbl1))
          (add-hook 'kill-buffer-hook 'mml-destroy-buffers t t)))
      `(lambda (no-highlight)
        (let ((mail-parse-charset (or gnus-article-charset
@@ -6902,8 +6900,8 @@ then we display only bindings that start with that 
prefix."
        (setq draft gnus-draft-mode)))
     (with-temp-buffer
       (use-local-map keymap)
-      (set (make-local-variable 'gnus-agent-summary-mode) agent)
-      (set (make-local-variable 'gnus-draft-mode) draft)
+      (setq-local gnus-agent-summary-mode agent)
+      (setq-local gnus-draft-mode draft)
       (describe-bindings prefix))
     (let ((item `((lambda (prefix)
                    (with-current-buffer ,(current-buffer)
@@ -7247,10 +7245,9 @@ This is an extended text-mode.
 \\{gnus-article-edit-mode-map}"
   (make-local-variable 'gnus-article-edit-done-function)
   (make-local-variable 'gnus-prev-winconf)
-  (set (make-local-variable 'font-lock-defaults)
-       '(message-font-lock-keywords t))
-  (set (make-local-variable 'mail-header-separator) "")
-  (set (make-local-variable 'gnus-article-edit-mode) t)
+  (setq-local font-lock-defaults '(message-font-lock-keywords t))
+  (setq-local mail-header-separator "")
+  (setq-local gnus-article-edit-mode t)
   (mml-mode)
   (setq buffer-read-only nil)
   (buffer-enable-undo)
diff --git a/lisp/gnus/gnus-cus.el b/lisp/gnus/gnus-cus.el
index f0c4d07..d832d0e 100644
--- a/lisp/gnus/gnus-cus.el
+++ b/lisp/gnus/gnus-cus.el
@@ -49,18 +49,15 @@ if that value is non-nil."
   ;; Emacs stuff:
   (when (and (facep 'custom-button-face)
             (facep 'custom-button-pressed-face))
-    (set (make-local-variable 'widget-button-face)
-        'custom-button-face)
-    (set (make-local-variable 'widget-button-pressed-face)
-        'custom-button-pressed-face)
-    (set (make-local-variable 'widget-mouse-face)
-        'custom-button-pressed-face))
+    (setq-local widget-button-face 'custom-button-face)
+    (setq-local widget-button-pressed-face 'custom-button-pressed-face)
+    (setq-local widget-mouse-face 'custom-button-pressed-face))
   (when (and (boundp 'custom-raised-buttons)
             (symbol-value 'custom-raised-buttons))
-    (set (make-local-variable 'widget-push-button-prefix) "")
-    (set (make-local-variable 'widget-push-button-suffix) "")
-    (set (make-local-variable 'widget-link-prefix) "")
-    (set (make-local-variable 'widget-link-suffix) "")))
+    (setq-local widget-push-button-prefix "")
+    (setq-local widget-push-button-suffix "")
+    (setq-local widget-link-prefix "")
+    (setq-local widget-link-suffix "")))
 
 ;;; Group Customization:
 
@@ -380,10 +377,8 @@ category."))
     (gnus-kill-buffer "*Gnus Customize*")
     (switch-to-buffer (gnus-get-buffer-create "*Gnus Customize*"))
     (gnus-custom-mode)
-    (make-local-variable 'gnus-custom-group)
-    (setq gnus-custom-group group)
-    (make-local-variable 'gnus-custom-topic)
-    (setq gnus-custom-topic topic)
+    (setq-local gnus-custom-group group)
+    (setq-local gnus-custom-topic topic)
     (buffer-disable-undo)
     (widget-insert "Customize the ")
     (if group
@@ -848,8 +843,7 @@ This can be changed using the 
`\\[gnus-score-change-score-file]' command."
     (kill-buffer (gnus-get-buffer-create "*Gnus Customize*"))
     (switch-to-buffer (gnus-get-buffer-create "*Gnus Customize*"))
     (gnus-custom-mode)
-    (make-local-variable 'gnus-custom-score-alist)
-    (setq gnus-custom-score-alist scores)
+    (setq-local gnus-custom-score-alist scores)
     (widget-insert "Customize the ")
     (widget-create 'info-link
                   :help-echo "Push me to learn more."
@@ -867,8 +861,7 @@ Check the [ ] for the entries you want to apply to this 
score file, then
 edit the value to suit your taste.  Don't forget to mark the checkbox,
 if you do all your changes will be lost.  ")
     (widget-insert "\n\n")
-    (make-local-variable 'gnus-custom-scores)
-    (setq gnus-custom-scores
+    (setq-local gnus-custom-scores
          (widget-create 'group
                         :value scores
                         `(checklist :inline t
@@ -1052,10 +1045,9 @@ articles in the thread.
          "\n    Note: Empty fields default to the customizable global\
  variables.\n\n")
 
-        (set (make-local-variable 'gnus-agent-cat-name)
-             name))
+        (setq-local gnus-agent-cat-name name))
 
-      (set (make-local-variable 'category-fields) nil)
+      (setq-local category-fields nil)
       (gnus-agent-cat-prepare-category-field agent-predicate)
 
       (gnus-agent-cat-prepare-category-field agent-score)
diff --git a/lisp/gnus/gnus-group.el b/lisp/gnus/gnus-group.el
index 73fda66..24534a1 100644
--- a/lisp/gnus/gnus-group.el
+++ b/lisp/gnus/gnus-group.el
@@ -1098,7 +1098,7 @@ When FORCE, rebuild the tool bar."
                                        gnus-group-tool-bar-zap-list
                                        'gnus-group-mode-map)))
       (if map
-         (set (make-local-variable 'tool-bar-map) map))))
+         (setq-local tool-bar-map map))))
   gnus-group-tool-bar-map)
 
 (define-derived-mode gnus-group-mode gnus-mode "Group"
@@ -1745,7 +1745,8 @@ already.  If INFO-UNCHANGED is non-nil, dribble buffer is 
not updated."
        (prog1
            (setq mode-line-buffer-identification
                  (gnus-mode-line-buffer-identification
-                  (list mode-string)))
+                  (list (propertize mode-string
+                                    'face 'mode-line-buffer-id))))
          (set-buffer-modified-p modified))))))
 
 (defun gnus-group-group-name ()
diff --git a/lisp/gnus/gnus-msg.el b/lisp/gnus/gnus-msg.el
index 465871e..3733bab 100644
--- a/lisp/gnus/gnus-msg.el
+++ b/lisp/gnus/gnus-msg.el
@@ -464,8 +464,7 @@ only affect the Gcc copy, but not the original message."
         (gnus-inews-add-send-actions ,winconf ,buffer ,oarticle ,config
                                      ,yanked ,winconf-name)
         (setq gnus-message-buffer (current-buffer))
-        (set (make-local-variable 'gnus-message-group-art)
-             (cons ,group ,article))
+         (setq-local gnus-message-group-art (cons ,group ,article))
          ;; Enable highlighting of different citation levels
          (when gnus-message-highlight-citation
            (gnus-message-citation-mode 1))
@@ -473,7 +472,7 @@ only affect the Gcc copy, but not the original message."
          (if (eq major-mode 'message-mode)
              (let ((mbl1 mml-buffer-list))
                (setq mml-buffer-list mbl)  ;; Global value
-               (set (make-local-variable 'mml-buffer-list) mbl1);; Local value
+               (setq-local mml-buffer-list mbl1) ;; Local value
                (add-hook 'change-major-mode-hook 'mml-destroy-buffers nil t)
                (add-hook 'kill-buffer-hook 'mml-destroy-buffers t t))
            (mml-destroy-buffers)
@@ -724,10 +723,10 @@ network.  The corresponding back end must have a 
`request-post' method."
          (gnus-setup-message 'message
            (progn
              (message-news (gnus-group-real-name gnus-newsgroup-name))
-             (set (make-local-variable 'gnus-discouraged-post-methods)
-                  (remove
-                   (car (gnus-find-method-for-group gnus-newsgroup-name))
-                   gnus-discouraged-post-methods)))))))))
+              (setq-local gnus-discouraged-post-methods
+                          (remove
+                           (car (gnus-find-method-for-group 
gnus-newsgroup-name))
+                           gnus-discouraged-post-methods)))))))))
 
 (defun gnus-summary-post-news (&optional arg)
   "Start composing a message.  Post to the current group by default.
@@ -1926,8 +1925,8 @@ this is a reply."
                         (message-goto-body)
                         (insert ,(cdr result)))))
                   ((eq 'signature (car result))
-                   (set (make-local-variable 'message-signature) nil)
-                   (set (make-local-variable 'message-signature-file) nil)
+                    (setq-local message-signature nil)
+                    (setq-local message-signature-file nil)
                    (if (not (cdr result))
                        'ignore
                      `(lambda ()
@@ -1953,8 +1952,8 @@ this is a reply."
       (when (or name address)
        (add-hook 'message-setup-hook
                  `(lambda ()
-                    (set (make-local-variable 'user-mail-address)
-                         ,(or (cdr address) user-mail-address))
+                     (setq-local user-mail-address
+                                 ,(or (cdr address) user-mail-address))
                     (let ((user-full-name ,(or (cdr name) (user-full-name)))
                           (user-mail-address
                            ,(or (cdr address) user-mail-address)))
diff --git a/lisp/gnus/gnus-registry.el b/lisp/gnus/gnus-registry.el
index 65bcd0e..31aee03 100644
--- a/lisp/gnus/gnus-registry.el
+++ b/lisp/gnus/gnus-registry.el
@@ -54,6 +54,9 @@
 
 ;; (: gnus-registry-split-fancy-with-parent)
 
+;; This won't work as expected unless `gnus-registry-register-all'
+;; is set to t.
+
 ;; You should also consider using the nnregistry backend to look up
 ;; articles.  See the Gnus manual for more information.
 
@@ -160,6 +163,11 @@ nnmairix groups are specifically excluded because they are 
ephemeral."
                  (const :tag "Always Install" t)
                  (const :tag "Ask Me" ask)))
 
+(defcustom gnus-registry-register-all nil
+  "If non-nil, register all articles in the registry."
+  :type 'boolean
+  :version "28.1")
+
 (defvar gnus-registry-enabled nil)
 
 (defvar gnus-summary-misc-menu) ;; Avoid byte compiler warning.
@@ -478,8 +486,8 @@ This is not required after changing 
`gnus-registry-cache-file'."
   (let ((db gnus-registry-db)
         ;; if the group is ignored, set the destination to nil (same as delete)
         (to (if (gnus-registry-ignore-group-p to) nil to))
-        ;; safe if not found
-        (entry (gnus-registry-get-or-make-entry id))
+        ;; Only retrieve an existing entry, don't create a new one.
+        (entry (gnus-registry-get-or-make-entry id t))
         (subject (gnus-string-remove-all-properties
                   (gnus-registry-simplify-subject subject)))
         (sender (gnus-string-remove-all-properties sender)))
@@ -488,29 +496,30 @@ This is not required after changing 
`gnus-registry-cache-file'."
     ;; several times but it's better to bunch the transactions
     ;; together
 
-    (registry-delete db (list id) nil)
-    (when from
-      (setq entry (cons (delete from (assoc 'group entry))
-                        (assq-delete-all 'group entry))))
-    ;; Only keep the entry if the message is going to a new group, or
-    ;; it's still in some previous group.
-    (when (or to (alist-get 'group entry))
-      (dolist (kv `((group ,to)
-                    (sender ,sender)
-                    (recipient ,@recipients)
-                    (subject ,subject)))
-       (when (cadr kv)
-          (let ((new (or (assq (car kv) entry)
-                        (list (car kv)))))
-            (dolist (toadd (cdr kv))
-              (unless (member toadd new)
-               (setq new (append new (list toadd)))))
-            (setq entry (cons new
-                              (assq-delete-all (car kv) entry))))))
-      (gnus-message 10 "Gnus registry: new entry for %s is %S"
-                    id
-                    entry)
-      (gnus-registry-insert db id entry))))
+    (when entry
+      (registry-delete db (list id) nil)
+      (when from
+       (setq entry (cons (delete from (assoc 'group entry))
+                          (assq-delete-all 'group entry))))
+      ;; Only keep the entry if the message is going to a new group, or
+      ;; it's still in some previous group.
+      (when (or to (alist-get 'group entry))
+       (dolist (kv `((group ,to)
+                      (sender ,sender)
+                      (recipient ,@recipients)
+                      (subject ,subject)))
+         (when (cadr kv)
+            (let ((new (or (assq (car kv) entry)
+                          (list (car kv)))))
+              (dolist (toadd (cdr kv))
+               (unless (member toadd new)
+                 (setq new (append new (list toadd)))))
+              (setq entry (cons new
+                               (assq-delete-all (car kv) entry))))))
+       (gnus-message 10 "Gnus registry: new entry for %s is %S"
+                      id
+                      entry)
+       (gnus-registry-insert db id entry)))))
 
 ;; Function for nn{mail|imap}-split-fancy: look up all references in
 ;; the cache and if a match is found, return that group.
@@ -846,7 +855,8 @@ Overrides existing keywords with FORCE set non-nil."
 
 (defun gnus-registry-register-message-ids ()
   "Register the Message-ID of every article in the group."
-  (unless (gnus-parameter-registry-ignore gnus-newsgroup-name)
+  (unless (or (gnus-parameter-registry-ignore gnus-newsgroup-name)
+             (null gnus-registry-register-all))
     (dolist (article gnus-newsgroup-articles)
       (let* ((id (gnus-registry-fetch-message-id-fast article))
              (groups (gnus-registry-get-id-key id 'group)))
@@ -1082,12 +1092,15 @@ only the last one's marks are returned."
   "Get the number of groups of a message, based on the message ID."
   (length (gnus-registry-get-id-key id 'group)))
 
-(defun gnus-registry-get-or-make-entry (id)
+(defun gnus-registry-get-or-make-entry (id &optional no-create)
+  "Return registry entry for ID.
+If entry is not found, create a new one, unless NO-create is
+non-nil."
   (let* ((db gnus-registry-db)
          ;; safe if not found
          (entries (registry-lookup db (list id))))
 
-    (when (null entries)
+    (unless (or entries no-create)
       (gnus-registry-insert db id (list (list 'creation-time (current-time))
                                         '(group) '(sender) '(subject)))
       (setq entries (registry-lookup db (list id))))
@@ -1098,7 +1111,8 @@ only the last one's marks are returned."
   (registry-delete gnus-registry-db idlist nil))
 
 (defun gnus-registry-get-id-key (id key)
-  (cdr-safe (assq key (gnus-registry-get-or-make-entry id))))
+  (cdr-safe (assq key (gnus-registry-get-or-make-entry
+                      id (null gnus-registry-register-all)))))
 
 (defun gnus-registry-set-id-key (id key vals)
   (let* ((db gnus-registry-db)
diff --git a/lisp/gnus/gnus-salt.el b/lisp/gnus/gnus-salt.el
index 8d58cd5..f19678a 100644
--- a/lisp/gnus/gnus-salt.el
+++ b/lisp/gnus/gnus-salt.el
@@ -106,7 +106,7 @@ It accepts the same format specs that 
`gnus-summary-line-format' does."
     (remove-hook 'gnus-message-setup-hook 'gnus-pick-setup-message))
    (t
     ;; Make sure that we don't select any articles upon group entry.
-    (set (make-local-variable 'gnus-auto-select-first) nil)
+    (setq-local gnus-auto-select-first nil)
     ;; Change line format.
     (setq gnus-summary-line-format gnus-summary-pick-line-format)
     (setq gnus-summary-line-format-spec nil)
@@ -114,7 +114,7 @@ It accepts the same format specs that 
`gnus-summary-line-format' does."
     (gnus-update-summary-mark-positions)
     ;; FIXME: a buffer-local minor mode adding globally to a hook??
     (add-hook 'gnus-message-setup-hook 'gnus-pick-setup-message)
-    (set (make-local-variable 'gnus-summary-goto-unread) 'never)
+    (setq-local gnus-summary-goto-unread 'never)
     ;; Set up the menu.
     (when (gnus-visual-p 'pick-menu 'menu)
       (gnus-pick-make-menu-bar)))))
@@ -333,10 +333,8 @@ This must be bound to a button-down mouse event."
    ((not (derived-mode-p 'gnus-summary-mode)) (setq gnus-binary-mode nil))
    (gnus-binary-mode
     ;; Make sure that we don't select any articles upon group entry.
-    (make-local-variable 'gnus-auto-select-first)
-    (setq gnus-auto-select-first nil)
-    (make-local-variable 'gnus-summary-display-article-function)
-    (setq gnus-summary-display-article-function 'gnus-binary-display-article)
+    (setq-local gnus-auto-select-first nil)
+    (setq-local gnus-summary-display-article-function 
'gnus-binary-display-article)
     ;; Set up the menu.
     (when (gnus-visual-p 'binary-menu 'menu)
       (gnus-binary-make-menu-bar)))))
diff --git a/lisp/gnus/gnus-score.el b/lisp/gnus/gnus-score.el
index 2e3abe7..94f2cc3 100644
--- a/lisp/gnus/gnus-score.el
+++ b/lisp/gnus/gnus-score.el
@@ -1117,8 +1117,7 @@ EXTRA is the possible non-standard header."
       (gnus-configure-windows 'edit-score)
       (gnus-score-mode)
       (setq gnus-score-edit-exit-function 'gnus-score-edit-done)
-      (make-local-variable 'gnus-prev-winconf)
-      (setq gnus-prev-winconf winconf))
+      (setq-local gnus-prev-winconf winconf))
     (gnus-message
      4 "%s" (substitute-command-keys
             "\\<gnus-score-mode-map>\\[gnus-score-edit-exit] to save edits"))))
@@ -1145,8 +1144,7 @@ EXTRA is the possible non-standard header."
     (gnus-configure-windows 'edit-score)
     (gnus-score-mode)
     (setq gnus-score-edit-exit-function 'gnus-score-edit-done)
-    (make-local-variable 'gnus-prev-winconf)
-    (setq gnus-prev-winconf winconf))
+    (setq-local gnus-prev-winconf winconf))
   (gnus-message
    4 "%s" (substitute-command-keys
           "\\<gnus-score-mode-map>\\[gnus-score-edit-exit] to save edits")))
diff --git a/lisp/gnus/gnus-search.el b/lisp/gnus/gnus-search.el
index 89d8cff..0e67fac 100644
--- a/lisp/gnus/gnus-search.el
+++ b/lisp/gnus/gnus-search.el
@@ -105,6 +105,8 @@
 
 (define-error 'gnus-search-parse-error "Gnus search parsing error")
 
+(define-error 'gnus-search-config-error "Gnus search configuration error")
+
 ;;; User Customizable Variables:
 
 (defgroup gnus-search nil
@@ -1852,8 +1854,10 @@ Assume \"size\" key is equal to \"larger\"."
         (grouplist (or groups (gnus-search-get-active server)))
         (buffer (slot-value engine 'proc-buffer)))
     (unless directory
-      (error "No directory found in method specification of server %s"
-            server))
+      (signal 'gnus-search-config-error
+             (list (format-message
+                    "No directory found in definition of server %s"
+                    server))))
     (apply
      'vconcat
      (mapcar (lambda (x)
@@ -1885,7 +1889,9 @@ Assume \"size\" key is equal to \"larger\"."
                                            group nil t)))
                                    group))))))
                     (unless group
-                      (error "Cannot locate directory for group"))
+                      (signal 'gnus-search-config-error
+                              (list
+                               "Cannot locate directory for group")))
                     (save-excursion
                       (apply
                        'call-process "find" nil t
@@ -1934,12 +1940,19 @@ Assume \"size\" key is equal to \"larger\"."
         (limit (alist-get 'limit prepared-query)))
     (mapc
      (pcase-lambda (`(,server . ,groups))
-       (let ((search-engine (gnus-search-server-to-engine server)))
-        (setq results
-              (vconcat
-               (gnus-search-run-search
-                search-engine server prepared-query groups)
-               results))))
+       (condition-case err
+          (let ((search-engine (gnus-search-server-to-engine server)))
+            (setq results
+                  (vconcat
+                   (gnus-search-run-search
+                    search-engine server prepared-query groups)
+                   results)))
+        (gnus-search-config-error
+         (if (< 1 (length (alist-get 'search-group-spec specs)))
+             (apply #'nnheader-message 4
+                    "Search engine for %s improperly configured: %s"
+                    server (cdr err))
+           (signal 'gnus-search-config-error err)))))
      (alist-get 'search-group-spec specs))
     ;; Some search engines do their own limiting, but some don't, so
     ;; do it again here.  This is bad because, if the user is
@@ -1949,7 +1962,7 @@ Assume \"size\" key is equal to \"larger\"."
     ;; from a later group entirely.
     (if limit
        (seq-subseq results 0 (min limit (length results)))
-     results)))
+      results)))
 
 (defun gnus-search-prepare-query (query-spec)
   "Accept a search query in raw format, and prepare it.
@@ -2023,11 +2036,13 @@ remaining string, then adds all that to the top-level 
spec."
              (condition-case nil
                  (setf (slot-value inst key) value)
                ((invalid-slot-name invalid-slot-type)
-                (nnheader-message
-                 5 "Invalid search engine parameter: (%s %s)"
+                (nnheader-report 'search
+                 "Invalid search engine parameter: (%s %s)"
                  key value)))))
          (push (cons srv inst) gnus-search-engine-instance-alist))
-      (error "No search engine defined for %s" srv))
+      (signal 'gnus-search-config-error
+             (list (format-message
+                    "No search engine configured for %s" srv))))
     inst))
 
 (declare-function gnus-registry-get-id-key "gnus-registry" (id key))
diff --git a/lisp/gnus/gnus-srvr.el b/lisp/gnus/gnus-srvr.el
index 6beb543..ba15f1a 100644
--- a/lisp/gnus/gnus-srvr.el
+++ b/lisp/gnus/gnus-srvr.el
@@ -262,8 +262,7 @@ The following commands are available:
   (setq mode-line-process nil)
   (buffer-disable-undo)
   (setq truncate-lines t)
-  (set (make-local-variable 'font-lock-defaults)
-       '(gnus-server-font-lock-keywords t)))
+  (setq-local font-lock-defaults '(gnus-server-font-lock-keywords t)))
 
 
 (defun gnus-server-insert-server-line (name method)
diff --git a/lisp/gnus/gnus-start.el b/lisp/gnus/gnus-start.el
index 615f8df..d15fc82 100644
--- a/lisp/gnus/gnus-start.el
+++ b/lisp/gnus/gnus-start.el
@@ -741,8 +741,7 @@ of an NNTP server to use.  As opposed to \\[gnus], this 
command
 will not connect to the local server."
   (let ((val (or arg (1- gnus-level-default-subscribed))))
     (gnus val t child)
-    (make-local-variable 'gnus-group-use-permanent-levels)
-    (setq gnus-group-use-permanent-levels val)))
+    (setq-local gnus-group-use-permanent-levels val)))
 
 (defun gnus-1 (&optional arg dont-connect child)
   "Read network news.
@@ -875,13 +874,13 @@ If REGEXP is given, lines that match it will be deleted."
     (with-current-buffer (setq gnus-dribble-buffer
                               (gnus-get-buffer-create
                                (file-name-nondirectory dribble-file)))
-      (set (make-local-variable 'file-precious-flag) t)
+      (setq-local file-precious-flag t)
       (setq buffer-save-without-query t)
       (erase-buffer)
       (setq buffer-file-name dribble-file)
       ;; The buffer may be shrunk a lot when deleting old entries.
       ;; It caused the auto-saving to stop.
-      (set (make-local-variable 'auto-save-include-big-deletions) t)
+      (setq-local auto-save-include-big-deletions t)
       (auto-save-mode t)
       (buffer-disable-undo)
       (bury-buffer (current-buffer))
@@ -2763,8 +2762,7 @@ values from `gnus-newsrc-hashtb', and write a new value of
 
          ;; Save .newsrc.eld.
          (set-buffer (gnus-get-buffer-create " *Gnus-newsrc*"))
-         (make-local-variable 'version-control)
-         (setq version-control gnus-backup-startup-file)
+          (setq-local version-control gnus-backup-startup-file)
          (setq buffer-file-name
                (concat gnus-current-startup-file ".eld"))
          (setq default-directory (file-name-directory buffer-file-name))
@@ -2973,8 +2971,7 @@ SPECIFIC-VARIABLES, or those in `gnus-variable-list'."
                (when ranges
                  (insert ",")))))
          (insert "\n")))
-      (make-local-variable 'version-control)
-      (setq version-control 'never)
+      (setq-local version-control 'never)
       ;; It has been reported that sometime the modtime on the .newsrc
       ;; file seems to be off.  We really do want to overwrite it, so
       ;; we clear the modtime here before saving.  It's a bit odd,
diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el
index 469fa36..9488b32 100644
--- a/lisp/gnus/gnus-sum.el
+++ b/lisp/gnus/gnus-sum.el
@@ -1460,8 +1460,8 @@ the normal Gnus MIME machinery."
     (?I gnus-tmp-indentation ?s)
     (?T (if (= gnus-tmp-level 0) "" (make-string (frame-width) ? )) ?s)
     (?R gnus-tmp-replied ?c)
-    (?\[ gnus-tmp-opening-bracket ?c)
-    (?\] gnus-tmp-closing-bracket ?c)
+    (?\[ gnus-tmp-opening-bracket ?s)
+    (?\] gnus-tmp-closing-bracket ?s)
     (?\> (make-string gnus-tmp-level ? ) ?s)
     (?\< (make-string (max 0 (- 20 gnus-tmp-level)) ? ) ?s)
     (?i gnus-tmp-score ?d)
@@ -3038,7 +3038,7 @@ When FORCE, rebuild the tool bar."
        ;; Need to set `gnus-summary-tool-bar-map' because `gnus-article-mode'
        ;; uses its value.
        (setq gnus-summary-tool-bar-map map))))
-  (set (make-local-variable 'tool-bar-map) gnus-summary-tool-bar-map))
+  (setq-local tool-bar-map gnus-summary-tool-bar-map))
 
 (defun gnus-make-score-map (type)
   "Make a summary score map of type TYPE."
@@ -3174,8 +3174,8 @@ The following commands are available:
   (make-local-variable 'gnus-original-article-buffer)
   (add-hook 'pre-command-hook #'gnus-set-global-variables nil t)
   (mm-enable-multibyte)
-  (set (make-local-variable 'bookmark-make-record-function)
-       #'gnus-summary-bookmark-make-record))
+  (setq-local bookmark-make-record-function
+              #'gnus-summary-bookmark-make-record))
 
 (defun gnus-summary-make-local-variables ()
   "Make all the local summary buffer variables."
@@ -3547,7 +3547,7 @@ Returns non-nil if the setup was successful."
       (let ((gnus-summary-mode-group group))
        (gnus-summary-mode))
       (when (gnus-group-quit-config group)
-       (set (make-local-variable 'gnus-single-article-buffer) nil))
+        (setq-local gnus-single-article-buffer nil))
       (turn-on-gnus-mailing-list-mode)
       ;; These functions don't currently depend on GROUP, but might in
       ;; the future.
@@ -3748,6 +3748,30 @@ buffer that was in action when the last article was 
fetched."
       (inline
        (gnus-summary-extract-address-component gnus-tmp-from))))))
 
+(defcustom gnus-sum-opening-bracket "["
+  "With %[ spec, used to identify normal (non-adopted) articles."
+  :version "28.1"
+  :type 'string
+  :group 'gnus-summary-format)
+
+(defcustom gnus-sum-closing-bracket "]"
+  "With %] spec, used to identify normal (non-adopted) articles."
+  :version "28.1"
+  :type 'string
+  :group 'gnus-summary-format)
+
+(defcustom gnus-sum-opening-bracket-adopted "<"
+  "With %[ spec, used to identify adopted articles."
+  :version "28.1"
+  :type 'string
+  :group 'gnus-summary-format)
+
+(defcustom gnus-sum-closing-bracket-adopted ">"
+  "With %] spec, used to identify adopted articles."
+  :version "28.1"
+  :type 'string
+  :group 'gnus-summary-format)
+
 (defun gnus-summary-insert-line (header level current undownloaded
                                  unread replied expirable subject-or-nil
                                 &optional dummy score process)
@@ -3805,8 +3829,14 @@ buffer that was in action when the last article was 
fetched."
                       (1+ (match-beginning 0)) (1- (match-end 0))))
           (t gnus-tmp-from)))
         (gnus-tmp-subject (mail-header-subject gnus-tmp-header))
-        (gnus-tmp-opening-bracket (if gnus-tmp-dummy ?\< ?\[))
-        (gnus-tmp-closing-bracket (if gnus-tmp-dummy ?\> ?\]))
+        (gnus-tmp-opening-bracket
+         (if gnus-tmp-dummy
+             gnus-sum-opening-bracket-adopted
+           gnus-sum-opening-bracket))
+        (gnus-tmp-closing-bracket
+         (if gnus-tmp-dummy
+             gnus-sum-closing-bracket-adopted
+           gnus-sum-closing-bracket))
         (inhibit-read-only t))
     (when (string= gnus-tmp-name "")
       (setq gnus-tmp-name gnus-tmp-from))
@@ -5439,10 +5469,10 @@ or a straight list of headers."
            (if (and (eq gnus-summary-make-false-root 'adopt)
                     (= gnus-tmp-level 1)
                     (memq number gnus-tmp-gathered))
-               (setq gnus-tmp-opening-bracket ?\<
-                     gnus-tmp-closing-bracket ?\>)
-             (setq gnus-tmp-opening-bracket ?\[
-                   gnus-tmp-closing-bracket ?\]))
+               (setq gnus-tmp-opening-bracket gnus-sum-opening-bracket-adopted
+                     gnus-tmp-closing-bracket gnus-sum-closing-bracket-adopted)
+             (setq gnus-tmp-opening-bracket gnus-sum-opening-bracket
+                   gnus-tmp-closing-bracket gnus-sum-closing-bracket))
            (if (>= gnus-tmp-level (length gnus-thread-indent-array))
                (gnus-make-thread-indent-array
                 (max (* 2 (length gnus-thread-indent-array))
@@ -5670,8 +5700,8 @@ If SELECT-ARTICLES, only select those articles from 
GROUP."
         articles fetched-articles cached)
 
     (unless (gnus-check-server
-            (set (make-local-variable 'gnus-current-select-method)
-                 (gnus-find-method-for-group group)))
+             (setq-local gnus-current-select-method
+                         (gnus-find-method-for-group group)))
       (error "Couldn't open server"))
 
     (or (and entry (not (eq (car entry) t))) ; Either it's active...
@@ -6254,7 +6284,9 @@ If WHERE is `summary', the summary mode line format will 
be used."
                   mode-string (- max-len 3) nil nil t)))))
       ;; Update the mode line.
       (setq mode-line-buffer-identification
-           (gnus-mode-line-buffer-identification (list mode-string)))
+           (gnus-mode-line-buffer-identification
+            (list (propertize mode-string
+                              'face 'mode-line-buffer-id))))
       (set-buffer-modified-p t))))
 
 (defun gnus-create-xref-hashtb (from-newsgroup headers unreads)
@@ -10638,7 +10670,7 @@ groups."
                 (mime-to-mml current-handles))
               (let ((mbl1 mml-buffer-list))
                 (setq mml-buffer-list mbl)
-                (set (make-local-variable 'mml-buffer-list) mbl1))
+                 (setq-local mml-buffer-list mbl1))
               (add-hook 'kill-buffer-hook #'mml-destroy-buffers t t))))
         `(lambda (no-highlight)
            (let ((mail-parse-charset ',gnus-newsgroup-charset)
@@ -12846,8 +12878,7 @@ UNREAD is a sorted list."
                (and gnus-newsgroup-name
                     (gnus-parameter-charset gnus-newsgroup-name))
                gnus-default-charset))
-      (set (make-local-variable 'gnus-newsgroup-ignored-charsets)
-          ignored-charsets))))
+      (setq-local gnus-newsgroup-ignored-charsets ignored-charsets))))
 
 ;;;
 ;;; Mime Commands
diff --git a/lisp/gnus/gnus-topic.el b/lisp/gnus/gnus-topic.el
index c913002..75de1e0 100644
--- a/lisp/gnus/gnus-topic.el
+++ b/lisp/gnus/gnus-topic.el
@@ -1129,18 +1129,17 @@ articles in the topic and its subtopics."
        (gnus-topic-make-menu-bar))
       (gnus-set-format 'topic t)
       (add-hook 'gnus-group-catchup-group-hook 'gnus-topic-update-topic)
-      (set (make-local-variable 'gnus-group-prepare-function)
-          'gnus-group-prepare-topics)
-      (set (make-local-variable 'gnus-group-get-parameter-function)
-          'gnus-group-topic-parameters)
-      (set (make-local-variable 'gnus-group-goto-next-group-function)
-          'gnus-topic-goto-next-group)
-      (set (make-local-variable 'gnus-group-indentation-function)
-          'gnus-topic-group-indentation)
-      (set (make-local-variable 'gnus-group-update-group-function)
-          'gnus-topic-update-topics-containing-group)
-      (set (make-local-variable 'gnus-group-sort-alist-function)
-          'gnus-group-sort-topic)
+      (setq-local gnus-group-prepare-function
+                 'gnus-group-prepare-topics)
+      (setq-local gnus-group-get-parameter-function
+                 'gnus-group-topic-parameters)
+      (setq-local gnus-group-goto-next-group-function
+                 'gnus-topic-goto-next-group)
+      (setq-local gnus-group-indentation-function
+                  'gnus-topic-group-indentation)
+      (setq-local gnus-group-update-group-function
+                 'gnus-topic-update-topics-containing-group)
+      (setq-local gnus-group-sort-alist-function 'gnus-group-sort-topic)
       (setq gnus-group-change-level-function 'gnus-topic-change-level)
       (setq gnus-goto-missing-group-function 'gnus-topic-goto-missing-group)
       (add-hook 'gnus-check-bogus-groups-hook 'gnus-topic-clean-alist
diff --git a/lisp/gnus/gnus-undo.el b/lisp/gnus/gnus-undo.el
index 3f2b576..a852f20 100644
--- a/lisp/gnus/gnus-undo.el
+++ b/lisp/gnus/gnus-undo.el
@@ -100,8 +100,8 @@
 
 \\{gnus-undo-mode-map}"
   :keymap gnus-undo-mode-map
-  (set (make-local-variable 'gnus-undo-actions) nil)
-  (set (make-local-variable 'gnus-undo-boundary) t)
+  (setq-local gnus-undo-actions nil)
+  (setq-local gnus-undo-boundary t)
   (when gnus-undo-mode
     ;; Set up the menu.
     (when (gnus-visual-p 'undo-menu 'menu)
diff --git a/lisp/gnus/gnus-win.el b/lisp/gnus/gnus-win.el
index baa3146..e900e29 100644
--- a/lisp/gnus/gnus-win.el
+++ b/lisp/gnus/gnus-win.el
@@ -68,7 +68,7 @@ used to display Gnus windows."
   :type 'boolean)
 
 (defvar gnus-buffer-configuration
-  '((group
+  `((group
      (vertical 1.0
               (group 1.0 point)))
     (summary
@@ -142,7 +142,7 @@ used to display Gnus windows."
     (pipe
      (vertical 1.0
               (summary 0.25 point)
-              (shell-command-buffer-name 1.0)))
+               (,shell-command-buffer-name 1.0)))
     (bug
      (vertical 1.0
               (if gnus-bug-create-help-buffer '("*Gnus Help Bug*" 0.5))
diff --git a/lisp/gnus/gnus.el b/lisp/gnus/gnus.el
index c1cfddc..abe7b1a 100644
--- a/lisp/gnus/gnus.el
+++ b/lisp/gnus/gnus.el
@@ -309,34 +309,29 @@ be set in `.emacs' instead."
   :group 'gnus-start
   :type 'boolean)
 
-(defvar gnus-mode-line-image-cache t)
-
-(eval-and-compile
-  (if (fboundp 'find-image)
-      (defun gnus-mode-line-buffer-identification (line)
-       (let ((str (car-safe line))
-             (load-path (append (mm-image-load-path) load-path)))
-         (if (and (display-graphic-p)
-                  (stringp str)
-                  (string-match "^Gnus:" str))
-             (progn (add-text-properties
-                     0 5
-                     (list 'display
-                           (if (eq t gnus-mode-line-image-cache)
-                               (setq gnus-mode-line-image-cache
-                                     (find-image
-                                      '((:type xpm :file "gnus-pointer.xpm"
-                                               :ascent center)
-                                        (:type xbm :file "gnus-pointer.xbm"
-                                               :ascent center))))
-                             gnus-mode-line-image-cache)
-                           'help-echo (format
-                                       "This is %s, %s."
-                                       gnus-version (gnus-emacs-version)))
-                     str)
-                    (list str))
-           line)))
-    (defalias 'gnus-mode-line-buffer-identification 'identity)))
+(defun gnus-mode-line-buffer-identification (line)
+  (let ((str (car-safe line)))
+    (if (or (not (fboundp 'find-image))
+           (not (display-graphic-p))
+           (not (stringp str))
+           (not (string-match "^Gnus:" str)))
+       line
+      (let ((load-path (append (mm-image-load-path) load-path)))
+       ;; Add the Gnus logo.
+       (add-text-properties
+        0 5
+        (list 'display
+              (find-image
+               '((:type xpm :file "gnus-pointer.xpm"
+                        :ascent center)
+                 (:type xbm :file "gnus-pointer.xbm"
+                        :ascent center))
+               t)
+              'help-echo (format
+                          "This is %s, %s."
+                          gnus-version (gnus-emacs-version)))
+        str)
+       (list str)))))
 
 ;; We define these group faces here to avoid the display
 ;; update forced when creating new faces.
@@ -3175,8 +3170,7 @@ that that variable is buffer-local to the summary 
buffers."
   "Make mode lines a bit simpler."
   (setq mode-line-modified "--")
   (when (listp mode-line-format)
-    (make-local-variable 'mode-line-format)
-    (setq mode-line-format (copy-sequence mode-line-format))
+    (setq-local mode-line-format (copy-sequence mode-line-format))
     (when (equal (nth 3 mode-line-format) "   ")
       (setcar (nthcdr 3 mode-line-format) " "))))
 
diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el
index 2ab3eb6..b6c1c0b 100644
--- a/lisp/gnus/message.el
+++ b/lisp/gnus/message.el
@@ -1155,7 +1155,7 @@ Note: Many newsgroups frown upon nontraditional reply 
styles.
 You probably want to set this variable only for specific groups,
 e.g. using `gnus-posting-styles':
 
-  (eval (set (make-local-variable \\='message-cite-reply-position) \\='above))"
+  (eval (setq-local message-cite-reply-position \\='above))"
   :version "24.1"
   :type '(choice (const :tag "Reply inline" traditional)
                 (const :tag "Reply above" above)
@@ -1172,7 +1172,7 @@ Presets to impersonate popular mail agents are found in 
the
 message-cite-style-* variables.  This variable is intended for
 use in `gnus-posting-styles', such as:
 
-  ((posting-from-work-p) (eval (set (make-local-variable 
\\='message-cite-style) message-cite-style-outlook)))"
+  ((posting-from-work-p) (eval (setq-local message-cite-style 
message-cite-style-outlook)))"
   :version "24.1"
   :group 'message-insertion
   :type '(choice (const :tag "Do not override variables" :value nil)
@@ -3078,44 +3078,43 @@ See also `message-forbidden-properties'."
 Like `text-mode', but with these additional commands:
 
 \\{message-mode-map}"
-  (set (make-local-variable 'message-reply-buffer) nil)
-  (set (make-local-variable 'message-inserted-headers) nil)
-  (set (make-local-variable 'message-send-actions) nil)
-  (set (make-local-variable 'message-return-action) nil)
-  (set (make-local-variable 'message-exit-actions) nil)
-  (set (make-local-variable 'message-kill-actions) nil)
-  (set (make-local-variable 'message-postpone-actions) nil)
-  (set (make-local-variable 'message-draft-article) nil)
+  (setq-local message-reply-buffer nil)
+  (setq-local message-inserted-headers nil)
+  (setq-local message-send-actions nil)
+  (setq-local message-return-action nil)
+  (setq-local message-exit-actions nil)
+  (setq-local message-kill-actions nil)
+  (setq-local message-postpone-actions nil)
+  (setq-local message-draft-article nil)
   (setq buffer-offer-save t)
-  (set (make-local-variable 'facemenu-add-face-function)
+  (setq-local facemenu-add-face-function
        (lambda (face end)
         (let ((face-fun (cdr (assq face message-face-alist))))
           (if face-fun
               (funcall face-fun (point) end)
             (error "Face %s not configured for %s mode" face mode-name)))
         ""))
-  (set (make-local-variable 'facemenu-remove-face-function) t)
-  (set (make-local-variable 'message-reply-headers) nil)
+  (setq-local facemenu-remove-face-function t)
+  (setq-local message-reply-headers nil)
   (make-local-variable 'message-newsreader)
   (make-local-variable 'message-mailer)
   (make-local-variable 'message-post-method)
-  (set (make-local-variable 'message-sent-message-via) nil)
-  (set (make-local-variable 'message-checksum) nil)
-  (set (make-local-variable 'message-mime-part) 0)
+  (setq-local message-sent-message-via nil)
+  (setq-local message-checksum nil)
+  (setq-local message-mime-part 0)
   (message-setup-fill-variables)
   (when message-fill-column
     (setq fill-column message-fill-column)
     (turn-on-auto-fill))
   ;; Allow using comment commands to add/remove quoting.
-  ;; (set (make-local-variable 'comment-start) message-yank-prefix)
+  ;; (setq-local comment-start message-yank-prefix)
   (when message-yank-prefix
-    (set (make-local-variable 'comment-start) message-yank-prefix)
-    (set (make-local-variable 'comment-start-skip)
-        (concat "^" (regexp-quote message-yank-prefix) "[ \t]*")))
-  (set (make-local-variable 'font-lock-defaults)
-       '(message-font-lock-keywords t))
+    (setq-local comment-start message-yank-prefix)
+    (setq-local comment-start-skip
+                (concat "^" (regexp-quote message-yank-prefix) "[ \t]*")))
+  (setq-local font-lock-defaults '(message-font-lock-keywords t))
   (if (boundp 'tool-bar-map)
-      (set (make-local-variable 'tool-bar-map) (message-make-tool-bar)))
+      (setq-local tool-bar-map (message-make-tool-bar)))
   ;; Mmmm... Forbidden properties...
   (add-hook 'after-change-functions #'message-strip-forbidden-properties
            nil 'local)
@@ -3134,45 +3133,41 @@ Like `text-mode', but with these additional commands:
     ;; Don't enable multibyte on an indirect buffer.  Maybe enabling
     ;; multibyte is not necessary at all. -- zsh
     (mm-enable-multibyte))
-  (set (make-local-variable 'indent-tabs-mode) nil) ;No tabs for indentation.
+  (setq-local indent-tabs-mode nil) ; No tabs for indentation.
   (mml-mode)
   ;; Syntactic fontification. Helps `show-paren-mode',
   ;; `electric-pair-mode', and C-M-* navigation by syntactically
   ;; excluding citations and other artifacts.
   ;;
-  (set (make-local-variable 'syntax-propertize-function) 
'message--syntax-propertize)
-  (set (make-local-variable 'parse-sexp-ignore-comments) t)
+  (setq-local syntax-propertize-function 'message--syntax-propertize)
+  (setq-local parse-sexp-ignore-comments t)
   (setq-local message-encoded-mail-cache nil))
 
 (defun message-setup-fill-variables ()
   "Setup message fill variables."
-  (set (make-local-variable 'fill-paragraph-function)
-       'message-fill-paragraph)
-  (make-local-variable 'paragraph-separate)
-  (make-local-variable 'paragraph-start)
-  (make-local-variable 'adaptive-fill-regexp)
+  (setq-local fill-paragraph-function 'message-fill-paragraph)
   (make-local-variable 'adaptive-fill-first-line-regexp)
   (let ((quote-prefix-regexp
         ;; User should change message-cite-prefix-regexp if
         ;; message-yank-prefix is set to an abnormal value.
         (concat "\\(" message-cite-prefix-regexp "\\)[ \t]*")))
-    (setq paragraph-start
-         (concat
-          (regexp-quote mail-header-separator) "$\\|"
-          "[ \t]*$\\|"                 ; blank lines
-          "-- $\\|"                    ; signature delimiter
-          "---+$\\|"              ; delimiters for forwarded messages
-          page-delimiter "$\\|"        ; spoiler warnings
-          ".*wrote:$\\|"               ; attribution lines
-          quote-prefix-regexp "$\\|"   ; empty lines in quoted text
-                                       ; mml tags
-          "<#!*/?\\(multipart\\|part\\|external\\|mml\\|secure\\)"))
-    (setq paragraph-separate paragraph-start)
-    (setq adaptive-fill-regexp
-         (concat quote-prefix-regexp "\\|" adaptive-fill-regexp))
-    (setq adaptive-fill-first-line-regexp
-         (concat quote-prefix-regexp "\\|"
-                 adaptive-fill-first-line-regexp)))
+    (setq-local paragraph-start
+                (concat
+                 (regexp-quote mail-header-separator) "$\\|"
+                 "[ \t]*$\\|"                  ; blank lines
+                 "-- $\\|"                     ; signature delimiter
+                 "---+$\\|"               ; delimiters for forwarded messages
+                 page-delimiter "$\\|" ; spoiler warnings
+                 ".*wrote:$\\|"                ; attribution lines
+                 quote-prefix-regexp "$\\|"    ; empty lines in quoted text
+                                        ; mml tags
+                 "<#!*/?\\(multipart\\|part\\|external\\|mml\\|secure\\)"))
+    (setq-local paragraph-separate paragraph-start)
+    (setq-local adaptive-fill-regexp
+                (concat quote-prefix-regexp "\\|" adaptive-fill-regexp))
+    (setq-local adaptive-fill-first-line-regexp
+                (concat quote-prefix-regexp "\\|"
+                        adaptive-fill-first-line-regexp)))
   (setq-local auto-fill-inhibit-regexp nil)
   (setq-local normal-auto-fill-function 'message-do-auto-fill))
 
diff --git a/lisp/gnus/mm-view.el b/lisp/gnus/mm-view.el
index ca61001..015bc79 100644
--- a/lisp/gnus/mm-view.el
+++ b/lisp/gnus/mm-view.el
@@ -486,7 +486,7 @@ If MODE is not set, try to find mode automatically."
         ;; support modes, but now that we use font-lock-ensure, support modes
         ;; aren't a problem any more.  So we could probably get rid of this
         ;; setting now, but it seems harmless and potentially still useful.
-       (set (make-local-variable 'font-lock-mode-hook) nil)
+       (setq-local font-lock-mode-hook nil)
         (setq buffer-file-name (mm-handle-filename handle))
        (with-demoted-errors
            (if mode
diff --git a/lisp/gnus/mml.el b/lisp/gnus/mml.el
index 067396f..47dcb54 100644
--- a/lisp/gnus/mml.el
+++ b/lisp/gnus/mml.el
@@ -1266,8 +1266,8 @@ See Info node `(emacs-mime)Composing'.
   :lighter " MML" :keymap mml-mode-map
   (when mml-mode
     (when (boundp 'dnd-protocol-alist)
-      (set (make-local-variable 'dnd-protocol-alist)
-          (append mml-dnd-protocol-alist dnd-protocol-alist)))))
+      (setq-local dnd-protocol-alist
+                  (append mml-dnd-protocol-alist dnd-protocol-alist)))))
 
 ;;;
 ;;; Helper functions for reading MIME stuff from the minibuffer and
diff --git a/lisp/gnus/nndiary.el b/lisp/gnus/nndiary.el
index ccd1774..ef52070 100644
--- a/lisp/gnus/nndiary.el
+++ b/lisp/gnus/nndiary.el
@@ -1002,10 +1002,10 @@ all.  This may very well take some time.")
       (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
-               nndiary-nov-file-name
-               (nnmail-group-pathname group nndiary-directory)))
+         (setq-local nndiary-nov-buffer-file-name
+                     (expand-file-name
+                      nndiary-nov-file-name
+                      (nnmail-group-pathname group nndiary-directory)))
          (erase-buffer)
          (when (file-exists-p nndiary-nov-buffer-file-name)
            (nnheader-insert-file-contents nndiary-nov-buffer-file-name)))
diff --git a/lisp/gnus/nnfolder.el b/lisp/gnus/nnfolder.el
index 6ff9905..b7bfd9a 100644
--- a/lisp/gnus/nnfolder.el
+++ b/lisp/gnus/nnfolder.el
@@ -1083,7 +1083,7 @@ This command does not work if you use short group names."
       (let ((coding-system-for-write
             (or nnfolder-file-coding-system-for-write
                 nnfolder-file-coding-system)))
-       (set (make-local-variable 'copyright-update) nil)
+        (setq-local copyright-update nil)
        (save-buffer)))
     (unless (or gnus-nov-is-evil nnfolder-nov-is-evil)
       (nnfolder-save-nov))))
@@ -1098,8 +1098,8 @@ This command does not work if you use short group names."
   (or (cdr (assoc group nnfolder-nov-buffer-alist))
       (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))
+          (setq-local nnfolder-nov-buffer-file-name
+                      (nnfolder-group-nov-pathname group))
          (erase-buffer)
          (when (file-exists-p nnfolder-nov-buffer-file-name)
            (nnheader-insert-file-contents nnfolder-nov-buffer-file-name)))
diff --git a/lisp/gnus/nnheader.el b/lisp/gnus/nnheader.el
index 2952e20..c976221 100644
--- a/lisp/gnus/nnheader.el
+++ b/lisp/gnus/nnheader.el
@@ -568,7 +568,7 @@ the line could be found."
     (mm-enable-multibyte)
     (kill-all-local-variables)
     (setq case-fold-search t)          ;Should ignore case.
-    (set (make-local-variable 'nntp-process-response) nil)
+    (setq-local nntp-process-response nil)
     t))
 
 ;;; Various functions the backends use.
diff --git a/lisp/gnus/nnimap.el b/lisp/gnus/nnimap.el
index a860333..61693a0 100644
--- a/lisp/gnus/nnimap.el
+++ b/lisp/gnus/nnimap.el
@@ -157,6 +157,9 @@ during splitting, which may be slow."
   :version "28.1"
   :type 'boolean)
 
+(defvar nnimap--split-download-body nil
+  "Like `nnimap-split-download-body', but for internal use.")
+
 (defvar nnimap-process nil)
 
 (defvar nnimap-status-string "")
@@ -373,10 +376,10 @@ during splitting, which may be slow."
     (mm-disable-multibyte)
     (buffer-disable-undo)
     (gnus-add-buffer)
-    (set (make-local-variable 'after-change-functions) nil) ;FIXME: Why?
-    (set (make-local-variable 'nnimap-object)
-        (make-nnimap :server (nnoo-current-server 'nnimap)
-                     :initial-resync 0))
+    (setq-local after-change-functions nil) ;FIXME: Why?
+    (setq-local nnimap-object
+                (make-nnimap :server (nnoo-current-server 'nnimap)
+                             :initial-resync 0))
     (push (list buffer (current-buffer)) nnimap-connection-alist)
     (push (current-buffer) nnimap-process-buffers)
     (current-buffer)))
@@ -2108,7 +2111,8 @@ Return the server's response to the SELECT or EXAMINE 
command."
                 "BODY.PEEK"
               "RFC822.PEEK"))
            (cond
-            (nnimap-split-download-body
+             ((or nnimap-split-download-body
+                  nnimap--split-download-body)
              "[]")
             ((nnimap-ver4-p)
              "[HEADER]")
diff --git a/lisp/gnus/nnml.el b/lisp/gnus/nnml.el
index ad608b6..c648e3a 100644
--- a/lisp/gnus/nnml.el
+++ b/lisp/gnus/nnml.el
@@ -778,8 +778,8 @@ article number.  This function is called narrowed to an 
article."
                         group)))
         (file-name-coding-system nnmail-pathname-coding-system))
     (with-current-buffer buffer
-      (set (make-local-variable 'nnml-nov-buffer-file-name)
-          (nnmail-group-pathname group nnml-directory nnml-nov-file-name))
+      (setq-local nnml-nov-buffer-file-name
+                  (nnmail-group-pathname group nnml-directory 
nnml-nov-file-name))
       (erase-buffer)
       (when (and (not incrementalp)
                 (file-exists-p nnml-nov-buffer-file-name))
diff --git a/lisp/gnus/spam.el b/lisp/gnus/spam.el
index 96a7da2..e74aef3 100644
--- a/lisp/gnus/spam.el
+++ b/lisp/gnus/spam.el
@@ -44,12 +44,9 @@
 ;;; for the definitions of group content classification and spam processors
 (require 'gnus)
 
-(eval-when-compile (require 'hashcash))
-
-;; for nnimap-split-download-body-default
-(eval-when-compile (require 'nnimap))
-
-(eval-when-compile (require 'cl-lib))
+(eval-when-compile
+  (require 'cl-lib)
+  (require 'hashcash))
 
 ;; autoload query-dig
 (autoload 'query-dig "dig")
@@ -1228,10 +1225,20 @@ Will not return a nil score."
 
 ;;{{{ set up widening, processor checks
 
-;;; set up IMAP widening if it's necessary
+(defconst spam--widened (list ())
+  "Unique value identifying changes to `nnimap--split-download-body'.")
+
 (defun spam-setup-widening ()
-  (when (spam-widening-needed-p)
-    (setq nnimap-split-download-body-default t)))
+  "Set up IMAP widening if it's necessary."
+  (and (boundp 'nnimap--split-download-body)
+       (not nnimap--split-download-body)
+       (spam-widening-needed-p)
+       (setq nnimap--split-download-body spam--widened)))
+
+(defun spam-teardown-widening ()
+  "Tear down IMAP widening."
+  (when (eq (bound-and-true-p nnimap--split-download-body) spam--widened)
+    (setq nnimap--split-download-body nil)))
 
 (defun spam-widening-needed-p (&optional force-symbols)
   (let (found)
@@ -2865,6 +2872,7 @@ installed through `spam-necessary-extra-headers'."
 (defun spam-unload-hook ()
   "Uninstall the spam.el hooks."
   (interactive)
+  (spam-teardown-widening)
   (remove-hook 'gnus-save-newsrc-hook 'spam-maybe-spam-stat-save)
   (remove-hook 'gnus-get-top-new-news-hook 'spam-maybe-spam-stat-load)
   (remove-hook 'gnus-startup-hook 'spam-maybe-spam-stat-load)
diff --git a/lisp/help-fns.el b/lisp/help-fns.el
index 1c55d0e..043c79f 100644
--- a/lisp/help-fns.el
+++ b/lisp/help-fns.el
@@ -1137,8 +1137,7 @@ it is displayed along with the global value."
                (when (looking-at "value is") (replace-match ""))
                (save-excursion
                  (insert "\n\nValue:")
-                 (set (make-local-variable 'help-button-cache)
-                      (point-marker)))
+                  (setq-local help-button-cache (point-marker)))
                (insert "value is shown ")
                (insert-button "below"
                               'action help-button-cache
diff --git a/lisp/help-mode.el b/lisp/help-mode.el
index 732e6cc..025a670 100644
--- a/lisp/help-mode.el
+++ b/lisp/help-mode.el
@@ -319,10 +319,10 @@ The format is (FUNCTION ARGS...).")
 Entry to this mode runs the normal hook `help-mode-hook'.
 Commands:
 \\{help-mode-map}"
-  (set (make-local-variable 'revert-buffer-function)
-       'help-mode-revert-buffer)
-  (set (make-local-variable 'bookmark-make-record-function)
-       'help-bookmark-make-record))
+  (setq-local revert-buffer-function
+              #'help-mode-revert-buffer)
+  (setq-local bookmark-make-record-function
+              #'help-bookmark-make-record))
 
 ;;;###autoload
 (defun help-mode-setup ()
diff --git a/lisp/hexl.el b/lisp/hexl.el
index 5d813c4..1fe9aad 100644
--- a/lisp/hexl.el
+++ b/lisp/hexl.el
@@ -722,7 +722,10 @@ With prefix arg N, puts point N bytes of the way from the 
true beginning."
   "Scroll hexl buffer window upward ARG lines; or near full window if no ARG."
   (interactive "P")
   (setq arg (if (null arg)
-                (1- (window-height))
+                (- (window-height)
+                   1
+                   (if ruler-mode 1 0)
+                   next-screen-context-lines)
               (prefix-numeric-value arg)))
   (hexl-scroll-up (- arg)))
 
@@ -731,7 +734,10 @@ With prefix arg N, puts point N bytes of the way from the 
true beginning."
 If there's no byte at the target address, move to the first or last line."
   (interactive "P")
   (setq arg (if (null arg)
-                (1- (window-height))
+                (- (window-height)
+                   1
+                   (if ruler-mode 1 0)
+                   next-screen-context-lines)
               (prefix-numeric-value arg)))
   (let* ((movement (* arg 16))
         (address (hexl-current-address))
diff --git a/lisp/ibuffer.el b/lisp/ibuffer.el
index 00ba868..7269af3 100644
--- a/lisp/ibuffer.el
+++ b/lisp/ibuffer.el
@@ -2464,7 +2464,7 @@ FORMATS is the value to use for `ibuffer-formats'.
          (require 'ibuf-ext)
          (setq ibuffer-filter-groups filter-groups))
        (when formats
-         (set (make-local-variable 'ibuffer-formats) formats))
+         (setq-local ibuffer-formats formats))
        (ibuffer-update nil)
        ;; Skip the group name by default.
        (ibuffer-forward-line 0 t)
@@ -2683,7 +2683,7 @@ You may rearrange filter groups by using the usual pair
 `\\[ibuffer-kill-line]' and `\\[ibuffer-yank]'.  Yanked groups
 will be inserted before the group at point."
   ;; Include state info next to the mode name.
-  (set (make-local-variable 'mode-line-process)
+  (setq-local mode-line-process
         '(" by "
           (ibuffer-sorting-mode (:eval (symbol-name ibuffer-sorting-mode))
                                 "view time")
@@ -2712,28 +2712,27 @@ will be inserted before the group at point."
   (setq show-trailing-whitespace nil)
   ;; disable `show-paren-mode' buffer-locally
   (if (bound-and-true-p show-paren-mode)
-      (set (make-local-variable 'show-paren-mode) nil))
-  (set (make-local-variable 'revert-buffer-function)
-       #'ibuffer-update)
-  (set (make-local-variable 'ibuffer-sorting-mode)
-       ibuffer-default-sorting-mode)
-  (set (make-local-variable 'ibuffer-sorting-reversep)
-       ibuffer-default-sorting-reversep)
-  (set (make-local-variable 'ibuffer-shrink-to-minimum-size)
-       ibuffer-default-shrink-to-minimum-size)
-  (set (make-local-variable 'ibuffer-display-maybe-show-predicates)
-       ibuffer-default-display-maybe-show-predicates)
-  (set (make-local-variable 'ibuffer-filtering-qualifiers) nil)
-  (set (make-local-variable 'ibuffer-filter-groups) nil)
-  (set (make-local-variable 'ibuffer-filter-group-kill-ring) nil)
-  (set (make-local-variable 'ibuffer-hidden-filter-groups) nil)
-  (set (make-local-variable 'ibuffer-compiled-formats) nil)
-  (set (make-local-variable 'ibuffer-cached-formats) nil)
-  (set (make-local-variable 'ibuffer-cached-eliding-string) nil)
-  (set (make-local-variable 'ibuffer-current-format) nil)
-  (set (make-local-variable 'ibuffer-did-modification) nil)
-  (set (make-local-variable 'ibuffer-tmp-hide-regexps) nil)
-  (set (make-local-variable 'ibuffer-tmp-show-regexps) nil)
+      (setq-local show-paren-mode nil))
+  (setq-local revert-buffer-function #'ibuffer-update)
+  (setq-local ibuffer-sorting-mode
+              ibuffer-default-sorting-mode)
+  (setq-local ibuffer-sorting-reversep
+              ibuffer-default-sorting-reversep)
+  (setq-local ibuffer-shrink-to-minimum-size
+              ibuffer-default-shrink-to-minimum-size)
+  (setq-local ibuffer-display-maybe-show-predicates
+              ibuffer-default-display-maybe-show-predicates)
+  (setq-local ibuffer-filtering-qualifiers nil)
+  (setq-local ibuffer-filter-groups nil)
+  (setq-local ibuffer-filter-group-kill-ring nil)
+  (setq-local ibuffer-hidden-filter-groups nil)
+  (setq-local ibuffer-compiled-formats nil)
+  (setq-local ibuffer-cached-formats nil)
+  (setq-local ibuffer-cached-eliding-string nil)
+  (setq-local ibuffer-current-format nil)
+  (setq-local ibuffer-did-modification nil)
+  (setq-local ibuffer-tmp-hide-regexps nil)
+  (setq-local ibuffer-tmp-show-regexps nil)
   (define-key ibuffer-mode-map [menu-bar edit] 'undefined)
   (define-key ibuffer-mode-map [menu-bar operate] (cons "Operate" 
ibuffer-mode-operate-map))
   (ibuffer-update-format)
diff --git a/lisp/icomplete.el b/lisp/icomplete.el
index 9c14708..0fdacd0 100644
--- a/lisp/icomplete.el
+++ b/lisp/icomplete.el
@@ -75,12 +75,7 @@ everything preceding the ~/ is discarded so the interactive
 selection process starts again from the user's $HOME.")
 
 (defcustom icomplete-show-matches-on-no-input nil
-  "If nil, don't wait for completions before showing the prompt.
-Instead, when there's no input, completions may be displayed
-asynchronously later, when the completions have been computed.
-
-If non-nil, always compute the completions first.
-
+  "When non-nil, show completions when the minibuffer is empty.
 This also means that if you traverse the list of completions with
 commands like `C-.' and just hit RET without typing any
 characters, the match under point will be chosen instead of the
@@ -446,7 +441,7 @@ Conditions are:
   "Run in minibuffer on activation to establish incremental completion.
 Usually run by inclusion in `minibuffer-setup-hook'."
   (when (and icomplete-mode (icomplete-simple-completing-p))
-    (set (make-local-variable 'completion-show-inline-help) nil)
+    (setq-local completion-show-inline-help nil)
     (use-local-map (make-composed-keymap icomplete-minibuffer-map
                                         (current-local-map)))
     (add-hook 'pre-command-hook  #'icomplete-pre-command-hook  nil t)
@@ -469,7 +464,7 @@ Usually run by inclusion in `minibuffer-setup-hook'."
   (when (and completion-in-region-mode
             icomplete-mode (icomplete-simple-completing-p))
     (setq icomplete--in-region-buffer (current-buffer))
-    (set (make-local-variable 'completion-show-inline-help) nil)
+    (setq-local completion-show-inline-help nil)
     (let ((tem (assq 'completion-in-region-mode
                     minor-mode-overriding-map-alist)))
       (unless (memq icomplete-minibuffer-map (cdr tem))
diff --git a/lisp/ido.el b/lisp/ido.el
index c83b700..5758d3f 100644
--- a/lisp/ido.el
+++ b/lisp/ido.el
@@ -3966,7 +3966,7 @@ If `ido-change-word-sub' cannot be found in WORD, return 
nil."
                      (boundp 'ido-completion-buffer-full))
                  (set-window-start win (point-min))
                (with-no-warnings
-                 (set (make-local-variable 'ido-completion-buffer-full) t))
+                  (setq-local ido-completion-buffer-full t))
                (setq full-list t
                      display-it t))
            (scroll-other-window))
@@ -4810,8 +4810,7 @@ Modified from `icomplete-completions'."
            (delete-region ido-eoinput (point-max))))
 
       ;; Reestablish the local variable 'cause minibuffer-setup is weird:
-      (make-local-variable 'ido-eoinput)
-      (setq ido-eoinput 1))))
+      (setq-local ido-eoinput 1))))
 
 (defun ido-summary-buffers-to-end ()
   ;; Move the summaries to the end of the buffer list.
diff --git a/lisp/ielm.el b/lisp/ielm.el
index 91d025d..b958389 100644
--- a/lisp/ielm.el
+++ b/lisp/ielm.el
@@ -529,8 +529,8 @@ Customized bindings may be defined in `ielm-map', which 
currently contains:
   :syntax-table emacs-lisp-mode-syntax-table
 
   (setq comint-prompt-regexp (concat "^" (regexp-quote ielm-prompt)))
-  (set (make-local-variable 'paragraph-separate) "\\'")
-  (set (make-local-variable 'paragraph-start) comint-prompt-regexp)
+  (setq-local paragraph-separate "\\'")
+  (setq-local paragraph-start comint-prompt-regexp)
   (setq comint-input-sender 'ielm-input-sender)
   (setq comint-process-echoes nil)
   (dolist (f '(elisp-completion-at-point
@@ -541,28 +541,28 @@ Customized bindings may be defined in `ielm-map', which 
currently contains:
             #'elisp-eldoc-var-docstring nil t)
   (add-hook 'eldoc-documentation-functions
             #'elisp-eldoc-funcall nil t)
-  (set (make-local-variable 'ielm-prompt-internal) ielm-prompt)
-  (set (make-local-variable 'comint-prompt-read-only) ielm-prompt-read-only)
+  (setq-local ielm-prompt-internal ielm-prompt)
+  (setq-local comint-prompt-read-only ielm-prompt-read-only)
   (setq comint-get-old-input 'ielm-get-old-input)
-  (set (make-local-variable 'comint-completion-addsuffix) '("/" . ""))
+  (setq-local comint-completion-addsuffix '("/" . ""))
   (setq mode-line-process '(":%s on " (:eval (buffer-name 
ielm-working-buffer))))
   ;; Useful for `hs-minor-mode'.
   (setq-local comment-start ";")
   (setq-local comment-use-syntax t)
   (setq-local lexical-binding t)
 
-  (set (make-local-variable 'indent-line-function) #'ielm-indent-line)
-  (set (make-local-variable 'ielm-working-buffer) (current-buffer))
-  (set (make-local-variable 'fill-paragraph-function) #'lisp-fill-paragraph)
+  (setq-local indent-line-function #'ielm-indent-line)
+  (setq-local ielm-working-buffer (current-buffer))
+  (setq-local fill-paragraph-function #'lisp-fill-paragraph)
 
   ;; Value holders
-  (set (make-local-variable '*) nil)
-  (set (make-local-variable '**) nil)
-  (set (make-local-variable '***) nil)
-  (set (make-local-variable 'ielm-match-data) nil)
+  (setq-local * nil)
+  (setq-local ** nil)
+  (setq-local *** nil)
+  (setq-local ielm-match-data nil)
 
   ;; font-lock support
-  (set (make-local-variable 'font-lock-defaults)
+  (setq-local font-lock-defaults
        '(ielm-font-lock-keywords nil nil ((?: . "w") (?- . "w") (?* . "w"))))
 
   ;; A dummy process to keep comint happy. It will never get any input
@@ -577,7 +577,7 @@ Customized bindings may be defined in `ielm-map', which 
currently contains:
 
     ;; Lisp output can include raw characters that confuse comint's
     ;; carriage control code.
-    (set (make-local-variable 'comint-inhibit-carriage-motion) t)
+    (setq-local comint-inhibit-carriage-motion t)
 
     ;; Add a silly header
     (insert ielm-header)
diff --git a/lisp/image.el b/lisp/image.el
index 9ebb603..023d64f 100644
--- a/lisp/image.el
+++ b/lisp/image.el
@@ -679,8 +679,10 @@ BUFFER nil or omitted means use the current buffer."
       (setq path (cdr path)))
     (if found filename)))
 
+(defvar find-image--cache (make-hash-table :test #'equal))
+
 ;;;###autoload
-(defun find-image (specs)
+(defun find-image (specs &optional cache)
   "Find an image, choosing one of a list of image specifications.
 
 SPECS is a list of image specifications.
@@ -695,26 +697,33 @@ is supported, and FILE exists, is used to construct the 
image
 specification to be returned.  Return nil if no specification is
 satisfied.
 
+If CACHE is non-nil, results are cached and returned on subsequent calls.
+
 The image is looked for in `image-load-path'.
 
 Image files should not be larger than specified by `max-image-size'."
-  (let (image)
-    (while (and specs (null image))
-      (let* ((spec (car specs))
-            (type (plist-get spec :type))
-            (data (plist-get spec :data))
-            (file (plist-get spec :file))
-            found)
-       (when (image-type-available-p type)
-         (cond ((stringp file)
-                (if (setq found (image-search-load-path file))
-                    (setq image
-                          (cons 'image (plist-put (copy-sequence spec)
-                                                  :file found)))))
-               ((not (null data))
-                (setq image (cons 'image spec)))))
-       (setq specs (cdr specs))))
-    image))
+  (or (and cache
+           (gethash specs find-image--cache))
+      (let ((orig-specs specs)
+            image)
+        (while (and specs (null image))
+          (let* ((spec (car specs))
+                (type (plist-get spec :type))
+                (data (plist-get spec :data))
+                (file (plist-get spec :file))
+                found)
+           (when (image-type-available-p type)
+             (cond ((stringp file)
+                    (if (setq found (image-search-load-path file))
+                        (setq image
+                              (cons 'image (plist-put (copy-sequence spec)
+                                                      :file found)))))
+                   ((not (null data))
+                    (setq image (cons 'image spec)))))
+           (setq specs (cdr specs))))
+        (when cache
+          (setf (gethash orig-specs find-image--cache) image))
+        image)))
 
 
 ;;;###autoload
diff --git a/lisp/image/exif.el b/lisp/image/exif.el
index 6aeb52c..e328fcc 100644
--- a/lisp/image/exif.el
+++ b/lisp/image/exif.el
@@ -165,7 +165,7 @@ If the orientation isn't present in the data, return nil."
       ;; Another magical number.
       (unless (= (exif--read-number 2 le) #x002a)
         (signal 'exif-error "Invalid TIFF header length"))
-      (let ((offset (exif--read-number 2 le)))
+      (let ((offset (exif--read-number 4 le)))
         ;; Jump to where the IFD (directory) starts and parse it.
         (when (> (1+ offset) (point-max))
           (signal 'exif-error "Invalid IFD (directory) offset"))
diff --git a/lisp/info.el b/lisp/info.el
index c3684de..c049aa8 100644
--- a/lisp/info.el
+++ b/lisp/info.el
@@ -2473,7 +2473,7 @@ Table of contents is created from the tree structure of 
menus."
               (setq bound (or (and (equal nodename "Top")
                                    (save-excursion
                                      (re-search-forward
-                                      "^[ \t-]*The Detailed Node Listing" nil 
t)))
+                                      "^[ \t—-]*The Detailed Node Listing" nil 
t)))
                               bound))
               (while (< (point) bound)
                 (cond
@@ -4790,10 +4790,10 @@ first line or header line, and for breadcrumb links.")
                    ;; an end of sentence
                    (skip-syntax-backward " ("))
                   (setq other-tag
-                       (cond ((save-match-data (looking-back "\\<see"
+                       (cond ((save-match-data (looking-back "\\(^\\| \\)see"
                                                               (- (point) 3)))
                               "")
-                             ((save-match-data (looking-back "\\<in"
+                             ((save-match-data (looking-back "\\(^\\| \\)in"
                                                               (- (point) 2)))
                               "")
                              ((memq (char-before) '(nil ?\. ?! ??))
diff --git a/lisp/international/characters.el b/lisp/international/characters.el
index 0b6920c..5f610dd 100644
--- a/lisp/international/characters.el
+++ b/lisp/international/characters.el
@@ -759,7 +759,14 @@ with L, LRE, or LRO Unicode bidi character type.")
         (funcall map-unicode-property 'uppercase
                  (lambda (lc uc) (aset up lc uc) (aset up uc uc)))
         (funcall map-unicode-property 'lowercase
-                 (lambda (uc lc) (aset down uc lc) (aset down lc lc))))))
+                 (lambda (uc lc) (aset down uc lc) (aset down lc lc)))
+
+        ;; Override the Unicode uppercase property for ß, since we are
+        ;; using our case tables for determining the case of a
+        ;; character (see uppercasep and lowercasep in buffer.h).
+        ;; The special-uppercase property of ß ensures that it is
+        ;; still upcased to SS per the usual convention.
+        (aset up ?ß ?ẞ))))
 
   ;; Clear out the extra slots so that they will be recomputed from the main
   ;; (downcase) table and upcase table.  Since we’re side-stepping the usual
diff --git a/lisp/international/isearch-x.el b/lisp/international/isearch-x.el
index f50f86a..867a3d8 100644
--- a/lisp/international/isearch-x.el
+++ b/lisp/international/isearch-x.el
@@ -35,9 +35,8 @@
   (interactive)
   (let ((overriding-terminal-local-map nil))
     (toggle-input-method t))
-  (setq isearch-input-method-function input-method-function
-       isearch-input-method-local-p t)
-  (setq input-method-function nil)
+  (setq isearch-input-method-function input-method-function)
+  (setq-local input-method-function nil)
   (isearch-update))
 
 ;;;###autoload
@@ -46,9 +45,8 @@
   (interactive)
   (let ((overriding-terminal-local-map nil))
     (toggle-input-method))
-  (setq isearch-input-method-function input-method-function
-       isearch-input-method-local-p t)
-  (setq input-method-function nil)
+  (setq isearch-input-method-function input-method-function)
+  (setq-local input-method-function nil)
   (isearch-update))
 
 ;;;###autoload
@@ -57,9 +55,8 @@
   (interactive)
   (let ((overriding-terminal-local-map nil))
     (activate-transient-input-method))
-  (setq isearch-input-method-function input-method-function
-       isearch-input-method-local-p t)
-  (setq input-method-function nil)
+  (setq isearch-input-method-function input-method-function)
+  (setq-local input-method-function nil)
   (isearch-update))
 
 (defvar isearch-minibuffer-local-map
diff --git a/lisp/international/robin.el b/lisp/international/robin.el
index 94d2bf1..16cac07 100644
--- a/lisp/international/robin.el
+++ b/lisp/international/robin.el
@@ -424,8 +424,7 @@ While this input method is active, the variable
        (add-hook 'minibuffer-exit-hook 'robin-exit-from-minibuffer))
     (run-hooks 'input-method-activate-hook
               'robin-activate-hook)
-    (set (make-local-variable 'input-method-function)
-        'robin-input-method)))
+    (setq-local input-method-function 'robin-input-method)))
 
 (define-obsolete-variable-alias
   'robin-inactivate-hook
diff --git a/lisp/isearch.el b/lisp/isearch.el
index a0aa250..0d5c480 100644
--- a/lisp/isearch.el
+++ b/lisp/isearch.el
@@ -965,10 +965,6 @@ Each element is an `isearch--state' struct where the slots 
are
 ;; The value of input-method-function when isearch is invoked.
 (defvar isearch-input-method-function nil)
 
-;; A flag to tell if input-method-function is locally bound when
-;; isearch is invoked.
-(defvar isearch-input-method-local-p nil)
-
 (defvar isearch--saved-overriding-local-map nil)
 
 ;; Minor-mode-alist changes - kind of redundant with the
@@ -1238,7 +1234,6 @@ used to set the value of `isearch-regexp-function'."
        search-ring-yank-pointer nil
        isearch-opened-overlays nil
        isearch-input-method-function input-method-function
-       isearch-input-method-local-p (local-variable-p 'input-method-function)
        regexp-search-ring-yank-pointer nil
 
        isearch-pre-scroll-point nil
@@ -1259,9 +1254,7 @@ used to set the value of `isearch-regexp-function'."
   ;; We must bypass input method while reading key.  When a user type
   ;; printable character, appropriate input method is turned on in
   ;; minibuffer to read multibyte characters.
-  (or isearch-input-method-local-p
-      (make-local-variable 'input-method-function))
-  (setq input-method-function nil)
+  (setq-local input-method-function nil)
 
   (looking-at "")
   (setq isearch-window-configuration
@@ -1418,8 +1411,8 @@ NOPUSH is t and EDIT is t."
        (set-window-group-start (selected-window) found-start t))))
 
   (setq isearch-mode nil)
-  (if isearch-input-method-local-p
-      (setq input-method-function isearch-input-method-function)
+  (if isearch-input-method-function
+      (setq-local input-method-function isearch-input-method-function)
     (kill-local-variable 'input-method-function))
 
   (if isearch-tool-bar-old-map
diff --git a/lisp/language/korea-util.el b/lisp/language/korea-util.el
index 3821785..36e1d20 100644
--- a/lisp/language/korea-util.el
+++ b/lisp/language/korea-util.el
@@ -70,27 +70,24 @@
   (interactive)
   (let ((overriding-terminal-local-map nil))
     (toggle-korean-input-method))
-  (setq isearch-input-method-function input-method-function
-       isearch-input-method-local-p t)
-  (setq input-method-function nil)
+  (setq isearch-input-method-function input-method-function)
+  (setq-local input-method-function nil)
   (isearch-update))
 
 (defun isearch-hangul-switch-symbol-ksc ()
   (interactive)
   (let ((overriding-terminal-local-map nil))
     (quail-hangul-switch-symbol-ksc))
-  (setq isearch-input-method-function input-method-function
-       isearch-input-method-local-p t)
-  (setq input-method-function nil)
+  (setq isearch-input-method-function input-method-function)
+  (setq-local input-method-function nil)
   (isearch-update))
 
 (defun isearch-hangul-switch-hanja ()
   (interactive)
   (let ((overriding-terminal-local-map nil))
     (quail-hangul-switch-hanja))
-  (setq isearch-input-method-function input-method-function
-       isearch-input-method-local-p t)
-  (setq input-method-function nil)
+  (setq isearch-input-method-function input-method-function)
+  (setq-local input-method-function nil)
   (isearch-update))
 
 ;; Information for setting and exiting Korean environment.
diff --git a/lisp/language/korean.el b/lisp/language/korean.el
index 7e75815..9bd11b9 100644
--- a/lisp/language/korean.el
+++ b/lisp/language/korean.el
@@ -42,6 +42,7 @@
 
 (define-coding-system-alias 'euc-kr 'korean-iso-8bit)
 (define-coding-system-alias 'euc-korea 'korean-iso-8bit)
+(define-coding-system-alias 'ks_c_5601-1987 'korean-iso-8bit)
 
 (define-coding-system 'iso-2022-kr
   "ISO 2022 based 7-bit encoding for Korean KSC5601 (MIME:ISO-2022-KR)."
diff --git a/lisp/leim/quail/hangul.el b/lisp/leim/quail/hangul.el
index b856255..16f8de9 100644
--- a/lisp/leim/quail/hangul.el
+++ b/lisp/leim/quail/hangul.el
@@ -525,7 +525,7 @@ HELP-TEXT is a text set in `hangul-input-method-help-text'."
   (quail-delete-overlays)
   (if (eq (selected-window) (minibuffer-window))
       (add-hook 'minibuffer-exit-hook 'quail-exit-from-minibuffer))
-  (set (make-local-variable 'input-method-function) func))
+  (setq-local input-method-function func))
 
 (defun hangul-input-method-deactivate ()
   "Deactivate the current Hangul input method."
diff --git a/lisp/leim/quail/uni-input.el b/lisp/leim/quail/uni-input.el
index 6f1fbcc..bee73d8 100644
--- a/lisp/leim/quail/uni-input.el
+++ b/lisp/leim/quail/uni-input.el
@@ -105,8 +105,7 @@ While this input method is active, the variable
     (quail-delete-overlays)
     (if (eq (selected-window) (minibuffer-window))
        (add-hook 'minibuffer-exit-hook 'quail-exit-from-minibuffer))
-    (set (make-local-variable 'input-method-function)
-        'ucs-input-method)))
+    (setq-local input-method-function 'ucs-input-method)))
 
 (defun ucs-input-deactivate ()
   "Deactivate UCS input method."
diff --git a/lisp/locate.el b/lisp/locate.el
index 44a67ab..14fd260 100644
--- a/lisp/locate.el
+++ b/lisp/locate.el
@@ -319,9 +319,9 @@ then `locate-post-command-hook'."
        (erase-buffer)
 
        (setq locate-current-filter filter)
-       (set (make-local-variable 'locate-local-search) search-string)
-       (set (make-local-variable 'locate-local-filter) filter)
-       (set (make-local-variable 'locate-local-prompt) run-locate-command)
+        (setq-local locate-local-search search-string)
+        (setq-local locate-local-filter filter)
+        (setq-local locate-local-prompt run-locate-command)
 
        (if run-locate-command
            (shell-command search-string locate-buffer-name)
@@ -467,8 +467,8 @@ do not work in subdirectories.
        buffer-read-only    t)
   (add-to-invisibility-spec '(dired . t))
   (dired-alist-add-1 default-directory (point-min-marker))
-  (set (make-local-variable 'dired-directory) "/")
-  (set (make-local-variable 'dired-subdir-switches) locate-ls-subdir-switches)
+  (setq-local dired-directory "/")
+  (setq-local dired-subdir-switches locate-ls-subdir-switches)
   (setq dired-switches-alist nil)
   ;; This should support both Unix and Windoze style names
   (setq-local directory-listing-before-filename-regexp
diff --git a/lisp/mail/rmail.el b/lisp/mail/rmail.el
index 63d992d..3c74edd 100644
--- a/lisp/mail/rmail.el
+++ b/lisp/mail/rmail.el
@@ -1080,6 +1080,7 @@ The buffer is expected to be narrowed to just the header 
of the message."
     (define-key map [?\S-\ ] 'scroll-down-command)
     (define-key map "\177"   'scroll-down-command)
     (define-key map "?"      'describe-mode)
+    (define-key map "\C-c\C-d" 'rmail-epa-decrypt)
     (define-key map "\C-c\C-s\C-d" 'rmail-sort-by-date)
     (define-key map "\C-c\C-s\C-s" 'rmail-sort-by-subject)
     (define-key map "\C-c\C-s\C-a" 'rmail-sort-by-author)
@@ -1272,6 +1273,7 @@ Instead, these commands are available:
 \\[rmail-undelete-previous-message]    Undelete message.  Tries current 
message, then earlier messages
        till a deleted message is found.
 \\[rmail-edit-current-message] Edit the current message.  \\[rmail-cease-edit] 
to return to Rmail.
+\\[rmail-epa-decrypt]  Decrypt the current message.
 \\[rmail-expunge]      Expunge deleted messages.
 \\[rmail-expunge-and-save]     Expunge and save the file.
 \\[rmail-quit]       Quit Rmail: expunge, save, then switch to another buffer.
@@ -4610,11 +4612,10 @@ Argument MIME is non-nil if this is a mime message."
                     "> ")
              (push (rmail-epa-decrypt-1 mime) decrypts))))
 
-      (when (and decrypts (eq major-mode 'rmail-mode))
-        (rmail-add-label "decrypt"))
-
       (when (and decrypts (rmail-buffers-swapped-p))
        (when (y-or-n-p "Replace the original message? ")
+          (when (eq major-mode 'rmail-mode)
+            (rmail-add-label "decrypt"))
          (setq decrypts (nreverse decrypts))
          (let ((beg (rmail-msgbeg rmail-current-message))
                (end (rmail-msgend rmail-current-message)))
diff --git a/lisp/mail/rmailsum.el b/lisp/mail/rmailsum.el
index a085e0b..9ccc0cf 100644
--- a/lisp/mail/rmailsum.el
+++ b/lisp/mail/rmailsum.el
@@ -121,6 +121,7 @@ Setting this option to nil might speed up the generation of 
summaries."
     (define-key map [?\S-\ ] 'rmail-summary-scroll-msg-down)
     (define-key map "\177"   'rmail-summary-scroll-msg-down)
     (define-key map "?"      'describe-mode)
+    (define-key map "\C-c\C-d"      'rmail-summary-epa-decrypt)
     (define-key map "\C-c\C-n" 'rmail-summary-next-same-subject)
     (define-key map "\C-c\C-p" 'rmail-summary-previous-same-subject)
     (define-key map "\C-c\C-s\C-d" 'rmail-summary-sort-by-date)
@@ -1482,6 +1483,12 @@ argument says to read a file name and use that file as 
the inbox."
   (rmail-edit-current-message)
   (use-local-map rmail-summary-edit-map))
 
+(defun rmail-summary-epa-decrypt ()
+  "Decrypt this message."
+  (interactive)
+  (rmail-pop-to-buffer rmail-buffer)
+  (rmail-epa-decrypt))
+
 (defun rmail-summary-cease-edit ()
   "Finish editing message, then go back to Rmail summary buffer."
   (interactive)
diff --git a/lisp/man.el b/lisp/man.el
index 991b1bb..8430201 100644
--- a/lisp/man.el
+++ b/lisp/man.el
@@ -1583,10 +1583,10 @@ The following key bindings are currently in effect in 
the buffer:
   (auto-fill-mode -1)
   (setq imenu-generic-expression (list (list nil Man-heading-regexp 0)))
   (imenu-add-to-menubar man-imenu-title)
-  (set (make-local-variable 'outline-regexp) Man-heading-regexp)
-  (set (make-local-variable 'outline-level) (lambda () 1))
-  (set (make-local-variable 'bookmark-make-record-function)
-       'Man-bookmark-make-record)
+  (setq-local outline-regexp Man-heading-regexp)
+  (setq-local outline-level (lambda () 1))
+  (setq-local bookmark-make-record-function
+              #'Man-bookmark-make-record)
   (add-hook 'window-state-change-functions #'Man--window-state-change nil t))
 
 (defun Man-build-section-list ()
diff --git a/lisp/master.el b/lisp/master.el
index 32556a5..88baa1f 100644
--- a/lisp/master.el
+++ b/lisp/master.el
@@ -96,8 +96,7 @@ yourself the value of `master-of' by calling 
`master-show-slave'."
   "Makes BUFFER the slave of the current buffer.
 Use \\[master-mode] to toggle control of the slave buffer."
   (interactive "bSlave: ")
-  (make-local-variable 'master-of)
-  (setq master-of buffer)
+  (setq-local master-of buffer)
   (run-hooks 'master-set-slave-hook))
 
 (defun master-show-slave ()
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index d44d896..456193d 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -2067,14 +2067,14 @@ variables.")
                               (funcall aff-fun completions)))
 
                       (with-current-buffer standard-output
-                        (set (make-local-variable 'completion-base-position)
+                        (setq-local completion-base-position
                              (list (+ start base-size)
                                    ;; FIXME: We should pay attention to 
completion
                                    ;; boundaries here, but currently
                                    ;; completion-all-completions does not give 
us the
                                    ;; necessary information.
                                    end))
-                        (set (make-local-variable 
'completion-list-insert-choice-function)
+                        (setq-local completion-list-insert-choice-function
                              (let ((ctable minibuffer-completion-table)
                                    (cpred minibuffer-completion-predicate)
                                    (cprops completion-extra-properties))
@@ -2866,7 +2866,7 @@ See `read-file-name' for the meaning of the arguments."
                           ;; On the first request on `M-n' fill
                           ;; `minibuffer-default' with a list of defaults
                           ;; relevant for file-name reading.
-                          (set (make-local-variable 
'minibuffer-default-add-function)
+                          (setq-local minibuffer-default-add-function
                                (lambda ()
                                  (with-current-buffer
                                      (window-buffer 
(minibuffer-selected-window))
diff --git a/lisp/net/rcirc.el b/lisp/net/rcirc.el
index 63e6eed..c4b68f1 100644
--- a/lisp/net/rcirc.el
+++ b/lisp/net/rcirc.el
@@ -416,6 +416,9 @@ will be killed."
 (defvar rcirc-server-buffer nil
   "The server buffer associated with this channel buffer.")
 
+(defvar rcirc-server-parameters nil
+  "List of parameters received from the server.")
+
 (defvar rcirc-target nil
   "The channel or user associated with this buffer.")
 
@@ -586,6 +589,7 @@ If ARG is non-nil, instead prompt for connection 
parameters."
       (setq-local rcirc-user-disconnect nil)
       (setq-local rcirc-user-authenticated nil)
       (setq-local rcirc-connecting t)
+      (setq-local rcirc-server-parameters nil)
 
       (add-hook 'auto-save-hook 'rcirc-log-write)
 
@@ -2873,9 +2877,28 @@ Not in rfc1459.txt"
 (defun rcirc-handler-433 (process sender args text)
   "ERR_NICKNAMEINUSE"
   (rcirc-handler-generic process "433" sender args text)
-  (let* ((new-nick (concat (cadr args) "`")))
-    (with-rcirc-process-buffer process
-      (rcirc-cmd-nick new-nick nil process))))
+  (with-rcirc-process-buffer process
+    (let* ((length (string-to-number
+                    (or (rcirc-server-parameter-value 'nicklen)
+                        "16"))))
+      (rcirc-cmd-nick (rcirc--make-new-nick (cadr args) length) nil process))))
+
+(defun rcirc--make-new-nick (nick length)
+  ;; If we already have some ` chars at the end, then shorten the
+  ;; non-` bit of the name.
+  (when (= (length nick) length)
+    (setq nick (replace-regexp-in-string "[^`]\\(`+\\)\\'" "\\1" nick)))
+  (concat
+   (if (>= (length nick) length)
+       (substring nick 0 (1- length))
+     nick)
+   "`"))
+
+(defun rcirc-handler-005 (process sender args text)
+  "ERR_NICKNAMEINUSE"
+  (rcirc-handler-generic process "005" sender args text)
+  (with-rcirc-process-buffer process
+    (setq rcirc-server-parameters (append rcirc-server-parameters args))))
 
 (defun rcirc-authenticate ()
   "Send authentication to process associated with current buffer.
@@ -3072,6 +3095,13 @@ Passwords are stored in `rcirc-authinfo' (which see)."
   (>= (point) rcirc-prompt-end-marker))
 
 
+(defun rcirc-server-parameter-value (parameter)
+  (cl-loop for elem in rcirc-server-parameters
+           for setting = (split-string elem "=")
+           when (and (= (length setting) 2)
+                     (string-equal (downcase (car setting)) parameter))
+           return (cadr setting)))
+
 (provide 'rcirc)
 
 ;;; rcirc.el ends here
diff --git a/lisp/net/socks.el b/lisp/net/socks.el
index 9b22a50..cb50a0a 100644
--- a/lisp/net/socks.el
+++ b/lisp/net/socks.el
@@ -260,7 +260,7 @@
     (setq state (process-get proc 'socks-state))
     (cond
      ((= state socks-state-waiting-for-auth)
-      (cl-callf (lambda (s) (setq string (concat string s)))
+      (cl-callf (lambda (s) (setq string (concat s string)))
           (process-get proc 'socks-scratch))
       (if (< (length string) 2)
          nil                           ; We need to spin some more
@@ -272,7 +272,7 @@
      ((= state socks-state-authenticated)
       )
      ((= state socks-state-waiting)
-      (cl-callf (lambda (s) (setq string (concat string s)))
+      (cl-callf (lambda (s) (setq string (concat s string)))
           (process-get proc 'socks-scratch))
       (setq version (process-get proc 'socks-server-protocol))
       (cond
@@ -542,7 +542,7 @@
                              service))
         (process-put proc 'socks-buffer buffer)
         (process-put proc 'socks-host host)
-        (process-put proc 'socks-service host)
+        (process-put proc 'socks-service service)
         (set-process-filter proc nil)
         (set-process-buffer proc (if buffer (get-buffer-create buffer)))
         proc))))
diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el
index 4947d16..f6e8933 100644
--- a/lisp/net/tramp-adb.el
+++ b/lisp/net/tramp-adb.el
@@ -1260,6 +1260,9 @@ connection if a previous connection has died for some 
reason."
            (process-put p 'adjust-window-size-function #'ignore)
            (set-process-query-on-exit-flag p nil)
 
+           ;; Set connection-local variables.
+           (tramp-set-connection-local-variables vec)
+
            ;; Change prompt.
            (tramp-set-connection-property
             p "prompt" (regexp-quote (format "///%s#$" prompt)))
@@ -1312,9 +1315,6 @@ connection if a previous connection has died for some 
reason."
                (tramp-error
                 vec 'file-error "Cannot switch to user `%s'" user)))
 
-           ;; Set connection-local variables.
-           (tramp-set-connection-local-variables vec)
-
            ;; Mark it as connected.
            (tramp-set-connection-property p "connected" t)))))))
 
diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el
index f3d03d0..1722c53 100644
--- a/lisp/net/tramp-gvfs.el
+++ b/lisp/net/tramp-gvfs.el
@@ -1434,6 +1434,9 @@ If FILE-SYSTEM is non-nil, return file system attributes."
        (unless (process-live-p p)
          (tramp-error
           p 'file-notify-error "Monitoring not supported for `%s'" file-name))
+       ;; Set "gio-file-monitor" property.  We believe, that "gio
+       ;; monitor" uses polling when applied for mounted files.
+       (tramp-set-connection-property p "gio-file-monitor" 'GPollFileMonitor)
        p))))
 
 (defun tramp-gvfs-monitor-process-filter (proc string)
@@ -2112,7 +2115,10 @@ connection if a previous connection has died for some 
reason."
              :buffer (tramp-get-connection-buffer vec)
              :server t :host 'local :service t :noquery t)))
       (process-put p 'vector vec)
-      (set-process-query-on-exit-flag p nil)))
+      (set-process-query-on-exit-flag p nil)
+
+      ;; Set connection-local variables.
+      (tramp-set-connection-local-variables vec)))
 
   (unless (tramp-gvfs-connection-mounted-p vec)
     (let ((method (tramp-file-name-method vec))
@@ -2216,9 +2222,6 @@ connection if a previous connection has died for some 
reason."
          (and (functionp tramp-password-save-function)
               (funcall tramp-password-save-function)))
 
-       ;; Set connection-local variables.
-       (tramp-set-connection-local-variables vec)
-
        ;; Mark it as connected.
        (tramp-set-connection-property
         (tramp-get-connection-process vec) "connected" t)))))
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index 1ce6542..98537a1 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -480,7 +480,7 @@ The string is used in `tramp-methods'.")
 ;; Solaris: /usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin
 ;; GNU/Linux (Debian, Suse, RHEL): /bin:/usr/bin
 ;; FreeBSD, DragonFly: /usr/bin:/bin:/usr/sbin:/sbin: - beware trailing ":"!
-;; Darwin: /usr/bin:/bin:/usr/sbin:/sbin
+;; FreeBSD 12.1, Darwin: /usr/bin:/bin:/usr/sbin:/sbin
 ;; IRIX64: /usr/bin
 ;; QNAP QTS: ---
 ;; Hydra: /run/current-system/sw/bin:/bin:/usr/bin
@@ -595,10 +595,12 @@ rm -f %t"
   "Shell function to implement `uudecode' to standard output.
 Many systems support `uudecode -o /dev/stdout' or `uudecode -o -'
 for this or `uudecode -p', but some systems don't, and for them
-we have this shell function.")
+we have this shell function.
+Format specifiers are replaced by `tramp-expand-script', percent
+characters need to be doubled.")
 
 (defconst tramp-perl-file-truename
-  "%s -e '
+  "%p -e '
 use File::Spec;
 use Cwd \"realpath\";
 
@@ -633,14 +635,14 @@ if (!$result) {
 
 $result =~ s/\"/\\\\\"/g;
 print \"\\\"$result\\\"\\n\";
-' \"$1\" 2>/dev/null"
+' \"$1\" %n"
   "Perl script to produce output suitable for use with `file-truename'
 on the remote file system.
-Escape sequence %s is replaced with name of Perl binary.
-This string is passed to `format', so percent characters need to be doubled.")
+Format specifiers are replaced by `tramp-expand-script', percent
+characters need to be doubled.")
 
 (defconst tramp-perl-file-name-all-completions
-  "%s -e '
+  "%p -e '
 opendir(d, $ARGV[0]) || die(\"$ARGV[0]: $!\\nfail\\n\");
 @files = readdir(d); closedir(d);
 foreach $f (@files) {
@@ -652,11 +654,11 @@ foreach $f (@files) {
  }
 }
 print \"ok\\n\"
-' \"$1\" 2>/dev/null"
+' \"$1\" %n"
   "Perl script to produce output suitable for use with
-`file-name-all-completions' on the remote file system.  Escape
-sequence %s is replaced with name of Perl binary.  This string is
-passed to `format', so percent characters need to be doubled.")
+`file-name-all-completions' on the remote file system.
+Format specifiers are replaced by `tramp-expand-script', percent
+characters need to be doubled.")
 
 ;; Perl script to implement `file-attributes' in a Lisp `read'able
 ;; output.  If you are hacking on this, note that you get *no* output
@@ -665,7 +667,7 @@ passed to `format', so percent characters need to be 
doubled.")
 ;; The device number is returned as "-1", because there will be a virtual
 ;; device number set in `tramp-sh-handle-file-attributes'.
 (defconst tramp-perl-file-attributes
-  "%s -e '
+  "%p -e '
 @stat = lstat($ARGV[0]);
 if (!@stat) {
     print \"nil\\n\";
@@ -702,14 +704,14 @@ printf(
     $stat[7],
     $stat[2],
     $stat[1]
-);' \"$1\" \"$2\" 2>/dev/null"
+);' \"$1\" \"$2\" %n"
   "Perl script to produce output suitable for use with `file-attributes'
 on the remote file system.
-Escape sequence %s is replaced with name of Perl binary.
-This string is passed to `format', so percent characters need to be doubled.")
+Format specifiers are replaced by `tramp-expand-script', percent
+characters need to be doubled.")
 
 (defconst tramp-perl-directory-files-and-attributes
-  "%s -e '
+  "%p -e '
 chdir($ARGV[0]) or printf(\"\\\"Cannot change to $ARGV[0]: $''!''\\\"\\n\"), 
exit();
 opendir(DIR,\".\") or printf(\"\\\"Cannot open directory $ARGV[0]: 
$''!''\\\"\\n\"), exit();
 @list = readdir(DIR);
@@ -754,31 +756,31 @@ for($i = 0; $i < $n; $i++)
         $stat[2],
         $stat[1]);
 }
-printf(\")\\n\");' \"$1\" \"$2\" 2>/dev/null"
+printf(\")\\n\");' \"$1\" \"$2\" %n"
   "Perl script implementing `directory-files-and-attributes' as Lisp `read'able
 output.
-Escape sequence %s is replaced with name of Perl binary.
-This string is passed to `format', so percent characters need to be doubled.")
+Format specifiers are replaced by `tramp-expand-script', percent
+characters need to be doubled.")
 
 ;; These two use base64 encoding.
 (defconst tramp-perl-encode-with-module
-  "%s -MMIME::Base64 -0777 -ne 'print encode_base64($_)' %n"
+  "%p -MMIME::Base64 -0777 -ne 'print encode_base64($_)' %n"
   "Perl program to use for encoding a file.
-Escape sequence %s is replaced with name of Perl binary.
-This string is passed to `format', so percent characters need to be doubled.
 This implementation requires the MIME::Base64 Perl module to be installed
-on the remote host.")
+on the remote host.
+Format specifiers are replaced by `tramp-expand-script', percent
+characters need to be doubled.")
 
 (defconst tramp-perl-decode-with-module
-  "%s -MMIME::Base64 -0777 -ne 'print decode_base64($_)' %n"
+  "%p -MMIME::Base64 -0777 -ne 'print decode_base64($_)' %n"
   "Perl program to use for decoding a file.
-Escape sequence %s is replaced with name of Perl binary.
-This string is passed to `format', so percent characters need to be doubled.
 This implementation requires the MIME::Base64 Perl module to be installed
-on the remote host.")
+on the remote host.
+Format specifiers are replaced by `tramp-expand-script', percent
+characters need to be doubled.")
 
 (defconst tramp-perl-encode
-  "%s -e '
+  "%p -e '
 # This script contributed by Juanma Barranquero <lektu@terra.es>.
 # Copyright (C) 2002-2020 Free Software Foundation, Inc.
 use strict;
@@ -813,11 +815,11 @@ while (read STDIN, $data, 54) {
                 qq(\\n);
 }' %n"
   "Perl program to use for encoding a file.
-Escape sequence %s is replaced with name of Perl binary.
-This string is passed to `format', so percent characters need to be doubled.")
+Format specifiers are replaced by `tramp-expand-script', percent
+characters need to be doubled.")
 
 (defconst tramp-perl-decode
-  "%s -e '
+  "%p -e '
 # This script contributed by Juanma Barranquero <lektu@terra.es>.
 # Copyright (C) 2002-2020 Free Software Foundation, Inc.
 use strict;
@@ -857,22 +859,25 @@ while (my $data = <STDIN>) {
     last if $finished;
 }' %n"
   "Perl program to use for decoding a file.
-Escape sequence %s is replaced with name of Perl binary.
-This string is passed to `format', so percent characters need to be doubled.")
+Format specifiers are replaced by `tramp-expand-script', percent
+characters need to be doubled.")
 
 (defconst tramp-perl-pack
-  "%s -e 'binmode STDIN; binmode STDOUT; print pack(q{u*}, join q{}, <>)'"
+  "%p -e 'binmode STDIN; binmode STDOUT; print pack(q{u*}, join q{}, <>)' %n"
   "Perl program to use for encoding a file.
-Escape sequence %s is replaced with name of Perl binary.")
+Format specifiers are replaced by `tramp-expand-script', percent
+characters need to be doubled.")
 
 (defconst tramp-perl-unpack
-  "%s -e 'binmode STDIN; binmode STDOUT; print unpack(q{u*}, join q{}, <>)'"
+  "%p -e 'binmode STDIN; binmode STDOUT; print unpack(q{u*}, join q{}, <>)' %n"
   "Perl program to use for decoding a file.
-Escape sequence %s is replaced with name of Perl binary.")
+Format specifiers are replaced by `tramp-expand-script', percent
+characters need to be doubled.")
 
 (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.")
+Format specifiers are replaced by `tramp-expand-script', percent
+characters need to be doubled.")
 
 (defconst tramp-awk-encode
   "%a '\\
@@ -906,21 +911,24 @@ END {
   printf tail
 }'"
   "`awk' program to use for encoding a file.
-This string is passed to `format', so percent characters need to be doubled.")
+Format specifiers are replaced by `tramp-expand-script', 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.")
+Format specifiers are replaced by `tramp-expand-script', 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.")
+Format specifiers are replaced by `tramp-expand-script', percent
+characters need to be doubled.")
 
-(defconst tramp-od-awk-encode
-  (format "%s | %s" tramp-od-encode tramp-awk-encode)
+(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.")
+Format specifiers are replaced by `tramp-expand-script', percent
+characters need to be doubled.")
 
 (defconst tramp-awk-decode
   "%a '\\
@@ -946,7 +954,8 @@ BEGIN {
   }
 }'"
   "Awk program to use for decoding a file.
-This string is passed to `format', so percent characters need to be doubled.")
+Format specifiers are replaced by `tramp-expand-script', percent
+characters need to be doubled.")
 
 (defconst tramp-vc-registered-read-file-names
   "echo \"(\"
@@ -968,7 +977,8 @@ echo \")\""
 It must be send formatted with two strings; the tests for file
 existence, and file readability.  Input shall be read via
 here-document, otherwise the command could exceed maximum length
-of command line.")
+of command line.
+Format specifiers \"%s\" are replaced before the script is used.")
 
 ;; New handlers should be added here.
 ;;;###tramp-autoload
@@ -3296,7 +3306,9 @@ implementation will be used."
                  ;; correctly.  Unset `file-name-handler-alist'.
                  ;; Otherwise, epa-file gets confused.
                  (let (file-name-handler-alist
-                       (coding-system-for-write 'binary))
+                       (coding-system-for-write 'binary)
+                       (default-directory
+                         (tramp-compat-temporary-file-directory)))
                    (with-temp-file tmpfile
                      (set-buffer-multibyte nil)
                      (insert-buffer-substring (tramp-get-buffer v))
@@ -3822,6 +3834,10 @@ Fall back to normal file name handler if no Tramp 
handler exists."
        (unless (process-live-p p)
          (tramp-error
           p 'file-notify-error "Monitoring not supported for `%s'" file-name))
+       ;; Set "gio-file-monitor" property if needed.
+       (when (string-equal (file-name-nondirectory command) "gio")
+         (tramp-set-connection-property
+          p "gio-file-monitor" (tramp-get-remote-gio-file-monitor v)))
        p))))
 
 (defun tramp-sh-gio-monitor-process-filter (proc string)
@@ -3994,6 +4010,51 @@ Fall back to normal file name handler if no Tramp 
handler exists."
 
 ;;; Internal Functions:
 
+(defun tramp-expand-script (vec script)
+  "Expand SCRIPT with remote files or commands.
+\"%a\", \"%h\", \"%o\" and \"%p\" format specifiers are replaced
+by the respective `awk', `hexdump', `od' and `perl' commands.
+\"%n\" is replaced by \"2>/dev/null\", and \"%t\" is replaced by
+a temporary file name.
+If VEC is nil, the respective local commands are used.
+If there is a format specifier which cannot be expanded, this
+function returns nil."
+  (if (not (string-match-p "\\(^\\|[^%]\\)%[ahnopt]" script))
+      script
+    (catch 'wont-work
+      (let ((awk (when (string-match-p "\\(^\\|[^%]\\)%a" script)
+                  (or
+                   (if vec (tramp-get-remote-awk vec) (executable-find "awk"))
+                   (throw 'wont-work nil))))
+           (hdmp (when (string-match-p "\\(^\\|[^%]\\)%h" script)
+                   (or
+                    (if vec (tramp-get-remote-hexdump vec)
+                      (executable-find "hexdump"))
+                    (throw 'wont-work nil))))
+           (dev (when (string-match-p "\\(^\\|[^%]\\)%n" script)
+                  (or
+                   (if vec (concat "2>" (tramp-get-remote-null-device vec))
+                     (if (eq system-type 'windows-nt) ""
+                       (concat "2>" null-device)))
+                   (throw 'wont-work nil))))
+           (od (when (string-match-p "\\(^\\|[^%]\\)%o" script)
+                 (or (if vec (tramp-get-remote-od vec) (executable-find "od"))
+                     (throw 'wont-work nil))))
+           (perl (when (string-match-p "\\(^\\|[^%]\\)%p" script)
+                   (or
+                    (if vec
+                        (tramp-get-remote-perl vec) (executable-find "perl"))
+                    (throw 'wont-work nil))))
+           (tmp (when (string-match-p "\\(^\\|[^%]\\)%t" script)
+                  (or
+                   (if vec
+                       (tramp-file-local-name (tramp-make-tramp-temp-name vec))
+                     (tramp-compat-make-temp-name))
+                   (throw 'wont-work nil)))))
+       (format-spec
+        script
+        (format-spec-make ?a awk ?h hdmp ?n dev ?o od ?p perl ?t tmp))))))
+
 (defun tramp-maybe-send-script (vec script name)
   "Define in remote shell function NAME implemented as SCRIPT.
 Only send the definition if it has not already been done."
@@ -4008,14 +4069,15 @@ Only send the definition if it has not already been 
done."
        ;; could result in unwanted command expansion.  Avoid this.
        (setq script (tramp-compat-string-replace
                      (make-string 1 ?\t) (make-string 8 ? ) script))
-       ;; The script could contain a call of Perl.  This is masked with `%s'.
-       (when (and (string-match-p "%s" script)
-                  (not (tramp-get-remote-perl vec)))
-         (tramp-error vec 'file-error "No Perl available on remote host"))
+       ;; Expand format specifiers.
+       (unless (setq script (tramp-expand-script vec script))
+         (tramp-error
+          vec 'file-error
+          (format "Script %s is not applicable on remote host" name)))
+       ;; Send it.
        (tramp-barf-unless-okay
         vec
-        (format "%s () {\n%s\n}"
-                name (format script (tramp-get-remote-perl vec)))
+        (format "%s () {\n%s\n}" name script)
         "Script %s sending failed" name)
        (tramp-set-connection-property
         (tramp-get-connection-process vec) "scripts" (cons name scripts))))))
@@ -4523,7 +4585,7 @@ process to set up.  VEC specifies the connection."
 (defconst tramp-local-coding-commands
   `((b64 base64-encode-region base64-decode-region)
     (uu  tramp-uuencode-region uudecode-decode-region)
-    (pack ,(format tramp-perl-pack "perl") ,(format tramp-perl-unpack "perl")))
+    (pack ,tramp-perl-pack ,tramp-perl-unpack))
   "List of local coding commands for inline transfer.
 Each item is a list that looks like this:
 
@@ -4613,6 +4675,8 @@ Goes through the list `tramp-local-coding-commands' and
                 vec 5 "Checking local encoding function `%s'" loc-enc)
              (tramp-message
               vec 5 "Checking local encoding command `%s' for sanity" loc-enc)
+             (unless (stringp (setq loc-enc (tramp-expand-script nil loc-enc)))
+               (throw 'wont-work-local nil))
              (unless (zerop (tramp-call-local-coding-command loc-enc nil nil))
                (throw 'wont-work-local nil)))
            (if (not (stringp loc-dec))
@@ -4620,6 +4684,8 @@ Goes through the list `tramp-local-coding-commands' and
                 vec 5 "Checking local decoding function `%s'" loc-dec)
              (tramp-message
               vec 5 "Checking local decoding command `%s' for sanity" loc-dec)
+             (unless (stringp (setq loc-dec (tramp-expand-script nil loc-dec)))
+               (throw 'wont-work-local nil))
              (unless (zerop (tramp-call-local-coding-command loc-dec nil nil))
                (throw 'wont-work-local nil)))
            ;; Search for remote coding commands with the same format
@@ -4647,35 +4713,8 @@ Goes through the list `tramp-local-coding-commands' and
                  (unless (stringp 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)))
-                     (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)
-                               ?n (concat
-                                    "2>" (tramp-get-remote-null-device vec))
-                               ?o (tramp-get-remote-od vec)))
-                             value (tramp-compat-string-replace "%" "%%" 
value)))
                      (tramp-maybe-send-script vec value name)
                      (setq rem-enc name)))
                  (tramp-message
@@ -4690,28 +4729,9 @@ Goes through the list `tramp-local-coding-commands' and
 
                  (unless (stringp rem-dec)
                    (let ((name (symbol-name rem-dec))
-                         (value (symbol-value rem-dec))
-                         tmpfile)
+                         (value (symbol-value rem-dec)))
                      (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)
-                               ?n (concat
-                                    "2>" (tramp-get-remote-null-device vec))
-                               ?o (tramp-get-remote-od vec)))
-                             value (tramp-compat-string-replace "%" "%%" 
value)))
-                     (when (string-match-p "\\(^\\|[^%]\\)%t" value)
-                       (setq tmpfile (tramp-make-tramp-temp-name vec)
-                             value
-                             (format-spec
-                              value
-                              (format-spec-make
-                               ?t (tramp-file-local-name tmpfile)))))
                      (tramp-maybe-send-script vec value name)
                      (setq rem-dec name)))
                  (tramp-message
@@ -5014,6 +5034,9 @@ connection if a previous connection has died for some 
reason."
 
                (tramp-message vec 6 "%s" (string-join (process-command p) " "))
 
+               ;; Set connection-local variables.
+               (tramp-set-connection-local-variables vec)
+
                ;; Check whether process is alive.
                (tramp-barf-if-no-shell-prompt
                 p 10
@@ -5123,9 +5146,6 @@ connection if a previous connection has died for some 
reason."
                  (setq options ""
                        target-alist (cdr target-alist)))
 
-               ;; Set connection-local variables.
-               (tramp-set-connection-local-variables vec)
-
                ;; Activate session timeout.
                (when (tramp-get-connection-property p "session-timeout" nil)
                  (run-at-time
@@ -5737,6 +5757,30 @@ This command is returned only if 
`delete-by-moving-to-trash' is non-nil."
     (tramp-message vec 5 "Finding a suitable `gio-monitor' command")
     (tramp-find-executable vec "gio" (tramp-get-remote-path vec) t t)))
 
+(defun tramp-get-remote-gio-file-monitor (vec)
+  "Determine remote GFileMonitor."
+  (with-tramp-connection-property vec "gio-file-monitor"
+    (with-current-buffer (tramp-get-connection-buffer vec)
+      (tramp-message vec 5 "Finding the used GFileMonitor")
+      (when-let ((gio (tramp-get-remote-gio-monitor vec)))
+       ;; Search for the used FileMonitor.  There is no known way to
+       ;; get this information directly from gio, so we check for
+       ;; linked libraries of libgio.
+       (when (tramp-send-command-and-check vec (concat "ldd " gio))
+         (goto-char (point-min))
+         (when (re-search-forward "\\S-+/libgio\\S-+")
+           (when (tramp-send-command-and-check
+                  vec (concat "strings " (match-string 0)))
+             (goto-char (point-min))
+             (re-search-forward
+              (format
+               "^%s$"
+               (regexp-opt
+                '("GFamFileMonitor" "GFenFileMonitor"
+                  "GInotifyFileMonitor" "GKqueueFileMonitor")))
+              nil 'noerror)
+             (intern (match-string 0)))))))))
+
 (defun tramp-get-remote-gvfs-monitor-dir (vec)
   "Determine remote `gvfs-monitor-dir' command."
   (with-tramp-connection-property vec "gvfs-monitor-dir"
diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el
index e521371..83c1b58 100644
--- a/lisp/net/tramp-smb.el
+++ b/lisp/net/tramp-smb.el
@@ -2040,6 +2040,9 @@ If ARGUMENT is non-nil, use it as argument for
              (process-put p 'adjust-window-size-function #'ignore)
              (set-process-query-on-exit-flag p nil)
 
+             ;; Set connection-local variables.
+             (tramp-set-connection-local-variables vec)
+
              (condition-case err
                  (let ((inhibit-message t))
                    ;; Play login scenario.
@@ -2073,9 +2076,6 @@ If ARGUMENT is non-nil, use it as argument for
                    (tramp-set-connection-property p "smb-share" share)
                    (tramp-set-connection-property p "chunksize" 1)
 
-                   ;; Set connection-local variables.
-                   (tramp-set-connection-local-variables vec)
-
                    ;; Mark it as connected.
                    (tramp-set-connection-property p "connected" t))
 
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index b3853aa..6750a7f 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -5210,6 +5210,8 @@ Invokes `password-read' if available, `read-passwd' else."
                (tramp-check-for-regexp proc tramp-password-prompt-regexp)
                (format "%s for %s " (capitalize (match-string 1)) key))))
         (auth-source-creation-prompts `((secret . ,pw-prompt)))
+        ;; Use connection-local value.
+        (auth-sources (with-current-buffer (process-buffer proc) auth-sources))
         ;; We suspend the timers while reading the password.
          (stimers (with-timeout-suspend))
         auth-info auth-passwd)
@@ -5250,7 +5252,7 @@ Invokes `password-read' if available, `read-passwd' else."
                   (setq auth-passwd (funcall auth-passwd)))
                 auth-passwd)
 
-              ;; Try the password cache.
+              ;; Try the password cache.  Exists since Emacs 26.1.
               (progn
                 (setq auth-passwd (password-read pw-prompt key)
                       tramp-password-save-function
diff --git a/lisp/newcomment.el b/lisp/newcomment.el
index 3eb158d..5d318bb 100644
--- a/lisp/newcomment.el
+++ b/lisp/newcomment.el
@@ -304,7 +304,7 @@ This is useful when style-conventions require a certain 
minimal offset.
 Python's PEP8 for example recommends two spaces, so you could do:
 
 \(add-hook \\='python-mode-hook
-   (lambda () (set (make-local-variable \\='comment-inline-offset) 2)))
+   (lambda () (setq-local comment-inline-offset 2)))
 
 See `comment-padding' for whole-line comments."
   :version "24.3"
@@ -361,21 +361,21 @@ function should first call this function explicitly."
       (let ((cs (read-string "No comment syntax is defined.  Use: ")))
        (if (zerop (length cs))
            (error "No comment syntax defined")
-         (set (make-local-variable 'comment-start) cs)
-         (set (make-local-variable 'comment-start-skip) cs))))
+          (setq-local comment-start cs)
+          (setq-local comment-start-skip cs))))
     ;; comment-use-syntax
     (when (eq comment-use-syntax 'undecided)
-      (set (make-local-variable 'comment-use-syntax)
-          (let ((st (syntax-table))
-                (cs comment-start)
-                (ce (if (string= "" comment-end) "\n" comment-end)))
-            ;; Try to skip over a comment using forward-comment
-            ;; to see if the syntax tables properly recognize it.
-            (with-temp-buffer
-              (set-syntax-table st)
-              (insert cs " hello " ce)
-              (goto-char (point-min))
-              (and (forward-comment 1) (eobp))))))
+      (setq-local comment-use-syntax
+                  (let ((st (syntax-table))
+                        (cs comment-start)
+                        (ce (if (string= "" comment-end) "\n" comment-end)))
+                    ;; Try to skip over a comment using forward-comment
+                    ;; to see if the syntax tables properly recognize it.
+                    (with-temp-buffer
+                      (set-syntax-table st)
+                      (insert cs " hello " ce)
+                      (goto-char (point-min))
+                      (and (forward-comment 1) (eobp))))))
     ;; comment-padding
     (unless comment-padding (setq comment-padding 0))
     (when (integerp comment-padding)
@@ -385,9 +385,9 @@ function should first call this function explicitly."
     ;;(setq comment-end (comment-string-strip comment-end nil t))
     ;; comment-continue
     (unless (or comment-continue (string= comment-end ""))
-      (set (make-local-variable 'comment-continue)
-          (concat (if (string-match "\\S-\\S-" comment-start) " " "|")
-                  (substring comment-start 1)))
+      (setq-local comment-continue
+                  (concat (if (string-match "\\S-\\S-" comment-start) " " "|")
+                          (substring comment-start 1)))
       ;; Hasn't been necessary yet.
       ;; (unless (string-match comment-start-skip comment-continue)
       ;;       (kill-local-variable 'comment-continue))
@@ -396,29 +396,29 @@ function should first call this function explicitly."
     (unless (and comment-start-skip
                 ;; In case comment-start has changed since last time.
                 (string-match comment-start-skip comment-start))
-      (set (make-local-variable 'comment-start-skip)
-          (concat (unless (eq comment-use-syntax t)
-                     ;; `syntax-ppss' will detect escaping.
-                     "\\(\\(^\\|[^\\\n]\\)\\(\\\\\\\\\\)*\\)")
-                   "\\(?:\\s<+\\|"
-                  (regexp-quote (comment-string-strip comment-start t t))
-                  ;; Let's not allow any \s- but only [ \t] since \n
-                  ;; might be both a comment-end marker and \s-.
-                  "+\\)[ \t]*")))
+      (setq-local comment-start-skip
+                  (concat (unless (eq comment-use-syntax t)
+                            ;; `syntax-ppss' will detect escaping.
+                            "\\(\\(^\\|[^\\\n]\\)\\(\\\\\\\\\\)*\\)")
+                          "\\(?:\\s<+\\|"
+                          (regexp-quote (comment-string-strip comment-start t 
t))
+                          ;; Let's not allow any \s- but only [ \t] since \n
+                          ;; might be both a comment-end marker and \s-.
+                          "+\\)[ \t]*")))
     (unless (and comment-end-skip
                 ;; In case comment-end has changed since last time.
                 (string-match comment-end-skip
                                (if (string= "" comment-end) "\n" comment-end)))
       (let ((ce (if (string= "" comment-end) "\n"
                  (comment-string-strip comment-end t t))))
-       (set (make-local-variable 'comment-end-skip)
-            ;; We use [ \t] rather than \s- because we don't want to
-            ;; remove ^L in C mode when uncommenting.
-            (concat "[ \t]*\\(\\s>" (if comment-quote-nested "" "+")
-                    "\\|" (regexp-quote (substring ce 0 1))
-                    (if (and comment-quote-nested (<= (length ce) 1)) "" "+")
-                    (regexp-quote (substring ce 1))
-                    "\\)"))))))
+        (setq-local comment-end-skip
+                    ;; We use [ \t] rather than \s- because we don't want to
+                    ;; remove ^L in C mode when uncommenting.
+                    (concat "[ \t]*\\(\\s>" (if comment-quote-nested "" "+")
+                            "\\|" (regexp-quote (substring ce 0 1))
+                            (if (and comment-quote-nested (<= (length ce) 1)) 
"" "+")
+                            (regexp-quote (substring ce 1))
+                            "\\)"))))))
 
 (defun comment-quote-re (str unp)
   (concat (regexp-quote (substring str 0 1))
diff --git a/lisp/outline.el b/lisp/outline.el
index 9b11b86..85f9de4 100644
--- a/lisp/outline.el
+++ b/lisp/outline.el
@@ -318,7 +318,7 @@ See the command `outline-mode' for more information on this 
mode."
        (add-hook 'change-major-mode-hook
                  (lambda () (outline-minor-mode -1))
                  nil t)
-       (set (make-local-variable 'line-move-ignore-invisible) t)
+        (setq-local line-move-ignore-invisible t)
        ;; Cause use of ellipses for invisible text.
        (add-to-invisibility-spec '(outline . t)))
     (setq line-move-ignore-invisible nil)
diff --git a/lisp/pcomplete.el b/lisp/pcomplete.el
index a744165..1f33274 100644
--- a/lisp/pcomplete.el
+++ b/lisp/pcomplete.el
@@ -738,8 +738,8 @@ user actually typed in."
 COMPLETEF-SYM should be the symbol where the
 dynamic-complete-functions are kept.  For comint mode itself,
 this is `comint-dynamic-complete-functions'."
-  (set (make-local-variable 'pcomplete-parse-arguments-function)
-       #'pcomplete-parse-comint-arguments)
+  (setq-local pcomplete-parse-arguments-function
+              #'pcomplete-parse-comint-arguments)
   (add-hook 'completion-at-point-functions
             #'pcomplete-completions-at-point nil 'local)
   (set (make-local-variable completef-sym)
diff --git a/lisp/play/dunnet.el b/lisp/play/dunnet.el
index 1df28a0..45afb51 100644
--- a/lisp/play/dunnet.el
+++ b/lisp/play/dunnet.el
@@ -46,10 +46,10 @@
 
 ;;;;
 ;;;; This section defines the globals that are used in dunnet.
-;;;;
-;;;; IMPORTANT
-;;;; All globals which can change must be saved from 'save-game.  Add
-;;;; all new globals to bottom of this section.
+;;
+;; IMPORTANT
+;; All globals which can change must be saved from 'save-game.
+;; Add all new globals to bottom of this section.
 
 (defvar dun-visited '(27))
 (defvar dun-current-room 1)
@@ -771,7 +771,6 @@ A hole leads north."
 )
 
 
-;;; How the user references *all* objects, permanent and regular.
 (defconst dun-objnames
   '((shovel . 0)
     (lamp . 1)
@@ -831,7 +830,8 @@ A hole leads north."
     (ladder . -27)
     (subway . -28) (train . -28)
     (pc . -29) (drive . -29) (coconut . -30) (coconuts . -30)
-    (lake . -32) (water . -32)))
+    (lake . -32) (water . -32))
+  "How the user references *all* objects, permanent and regular.")
 
 (dolist (x dun-objnames)
   (let (name)
@@ -840,13 +840,6 @@ A hole leads north."
 
 (defconst obj-special 255)
 
-;;; The initial setup of what objects are in each room.
-;;; Regular objects have whole numbers lower than 255.
-;;; Objects that cannot be taken but might move and are
-;;; described during room description are negative.
-;;; Stuff that is described and might change are 255, and are
-;;; handled specially by 'dun-describe-room.
-
 (defvar dun-room-objects (list nil
 
         (list obj-shovel)                     ;; treasure-room
@@ -899,10 +892,13 @@ A hole leads north."
 nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
 nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
 nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
-nil))
-
-;;; These are objects in a room that are only described in the
-;;; room description.  They are permanent.
+nil)
+  "The initial setup of what objects are in each room.
+Regular objects have whole numbers lower than 255.
+Objects that cannot be taken but might move and are
+described during room description are negative.
+Stuff that is described and might change are 255, and are
+handled specially by 'dun-describe-room.")
 
 (defconst dun-room-silents (list nil
         (list obj-tree obj-coconut)            ;; dead-end
@@ -947,12 +943,11 @@ nil))
         nil nil nil nil nil nil nil nil
        (list obj-pc)                          ;; pc-area
        nil nil nil nil nil nil
-))
+       )
+  "These are objects in a room that are only described in the
+room description.  They are permanent.")
 (defvar dun-inventory '(1))
 
-;;; Descriptions of objects, as they appear in the room description, and
-;;; the inventory.
-
 (defconst dun-objects
   '(("There is a shovel here." "A shovel")                ;0
     ("There is a lamp nearby." "A lamp")                  ;1
@@ -982,26 +977,24 @@ nil))
     ("There is a valuable amethyst here." "An amethyst") ;24
     ("The Mona Lisa is here." "The Mona Lisa") ;25
     ("There is a 100 dollar bill here." "A $100 bill") ;26
-    ("There is a floppy disk here." "A floppy disk"))) ;27
-
-;;; Weight of objects
+    ("There is a floppy disk here." "A floppy disk")) ;27
+  "Descriptions of objects, as they appear in the room description, and
+the inventory.")
 
 (defconst dun-object-lbs
-  '(2 1 1 1 1 0 2 2 10 3 1 1 1 0 1 1 0 1 1 1 1 0 0 2 2 1 0 0))
+  '(2 1 1 1 1 0 2 2 10 3 1 1 1 0 1 1 0 1 1 1 1 0 0 2 2 1 0 0)
+  "Weight of objects.")
 (defconst dun-object-pts
   '(0 0 0 0 0 0 0 10 0 0 10 10 10 0 0 10 0 10 10 0 0 0 0 10 10 10 10 0))
 
 
-;;; Unix representation of objects.
 (defconst dun-objfiles
   '("shovel.o" "lamp.o" "cpu.o" "food.o" "key.o" "paper.o"
     "rms.o" "diamond.o" "weight.o" "preserver.o" "bracelet.o"
     "gold.o" "platinum.o" "towel.o" "axe.o" "silver.o" "license.o"
     "coins.o" "egg.o" "jar.o" "bone.o" "nitric.o" "glycerine.o"
-    "ruby.o" "amethyst.o"))
-
-;;; These are the descriptions for the negative numbered objects from
-;;; dun-room-objects
+    "ruby.o" "amethyst.o")
+  "Unix representation of objects.")
 
 (defconst dun-perm-objects
   '(nil
@@ -1016,12 +1009,11 @@ nil))
     ("There is a box with a slit in it, bolted to the wall here.")
     nil nil
     ("There is a bus here.")
-    nil nil nil))
+    nil nil nil)
+  "These are the descriptions for the negative numbered objects from
+`dun-room-objects'.")
 
 
-;;; These are the descriptions the user gets when regular objects are
-;;; examined.
-
 (defconst dun-physobj-desc '(
 "It is a normal shovel with a price tag attached that says $19.99."
 "The lamp is hand-crafted by Geppetto."
@@ -1043,10 +1035,8 @@ nil nil
 "They are old coins from the 19th century."
 "It is a valuable Fabrege egg."
 "It is a plain glass jar."
-nil nil nil nil nil))
-
-;;; These are the descriptions the user gets when non-regular objects
-;;; are examined.
+nil nil nil nil nil)
+  "The descriptions the user gets when regular objects are examined.")
 
 (defconst dun-permobj-desc
   '(nil
@@ -1087,7 +1077,8 @@ it.  It is very big, though."
 nil nil nil nil
 "It is a normal ladder that is permanently attached to the hole."
 "It is a passenger train that is ready to go."
-"It is a personal computer that has only one floppy disk drive."))
+"It is a personal computer that has only one floppy disk drive.")
+  "The descriptions the user gets when non-regular objects are examined.")
 
 (defconst dun-diggables
       (list nil nil nil (list obj-cpu) nil nil nil nil nil nil nil
@@ -1189,10 +1180,9 @@ treasures for points?" "4" "four")
 ;;;; This section contains all of the verbs and commands.
 ;;;;
 
-;;; Give long description of room if haven't been there yet.  Otherwise
-;;; short.  Also give long if we were called with negative room number.
-
 (defun dun-describe-room (room)
+  "Give long description of room if haven't been there yet.
+Otherwise short.  Also give long if we were called with negative room number."
   (if (and (not (member (abs room) dun-light-rooms))
           (not (member obj-lamp dun-inventory))
           (not (member obj-lamp (nth dun-current-room dun-room-objects))))
@@ -1222,10 +1212,9 @@ treasures for points?" "4" "four")
     (if (and (member obj-bus (nth dun-current-room dun-room-objects)) 
dun-inbus)
        (dun-mprincl "You are on the bus."))))
 
-;;; There is a special object in the room.  This object's description,
-;;; or lack thereof, depends on certain conditions.
-
 (defun dun-special-object ()
+  "There is a special object in the room.  This object's description,
+or lack thereof, depends on certain conditions."
   (cond
    ((= dun-current-room computer-room)
     (if dun-computer
@@ -1298,10 +1287,9 @@ disk bursts into flames, and disintegrates.")
 (defun dun-quit (_args)
   (dun-die nil))
 
-;;; Print every object in player's inventory.  Special case for the jar,
-;;; as we must also print what is in it.
-
 (defun dun-inven (_args)
+  "Print every object in player's inventory.
+Special case for the jar, as we must also print what is in it."
   (dun-mprincl "You currently have:")
   (dolist (curobj dun-inventory)
     (when curobj
@@ -1352,9 +1340,8 @@ on your head.")
         (if (member objnum (list obj-food obj-weight obj-jar))
             (dun-drop-check objnum)))))))
 
-;;; Dropping certain things causes things to happen.
-
 (defun dun-drop-check (objnum)
+  "Dropping certain things causes things to happen."
   (cond
    ((and (= objnum obj-food) (= dun-room bear-hangout)
          (member obj-bear (nth bear-hangout dun-room-objects)))
@@ -1381,9 +1368,8 @@ through.")))
    ((and (= objnum obj-weight) (= dun-current-room maze-button-room))
     (dun-mprincl "A passageway opens."))))
 
-;;; Give long description of current room, or an object.
-
 (defun dun-examine (obj)
+  "Give long description of current room, or an object."
   (let ((objnum (dun-objnum-from-args obj)))
     (cond
      ((eq objnum obj-special)
@@ -1474,10 +1460,9 @@ For an explosive time, go to Fourth St. and Vermont.")
       (setq total (+ total (nth x dun-object-lbs))))
     total))
 
-;;; We try to take an object that is untakable.  Print a message
-;;; depending on what it is.
-
 (defun dun-try-take (_obj)
+  "We try to take an object that is untakable.
+Print a message depending on what it is."
   (dun-mprinc "You cannot take that."))
 
 (defun dun-dig (_args)
@@ -1670,15 +1655,15 @@ just try dropping it."))
 (defun dun-go (args)
   (if (or (not (car args))
          (eq (dun-doverb dun-ignore dun-verblist (car args)
-                         (cdr (cdr args))) -1))
+                         (cdr (cdr args)))
+             -1))
       (dun-mprincl "I don't understand where you want me to go.")))
 
-;;; Uses the dungeon-map to figure out where we are going.  If the
-;;; requested direction yields 255, we know something special is
-;;; supposed to happen, or perhaps you can't go that way unless
-;;; certain conditions are met.
-
 (defun dun-move (dir)
+  ;; Uses the dungeon-map to figure out where we are going.  If the
+  ;; requested direction yields 255, we know something special is
+  ;; supposed to happen, or perhaps you can't go that way unless
+  ;; certain conditions are met.
   (if (and (not (member dun-current-room dun-light-rooms))
           (not (member obj-lamp dun-inventory))
           (not (member obj-lamp (nth dun-current-room dun-room-objects))))
@@ -1709,17 +1694,17 @@ body.")
                                   (list obj-bus)))))
            (setq dun-current-room newroom)))))))
 
-;;; Movement in this direction causes something special to happen if the
-;;; right conditions exist.  It may be that you can't go this way unless
-;;; you have a key, or a passage has been opened.
+(defun dun-special-move (dir)
+  ;; Movement in this direction causes something special to happen if the
+  ;; right conditions exist.  It may be that you can't go this way unless
+  ;; you have a key, or a passage has been opened.
 
-;;; coding note: Each check of the current room is on the same 'if' level,
-;;; i.e. there aren't else's.  If two rooms next to each other have
-;;; specials, and they are connected by specials, this could cause
-;;; a problem.  Be careful when adding them to consider this, and
-;;; perhaps use else's.
+  ;; coding note: Each check of the current room is on the same 'if' level,
+  ;; i.e. there aren't else's.  If two rooms next to each other have
+  ;; specials, and they are connected by specials, this could cause
+  ;; a problem.  Be careful when adding them to consider this, and
+  ;; perhaps use else's.
 
-(defun dun-special-move (dir)
   (if (= dun-current-room building-front)
       (if (not (member obj-key dun-inventory))
          (dun-mprincl "You don't have a key that can open this door.")
@@ -2152,10 +2137,10 @@ for a moment, then straighten yourself up.\n")
 ;;;;
 
 
-;;; Function which takes a verb and a list of other words.  Calls proper
-;;; function associated with the verb, and passes along the other words.
-
 (defun dun-doverb (ignore verblist verb rest)
+  "Take a verb and a list of other words.
+Calls proper function associated with the verb, and passes along the
+other words."
   (when verb
     (if (member (intern verb) ignore)
        (if (not (car rest)) -1
@@ -2165,9 +2150,8 @@ for a moment, then straighten yourself up.\n")
        (funcall (cdr (assq (intern verb) verblist)) rest)))))
 
 
-;;; Function to take a string and change it into a list of lowercase words.
-
 (defun dun-listify-string (strin)
+  "Take a string and change it into a list of lowercase words."
   (let (pos ret-list end-pos)
     (setq pos 0)
     (setq ret-list nil)
@@ -2177,7 +2161,8 @@ for a moment, then straighten yourself up.\n")
          (setq ret-list (append ret-list (list
                                           (downcase
                                            (substring strin pos end-pos))))))
-      (setq pos (+ end-pos 1))) ret-list))
+      (setq pos (+ end-pos 1)))
+    ret-list))
 
 (defun dun-listify-string2 (strin)
   (let (pos ret-list end-pos)
@@ -2194,10 +2179,8 @@ for a moment, then straighten yourself up.\n")
 (defun dun-replace (list n number)
   (rplaca (nthcdr n list) number))
 
-
-;;; Get the first non-ignored word from a list.
-
 (defun dun-firstword (list)
+  "Get the first non-ignored word from a list."
   (when (car list)
     (while (and list (memq (intern (car list)) dun-ignore))
       (setq list (cdr list)))
@@ -2209,10 +2192,9 @@ for a moment, then straighten yourself up.\n")
       (setq list (cdr list)))
     list))
 
-;;; parse a line passed in as a string  Call the proper verb with the
-;;; rest of the line passed in as a list.
-
 (defun dun-vparse (ignore verblist line)
+  "Parse a line passed in as a string.
+Call the proper verb with the rest of the line passed in as a list."
   (dun-mprinc "\n")
   (setq dun-line-list (dun-listify-string (concat line " ")))
   (dun-doverb ignore verblist (car dun-line-list) (cdr dun-line-list)))
@@ -2222,54 +2204,47 @@ for a moment, then straighten yourself up.\n")
   (setq dun-line-list (dun-listify-string2 (concat line " ")))
   (dun-doverb ignore verblist (car dun-line-list) (cdr dun-line-list)))
 
-;;; Read a line, in window mode
-
 (defun dun-read-line ()
+  "Read a line, in window mode."
   (let ((line (read-string "")))
     (dun-mprinc line)
     line))
 
-;;; Insert something into the window buffer
-
 (defun dun-minsert (&rest args)
+  "Insert something into the window buffer."
   (dolist (arg args)
     (if (stringp arg)
         (insert arg)
       (insert (prin1-to-string arg)))))
 
-;;; Print something out, in window mode
-
 (defun dun-mprinc (&rest args)
+  "Print something out, in window mode."
   (dolist (arg args)
     (if (stringp arg)
         (insert arg)
       (insert (prin1-to-string arg)))))
 
-;;; In window mode, keep screen from jumping by keeping last line at
-;;; the bottom of the screen.
-
 (defun dun-fix-screen ()
+  "In window mode, keep screen from jumping by keeping last line at
+the bottom of the screen."
   (interactive)
   (forward-line (- 0 (- (window-height) 2 )))
   (set-window-start (selected-window) (point))
   (goto-char (point-max)))
 
-;;; Insert something into the buffer, followed by newline.
-
 (defun dun-minsertl (&rest args)
+  "Insert something into the buffer, followed by newline."
   (apply #'dun-minsert args)
   (dun-minsert "\n"))
 
-;;; Print something, followed by a newline.
-
 (defun dun-mprincl (&rest args)
+  "Print something, followed by a newline."
   (apply #'dun-mprinc args)
   (dun-mprinc "\n"))
 
-;;; Function which will get an object number given the list of
-;;; words in the command, except for the verb.
-
 (defun dun-objnum-from-args (obj)
+  "Get an object number given the list of words in the command,
+except for the verb."
   (setq obj (dun-firstword obj))
   (if (not obj)
       obj-special
@@ -2285,9 +2260,8 @@ for a moment, then straighten yourself up.\n")
       nil
     result)))
 
-;;; Given a unix style pathname, build a list of path components (recursive)
-
 (defun dun-get-path (dirstring startlist)
+  "Given a unix style pathname, build a list of path components (recursive)"
   (let (slash)
     (if (= (length dirstring) 0)
        startlist
@@ -2299,10 +2273,9 @@ for a moment, then straighten yourself up.\n")
                    (append startlist
                            (list (substring dirstring 0 slash)))))))))
 
-;;; Function to put objects in the treasure room.  Also prints current
-;;; score to let user know he has scored.
-
 (defun dun-put-objs-in-treas (objlist)
+  "Put objects in the treasure room.
+Also prints current score to let user know he has scored."
   (let (oscore newscore)
     (setq oscore (dun-reg-score))
     (dun-replace dun-room-objects 0 (append (nth 0 dun-room-objects) objlist))
@@ -2310,9 +2283,8 @@ for a moment, then straighten yourself up.\n")
     (if (not (= oscore newscore))
        (dun-score nil))))
 
-;;; Load an encrypted file, and eval it.
-
 (defun dun-load-d (filename)
+  "Load an encrypted file, and eval it."
   (let ((result t))
     (with-temp-buffer
       (condition-case nil
@@ -3154,14 +3126,16 @@ File not found")))
   (dun-mprinc "\n")
   (dun-batch-loop))
 
-(when noninteractive
-  (fset 'dun-mprinc 'dun-batch-mprinc)
-  (fset 'dun-mprincl 'dun-batch-mprincl)
-  (fset 'dun-vparse 'dun-batch-parse)
-  (fset 'dun-parse2 'dun-batch-parse2)
-  (fset 'dun-read-line 'dun-batch-read-line)
-  (fset 'dun-dos-interface 'dun-batch-dos-interface)
-  (fset 'dun-unix-interface 'dun-batch-unix-interface)
+;;;###autoload
+(defun dun-batch ()
+  "Start `dunnet' in batch mode."
+  (fset 'dun-mprinc #'dun-batch-mprinc)
+  (fset 'dun-mprincl #'dun-batch-mprincl)
+  (fset 'dun-vparse #'dun-batch-parse)
+  (fset 'dun-parse2 #'dun-batch-parse2)
+  (fset 'dun-read-line #'dun-batch-read-line)
+  (fset 'dun-dos-interface #'dun-batch-dos-interface)
+  (fset 'dun-unix-interface #'dun-batch-unix-interface)
   (dun-mprinc "\n")
   (setq dun-batch-mode t)
   (dun-batch-loop))
diff --git a/lisp/proced.el b/lisp/proced.el
index 203d703..5d4318d 100644
--- a/lisp/proced.el
+++ b/lisp/proced.el
@@ -664,9 +664,9 @@ After displaying or updating a Proced buffer, Proced runs 
the normal hook
         truncate-lines t
         header-line-format '(:eval (proced-header-line)))
   (add-hook 'post-command-hook #'force-mode-line-update nil t)  ;; FIXME: Why?
-  (set (make-local-variable 'revert-buffer-function) #'proced-revert)
-  (set (make-local-variable 'font-lock-defaults)
-       '(proced-font-lock-keywords t nil nil beginning-of-line))
+  (setq-local revert-buffer-function #'proced-revert)
+  (setq-local font-lock-defaults
+              '(proced-font-lock-keywords t nil nil beginning-of-line))
   (if (and (not proced-auto-update-timer) proced-auto-update-interval)
       (setq proced-auto-update-timer
             (run-at-time t proced-auto-update-interval
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index 5e2ce71..f14ffb3 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -10837,11 +10837,11 @@ comment at the start of cc-engine.el for more info."
             (low-lim (max (or lim (point-min))   (or macro-start (point-min))))
             before-lparen after-rparen
             (here (point))
-            (pp-count-out 20)  ; Max number of paren/brace constructs before
-                               ; we give up.
+            (pp-count-out 20)   ; Max number of paren/brace constructs before
+                                       ; we give up
             ids              ; List of identifiers in the parenthesized list.
             id-start after-prec-token decl-or-cast decl-res
-            c-last-identifier-range identifier-ok)
+            c-last-identifier-range semi-position+1)
        (narrow-to-region low-lim (or macro-end (point-max)))
 
        ;; Search backwards for the defun's argument list.  We give up if we
@@ -10875,8 +10875,8 @@ comment at the start of cc-engine.el for more info."
                   (setq after-rparen (point)))
                  ((eq (char-before) ?\])
                   (setq after-rparen nil))
-                 (t ; either } (hit previous defun) or = or no more
-                    ; parens/brackets.
+                 (t           ; either } (hit previous defun) or = or no more
+                                       ; parens/brackets.
                   (throw 'knr nil)))
 
            (if after-rparen
@@ -10933,31 +10933,35 @@ comment at the start of cc-engine.el for more info."
                       (forward-char)   ; over the )
                       (setq after-prec-token after-rparen)
                       (c-forward-syntactic-ws)
+                      ;; Each time around the following checks one
+                      ;; declaration (which may contain several identifiers).
                       (while (and
-                              (or (consp (setq decl-or-cast
-                                               (c-forward-decl-or-cast-1
-                                                after-prec-token
-                                                nil ; Or 'arglist ???
-                                                nil)))
-                                  (progn
-                                    (goto-char after-prec-token)
-                                    (c-forward-syntactic-ws)
-                                    (setq identifier-ok (eq (char-after) ?{))
-                                    nil))
-                              (eq (char-after) ?\;)
-                              (setq after-prec-token (1+ (point)))
+                              (consp (setq decl-or-cast
+                                           (c-forward-decl-or-cast-1
+                                            after-prec-token
+                                            nil ; Or 'arglist ???
+                                            nil)))
+                              (memq (char-after) '(?\; ?\,))
                               (goto-char (car decl-or-cast))
-                              (setq decl-res (c-forward-declarator))
-                              (setq identifier-ok
-                                    (member (buffer-substring-no-properties
-                                       (car decl-res) (cadr decl-res))
-                                      ids))
-                              (progn
-                                (goto-char after-prec-token)
-                                (prog1 (< (point) here)
-                                  (c-forward-syntactic-ws))))
-                        (setq identifier-ok nil))
-                      identifier-ok))
+                              (save-excursion
+                                (setq semi-position+1
+                                      (c-syntactic-re-search-forward
+                                       ";" (+ (point) 1000) t)))
+                              (c-do-declarators
+                               semi-position+1 t nil nil
+                               (lambda (id-start id-end _next _not-top
+                                                 _func _init)
+                                 (if (not (member
+                                           (buffer-substring-no-properties
+                                            id-start id-end)
+                                           ids))
+                                     (throw 'knr nil))))
+
+                              (progn (forward-char)
+                                     (<= (point) here))
+                              (progn (c-forward-syntactic-ws)
+                                     t)))
+                      t))
                    ;; ...Yes.  We've identified the function's argument list.
                    (throw 'knr
                           (progn (goto-char after-rparen)
diff --git a/lisp/progmodes/cfengine.el b/lisp/progmodes/cfengine.el
index a8fe485..6e91544 100644
--- a/lisp/progmodes/cfengine.el
+++ b/lisp/progmodes/cfengine.el
@@ -1314,19 +1314,19 @@ see.  Use it by enabling `eldoc-mode'."
       (append bounds (list (cdr flist))))))
 
 (defun cfengine-common-settings ()
-  (set (make-local-variable 'syntax-propertize-function)
-       ;; In the main syntax-table, \ is marked as a punctuation, because
-       ;; of its use in DOS-style directory separators.  Here we try to
-       ;; recognize the cases where \ is used as an escape inside strings.
-       (syntax-propertize-rules ("\\(\\(?:\\\\\\)+\\)\"" (1 "\\"))))
-  (set (make-local-variable 'parens-require-spaces) nil)
-  (set (make-local-variable 'comment-start)  "# ")
-  (set (make-local-variable 'comment-start-skip)
-       "\\(\\(?:^\\|[^\\\n]\\)\\(?:\\\\\\\\\\)*\\)#+[ \t]*")
+  (setq-local syntax-propertize-function
+              ;; In the main syntax-table, \ is marked as a punctuation, 
because
+              ;; of its use in DOS-style directory separators.  Here we try to
+              ;; recognize the cases where \ is used as an escape inside 
strings.
+              (syntax-propertize-rules ("\\(\\(?:\\\\\\)+\\)\"" (1 "\\"))))
+  (setq-local parens-require-spaces nil)
+  (setq-local comment-start  "# ")
+  (setq-local comment-start-skip
+              "\\(\\(?:^\\|[^\\\n]\\)\\(?:\\\\\\\\\\)*\\)#+[ \t]*")
   ;; Like Lisp mode.  Without this, we lose with, say,
   ;; `backward-up-list' when there's an unbalanced quote in a
   ;; preceding comment.
-  (set (make-local-variable 'parse-sexp-ignore-comments) t))
+  (setq-local parse-sexp-ignore-comments t))
 
 (defun cfengine-common-syntax (table)
   ;; The syntax defaults seem OK to give reasonable word movement.
@@ -1374,7 +1374,7 @@ to the action header."
   (cfengine-common-settings)
   (cfengine-common-syntax cfengine3-mode-syntax-table)
 
-  (set (make-local-variable 'indent-line-function) #'cfengine3-indent-line)
+  (setq-local indent-line-function #'cfengine3-indent-line)
 
   (setq font-lock-defaults
         '(cfengine3-font-lock-keywords
@@ -1384,11 +1384,11 @@ to the action header."
   ;; `compile-command' is almost never a `make' call with CFEngine so
   ;; we override it
   (when cfengine-cf-promises
-    (set (make-local-variable 'compile-command)
-         (concat cfengine-cf-promises
-                 " -f "
-                 (when buffer-file-name
-                   (shell-quote-argument buffer-file-name)))))
+    (setq-local compile-command
+                (concat cfengine-cf-promises
+                        " -f "
+                        (when buffer-file-name
+                          (shell-quote-argument buffer-file-name)))))
 
   (add-hook 'eldoc-documentation-functions
             #'cfengine3-documentation-function nil t)
@@ -1418,20 +1418,18 @@ to the action header."
   ;; should avoid potential confusion in some cases.
   (modify-syntax-entry ?\` "\"" cfengine2-mode-syntax-table)
 
-  (set (make-local-variable 'indent-line-function) #'cfengine2-indent-line)
-  (set (make-local-variable 'outline-regexp) "[ \t]*\\(\\sw\\|\\s_\\)+:+")
-  (set (make-local-variable 'outline-level) #'cfengine2-outline-level)
-  (set (make-local-variable 'fill-paragraph-function)
-       #'cfengine-fill-paragraph)
+  (setq-local indent-line-function #'cfengine2-indent-line)
+  (setq-local outline-regexp "[ \t]*\\(\\sw\\|\\s_\\)+:+")
+  (setq-local outline-level #'cfengine2-outline-level)
+  (setq-local fill-paragraph-function #'cfengine-fill-paragraph)
   (define-abbrev-table 'cfengine2-mode-abbrev-table cfengine-mode-abbrevs)
   (setq font-lock-defaults
         '(cfengine2-font-lock-keywords nil nil nil beginning-of-line))
   ;; Fixme: set the args of functions in evaluated classes to string
   ;; syntax, and then obey syntax properties.
   (setq imenu-generic-expression cfengine2-imenu-expression)
-  (set (make-local-variable 'beginning-of-defun-function)
-       #'cfengine2-beginning-of-defun)
-  (set (make-local-variable 'end-of-defun-function) #'cfengine2-end-of-defun))
+  (setq-local beginning-of-defun-function #'cfengine2-beginning-of-defun)
+  (setq-local end-of-defun-function #'cfengine2-end-of-defun))
 
 ;;;###autoload
 (defun cfengine-auto-mode ()
diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el
index 787f5d5..d229315 100644
--- a/lisp/progmodes/compile.el
+++ b/lisp/progmodes/compile.el
@@ -241,11 +241,20 @@ of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2 nil (1))
     ;; GradleStyleMessagerRenderer.kt in kotlin sources, see
     ;; https://youtrack.jetbrains.com/issue/KT-34683).
     (gradle-kotlin
-     ,(concat
-       "^\\(?:\\(w\\)\\|.\\): *"            ;type
-       "\\(\\(?:[A-Za-z]:\\)?[^:\n]+\\): *" ;file
-       "(\\([0-9]+\\), *\\([0-9]+\\))")     ;line, column
-     2 3 4 (1))
+     ,(rx bol
+          (| (group "w")                ; 1: warning
+             (group (in "iv"))          ; 2: info
+             "e")                       ; error
+          ": "
+          (group                        ; 3: file
+           (? (in "A-Za-z") ":")
+           (+ (not (in "\n:"))))
+          ": ("
+          (group (+ digit))             ; 4: line
+          ", "
+          (group (+ digit))             ; 5: column
+          "): ")
+     3 4 5 (1 . 2))
 
     (iar
      
"^\"\\(.*\\)\",\\([0-9]+\\)\\s-+\\(?:Error\\|Warnin\\(g\\)\\)\\[[0-9]+\\]:"
@@ -807,7 +816,7 @@ You might also use mode hooks to specify it in certain 
modes, like this:
        (lambda ()
         (unless (or (file-exists-p \"makefile\")
                     (file-exists-p \"Makefile\"))
-          (set (make-local-variable \\='compile-command)
+           (setq-local compile-command
                (concat \"make -k \"
                        (if buffer-file-name
                          (shell-quote-argument
@@ -1839,14 +1848,13 @@ Returns the compilation buffer created."
         ;; default-directory' can't be used reliably for that because it may be
         ;; affected by the special handling of "cd ...;".
         ;; NB: must be done after (funcall mode) as that resets local variables
-        (set (make-local-variable 'compilation-directory) thisdir)
-       (set (make-local-variable 'compilation-environment) thisenv)
+        (setq-local compilation-directory thisdir)
+        (setq-local compilation-environment thisenv)
        (if highlight-regexp
-           (set (make-local-variable 'compilation-highlight-regexp)
-                highlight-regexp))
+            (setq-local compilation-highlight-regexp highlight-regexp))
         (if (or compilation-auto-jump-to-first-error
                (eq compilation-scroll-output 'first-error))
-            (set (make-local-variable 'compilation-auto-jump-to-next) t))
+            (setq-local compilation-auto-jump-to-next t))
        ;; Output a mode setter, for saving and later reloading this buffer.
        (insert "-*- mode: " name-of-mode
                "; default-directory: "
@@ -1868,13 +1876,13 @@ Returns the compilation buffer created."
       (let ((process-environment
             (append
              compilation-environment
-              (comint-term-environment)
+              (and (derived-mode-p 'comint-mode)
+                   (comint-term-environment))
              (list (format "INSIDE_EMACS=%s,compile" emacs-version))
              (copy-sequence process-environment))))
-       (set (make-local-variable 'compilation-arguments)
-            (list command mode name-function highlight-regexp))
-       (set (make-local-variable 'revert-buffer-function)
-            'compilation-revert-buffer)
+        (setq-local compilation-arguments
+                    (list command mode name-function highlight-regexp))
+        (setq-local revert-buffer-function 'compilation-revert-buffer)
        (and outwin
             ;; Forcing the window-start overrides the usual redisplay
             ;; feature of bringing point into view, so setting the
@@ -2179,20 +2187,19 @@ Runs `compilation-mode-hook' with `run-mode-hooks' 
(which see).
   (kill-all-local-variables)
   (use-local-map compilation-mode-map)
   ;; Let windows scroll along with the output.
-  (set (make-local-variable 'window-point-insertion-type) t)
-  (set (make-local-variable 'tool-bar-map) compilation-mode-tool-bar-map)
+  (setq-local window-point-insertion-type t)
+  (setq-local tool-bar-map compilation-mode-tool-bar-map)
   (setq major-mode 'compilation-mode ; FIXME: Use define-derived-mode.
        mode-name (or name-of-mode "Compilation"))
-  (set (make-local-variable 'page-delimiter)
-       compilation-page-delimiter)
-  ;; (set (make-local-variable 'compilation-buffer-modtime) nil)
+  (setq-local page-delimiter compilation-page-delimiter)
+  ;; (setq-local compilation-buffer-modtime nil)
   (compilation-setup)
   ;; Turn off deferred fontifications in the compilation buffer, if
   ;; the user turned them on globally.  This is because idle timers
   ;; aren't re-run after receiving input from a subprocess, so the
   ;; buffer is left unfontified after the compilation exits, until
   ;; some other input event happens.
-  (set (make-local-variable 'jit-lock-defer-time) nil)
+  (setq-local jit-lock-defer-time nil)
   (setq buffer-read-only t)
   (run-mode-hooks 'compilation-mode-hook))
 
@@ -2262,7 +2269,7 @@ Optional argument MINOR indicates this is called from
   (setq-local compilation-num-errors-found 0)
   (setq-local compilation-num-warnings-found 0)
   (setq-local compilation-num-infos-found 0)
-  (set (make-local-variable 'overlay-arrow-string) "")
+  (setq-local overlay-arrow-string "")
   (setq next-error-overlay-arrow-position nil)
   (add-hook 'kill-buffer-hook
            (lambda () (setq next-error-overlay-arrow-position nil)) nil t)
@@ -2270,10 +2277,10 @@ Optional argument MINOR indicates this is called from
   ;; with the next-error function in simple.el, and it's only
   ;; coincidentally named similarly to compilation-next-error.
   (setq next-error-function 'compilation-next-error-function)
-  (set (make-local-variable 'comint-file-name-prefix)
-       (or (file-remote-p default-directory) ""))
-  (set (make-local-variable 'compilation-locs)
-       (make-hash-table :test 'equal :weakness 'value))
+  (setq-local comint-file-name-prefix
+              (or (file-remote-p default-directory) ""))
+  (setq-local compilation-locs
+              (make-hash-table :test 'equal :weakness 'value))
   ;; It's generally preferable to use after-change-functions since they
   ;; can be subject to combine-after-change-calls, but if we do that, we risk
   ;; running our hook after font-lock, resulting in incorrect refontification.
@@ -2411,8 +2418,7 @@ and runs `compilation-filter-hook'."
               (set-marker (process-mark proc) (point))
               ;; Update the number of errors in compilation-mode-line-errors
               (compilation--ensure-parse (point))
-              ;; (set (make-local-variable 'compilation-buffer-modtime)
-              ;;      (current-time))
+              ;; (setq-local compilation-buffer-modtime (current-time))
               (run-hooks 'compilation-filter-hook))
          (goto-char pos)
           (narrow-to-region min max)
@@ -3166,9 +3172,9 @@ TRUE-DIRNAME is the `file-truename' of DIRNAME, if given."
   ;; Again, since this command is used in buffers that contain several
   ;; compilations, to set the beginning of "this compilation", it's a good
   ;; place to reset compilation-auto-jump-to-next.
-  (set (make-local-variable 'compilation-auto-jump-to-next)
-       (or compilation-auto-jump-to-first-error
-          (eq compilation-scroll-output 'first-error))))
+  (setq-local compilation-auto-jump-to-next
+              (or compilation-auto-jump-to-first-error
+                  (eq compilation-scroll-output 'first-error))))
 
 (provide 'compile)
 
diff --git a/lisp/progmodes/cperl-mode.el b/lisp/progmodes/cperl-mode.el
index 48f0a34..ae839a6 100644
--- a/lisp/progmodes/cperl-mode.el
+++ b/lisp/progmodes/cperl-mode.el
@@ -1599,111 +1599,106 @@ or as help on variables `cperl-tips', 
`cperl-problems',
   ;; Until Emacs is multi-threaded, we do not actually need it local:
   (make-local-variable 'cperl-font-lock-multiline-start)
   (make-local-variable 'cperl-font-locking)
-  (set (make-local-variable 'outline-regexp) cperl-outline-regexp)
-  (set (make-local-variable 'outline-level) 'cperl-outline-level)
-  (set (make-local-variable 'add-log-current-defun-function)
-       (lambda ()
-         (save-excursion
-           (if (re-search-backward "^sub[ \t]+\\([^({ \t\n]+\\)" nil t)
-               (match-string-no-properties 1)))))
-
-  (set (make-local-variable 'paragraph-start) (concat "^$\\|" page-delimiter))
-  (set (make-local-variable 'paragraph-separate) paragraph-start)
-  (set (make-local-variable 'paragraph-ignore-fill-prefix) t)
-  (set (make-local-variable 'indent-line-function) #'cperl-indent-line)
-  (set (make-local-variable 'require-final-newline) mode-require-final-newline)
-  (set (make-local-variable 'comment-start) "# ")
-  (set (make-local-variable 'comment-end) "")
-  (set (make-local-variable 'comment-column) cperl-comment-column)
-  (set (make-local-variable 'comment-start-skip) "#+ *")
+  (setq-local outline-regexp cperl-outline-regexp)
+  (setq-local outline-level 'cperl-outline-level)
+  (setq-local add-log-current-defun-function
+              (lambda ()
+                (save-excursion
+                  (if (re-search-backward "^sub[ \t]+\\([^({ \t\n]+\\)" nil t)
+                      (match-string-no-properties 1)))))
+
+  (setq-local paragraph-start (concat "^$\\|" page-delimiter))
+  (setq-local paragraph-separate paragraph-start)
+  (setq-local paragraph-ignore-fill-prefix t)
+  (setq-local indent-line-function #'cperl-indent-line)
+  (setq-local require-final-newline mode-require-final-newline)
+  (setq-local comment-start "# ")
+  (setq-local comment-end "")
+  (setq-local comment-column cperl-comment-column)
+  (setq-local comment-start-skip "#+ *")
 
 ;;       "[ \t]*sub"
 ;;       (cperl-after-sub-regexp 'named nil) ; 8=name 11=proto 14=attr-start
 ;;       cperl-maybe-white-and-comment-rex     ; 15=pre-block
-  (set (make-local-variable 'defun-prompt-regexp)
-       (concat "^[ \t]*\\("
-               cperl-sub-regexp
-              (cperl-after-sub-regexp 'named 'attr-groups)
-              "\\|"                    ; per toke.c
-              
"\\(BEGIN\\|UNITCHECK\\|CHECK\\|INIT\\|END\\|AUTOLOAD\\|DESTROY\\)"
-              "\\)"
-              cperl-maybe-white-and-comment-rex))
-  (set (make-local-variable 'comment-indent-function) #'cperl-comment-indent)
-  (set (make-local-variable 'fill-paragraph-function)
-       #'cperl-fill-paragraph)
-  (set (make-local-variable 'parse-sexp-ignore-comments) t)
-  (set (make-local-variable 'indent-region-function) #'cperl-indent-region)
+  (setq-local defun-prompt-regexp
+              (concat "^[ \t]*\\("
+                      cperl-sub-regexp
+                      (cperl-after-sub-regexp 'named 'attr-groups)
+                      "\\|"                    ; per toke.c
+                      
"\\(BEGIN\\|UNITCHECK\\|CHECK\\|INIT\\|END\\|AUTOLOAD\\|DESTROY\\)"
+                      "\\)"
+                      cperl-maybe-white-and-comment-rex))
+  (setq-local comment-indent-function #'cperl-comment-indent)
+  (setq-local fill-paragraph-function #'cperl-fill-paragraph)
+  (setq-local parse-sexp-ignore-comments t)
+  (setq-local indent-region-function #'cperl-indent-region)
   ;;(setq auto-fill-function #'cperl-do-auto-fill) ; Need to switch on and off!
-  (set (make-local-variable 'imenu-create-index-function)
-       #'cperl-imenu--create-perl-index)
-  (set (make-local-variable 'imenu-sort-function) nil)
-  (set (make-local-variable 'vc-rcs-header) cperl-vc-rcs-header)
-  (set (make-local-variable 'vc-sccs-header) cperl-vc-sccs-header)
+  (setq-local imenu-create-index-function #'cperl-imenu--create-perl-index)
+  (setq-local imenu-sort-function nil)
+  (setq-local vc-rcs-header cperl-vc-rcs-header)
+  (setq-local vc-sccs-header cperl-vc-sccs-header)
   (cond ((boundp 'compilation-error-regexp-alist-alist);; xemacs 20.x
-        (set (make-local-variable 'compilation-error-regexp-alist-alist)
-             (cons (cons 'cperl (car cperl-compilation-error-regexp-alist))
-                   compilation-error-regexp-alist-alist))
+         (setq-local compilation-error-regexp-alist-alist
+                     (cons (cons 'cperl (car 
cperl-compilation-error-regexp-alist))
+                           compilation-error-regexp-alist-alist))
         (if (fboundp 'compilation-build-compilation-error-regexp-alist)
             (let ((f 'compilation-build-compilation-error-regexp-alist))
               (funcall f))
           (make-local-variable 'compilation-error-regexp-alist)
           (push 'cperl compilation-error-regexp-alist)))
        ((boundp 'compilation-error-regexp-alist);; xemacs 19.x
-        (set (make-local-variable 'compilation-error-regexp-alist)
-              (append cperl-compilation-error-regexp-alist
-                      compilation-error-regexp-alist))))
-  (set (make-local-variable 'font-lock-defaults)
-       '((cperl-load-font-lock-keywords
-          cperl-load-font-lock-keywords-1
-          cperl-load-font-lock-keywords-2) nil nil ((?_ . "w"))))
+         (setq-local compilation-error-regexp-alist
+                     (append cperl-compilation-error-regexp-alist
+                             compilation-error-regexp-alist))))
+  (setq-local font-lock-defaults
+              '((cperl-load-font-lock-keywords
+                 cperl-load-font-lock-keywords-1
+                 cperl-load-font-lock-keywords-2)
+                nil nil ((?_ . "w"))))
   ;; Reset syntaxification cache.
-  (set (make-local-variable 'cperl-syntax-state) nil)
+  (setq-local cperl-syntax-state nil)
   (if cperl-use-syntax-table-text-property
       (if (eval-when-compile (fboundp 'syntax-propertize-rules))
           (progn
             ;; Reset syntaxification cache.
-            (set (make-local-variable 'cperl-syntax-done-to) nil)
-            (set (make-local-variable 'syntax-propertize-function)
-                 (lambda (start end)
-                   (goto-char start)
-                   ;; Even if cperl-fontify-syntaxically has already gone
-                   ;; beyond `start', syntax-propertize has just removed
-                   ;; syntax-table properties between start and end, so we have
-                   ;; to re-apply them.
-                   (setq cperl-syntax-done-to start)
-                   (cperl-fontify-syntaxically end))))
+            (setq-local cperl-syntax-done-to nil)
+            (setq-local syntax-propertize-function
+                        (lambda (start end)
+                          (goto-char start)
+                          ;; Even if cperl-fontify-syntaxically has already 
gone
+                          ;; beyond `start', syntax-propertize has just removed
+                          ;; syntax-table properties between start and end, so 
we have
+                          ;; to re-apply them.
+                          (setq cperl-syntax-done-to start)
+                          (cperl-fontify-syntaxically end))))
        ;; Do not introduce variable if not needed, we check it!
-       (set (make-local-variable 'parse-sexp-lookup-properties) t)
-       ;; Fix broken font-lock:
-       (or (boundp 'font-lock-unfontify-region-function)
-           (setq font-lock-unfontify-region-function
-                #'font-lock-default-unfontify-region))
+        (setq-local parse-sexp-lookup-properties t)
        ;; Our: just a plug for wrong font-lock
-       (set (make-local-variable 'font-lock-unfontify-region-function)
-             ;; not present with old Emacs
-            #'cperl-font-lock-unfontify-region-function)
+        (setq-local font-lock-unfontify-region-function
+                    ;; not present with old Emacs
+                    #'cperl-font-lock-unfontify-region-function)
        ;; Reset syntaxification cache.
-       (set (make-local-variable 'cperl-syntax-done-to) nil)
-       (set (make-local-variable 'font-lock-syntactic-keywords)
-             (if cperl-syntaxify-by-font-lock
-                 '((cperl-fontify-syntaxically))
-                ;; unless font-lock-syntactic-keywords, font-lock (pre-22.1)
-                ;;  used to ignore syntax-table text-properties.  (t) is a hack
-                ;;  to make font-lock think that font-lock-syntactic-keywords
-                ;;  are defined.
-               '(t)))))
+        (setq-local cperl-syntax-done-to nil)
+        (setq-local font-lock-syntactic-keywords
+                    (if cperl-syntaxify-by-font-lock
+                        '((cperl-fontify-syntaxically))
+                      ;; unless font-lock-syntactic-keywords, font-lock 
(pre-22.1)
+                      ;;  used to ignore syntax-table text-properties.  (t) is 
a hack
+                      ;;  to make font-lock think that 
font-lock-syntactic-keywords
+                      ;;  are defined.
+                      '(t)))))
   (setq cperl-font-lock-multiline t) ; Not localized...
-  (set (make-local-variable 'font-lock-multiline) t)
-  (set (make-local-variable 'font-lock-fontify-region-function)
-       #'cperl-font-lock-fontify-region-function)
+  (setq-local font-lock-multiline t)
+  (setq-local font-lock-fontify-region-function
+              #'cperl-font-lock-fontify-region-function)
   (make-local-variable 'cperl-old-style)
-  (set (make-local-variable 'normal-auto-fill-function)
-       #'cperl-do-auto-fill)
+  (setq-local normal-auto-fill-function
+              #'cperl-do-auto-fill)
   (if (cperl-val 'cperl-font-lock)
       (progn (or cperl-faces-init (cperl-init-faces))
             (font-lock-mode 1)))
-  (set (make-local-variable 'facemenu-add-face-function)
-       #'cperl-facemenu-add-face-function) ; XXXX What this guy is for???
+  (setq-local facemenu-add-face-function
+              #'cperl-facemenu-add-face-function) ; XXXX What this guy is 
for???
   (and (boundp 'msb-menu-cond)
        (not cperl-msb-fixed)
        (cperl-msb-fix))
@@ -3478,49 +3473,18 @@ the sections using `cperl-pod-head-face', 
`cperl-pod-face',
         (font-lock-string-face (if (boundp 'font-lock-string-face)
                                    font-lock-string-face
                                  'font-lock-string-face))
-        (my-cperl-delimiters-face (if (boundp 'font-lock-constant-face)
-                                     font-lock-constant-face
-                                   'font-lock-constant-face))
+        (my-cperl-delimiters-face
+         font-lock-constant-face)
         (my-cperl-REx-spec-char-face   ; [] ^.$ and wrapper-of ({})
-         (if (boundp 'font-lock-function-name-face)
-             font-lock-function-name-face
-           'font-lock-function-name-face))
-        (font-lock-variable-name-face  ; interpolated vars and ({})-code
-         (if (boundp 'font-lock-variable-name-face)
-             font-lock-variable-name-face
-           'font-lock-variable-name-face))
-        (font-lock-function-name-face  ; used in `cperl-find-sub-attrs'
-         (if (boundp 'font-lock-function-name-face)
-             font-lock-function-name-face
-           'font-lock-function-name-face))
-        (font-lock-constant-face       ; used in `cperl-find-sub-attrs'
-         (if (boundp 'font-lock-constant-face)
-             font-lock-constant-face
-           'font-lock-constant-face))
+          font-lock-function-name-face)
         (my-cperl-REx-0length-face ; 0-length, (?:)etc, non-literal \
-         (if (boundp 'font-lock-builtin-face)
-             font-lock-builtin-face
-           'font-lock-builtin-face))
-        (font-lock-comment-face
-         (if (boundp 'font-lock-comment-face)
-             font-lock-comment-face
-           'font-lock-comment-face))
-        (font-lock-warning-face
-         (if (boundp 'font-lock-warning-face)
-             font-lock-warning-face
-           'font-lock-warning-face))
+          font-lock-builtin-face)
         (my-cperl-REx-ctl-face         ; (|)
-         (if (boundp 'font-lock-keyword-face)
-             font-lock-keyword-face
-           'font-lock-keyword-face))
+          font-lock-keyword-face)
         (my-cperl-REx-modifiers-face   ; //gims
-         (if (boundp 'cperl-nonoverridable-face)
-             cperl-nonoverridable-face
-           'cperl-nonoverridable-face))
+         'cperl-nonoverridable-face)
         (my-cperl-REx-length1-face     ; length=1 escaped chars, POSIX classes
-         (if (boundp 'font-lock-type-face)
-             font-lock-type-face
-           'font-lock-type-face))
+          font-lock-type-face)
         (stop-point (if ignore-max
                         (point-max)
                       max))
@@ -6107,7 +6071,7 @@ side-effect of memorizing only.  Examples in 
`cperl-style-examples'."
               (set-buffer "*info-perl-tmp*")
               (rename-buffer "*info*")
               (set-buffer bname)))
-       (set (make-local-variable 'window-min-height) 2)
+        (setq-local window-min-height 2)
        (current-buffer)))))
 
 (defun cperl-word-at-point (&optional p)
@@ -6425,7 +6389,7 @@ by CPerl."
   (if cperl-use-syntax-table-text-property-for-tags
       (progn
        ;; Do not introduce variable if not needed, we check it!
-       (set (make-local-variable 'parse-sexp-lookup-properties) t))))
+        (setq-local parse-sexp-lookup-properties t))))
 
 ;; Copied from imenu-example--name-and-position.
 (defvar imenu-use-markers)
@@ -8347,7 +8311,7 @@ may be used to debug problems with delayed incremental 
fontification."
     (goto-char pos)
     (normal-mode)
     ;; Why needed???  With older font-locks???
-    (set (make-local-variable 'font-lock-cache-position) (make-marker))
+    (setq-local font-lock-cache-position (make-marker))
     (while (if (> window-size 0)
               (< pos (point-max))
             (> pos (point-min)))
diff --git a/lisp/progmodes/dcl-mode.el b/lisp/progmodes/dcl-mode.el
index ca45795..9bafd7a 100644
--- a/lisp/progmodes/dcl-mode.el
+++ b/lisp/progmodes/dcl-mode.el
@@ -588,17 +588,17 @@ $
 
 There is some minimal font-lock support (see vars
 `dcl-font-lock-defaults' and `dcl-font-lock-keywords')."
-  (set (make-local-variable 'indent-line-function) 'dcl-indent-line)
-  (set (make-local-variable 'comment-start) "!")
-  (set (make-local-variable 'comment-end) "")
-  (set (make-local-variable 'comment-multi-line) nil)
+  (setq-local indent-line-function 'dcl-indent-line)
+  (setq-local comment-start "!")
+  (setq-local comment-end "")
+  (setq-local comment-multi-line nil)
 
   ;; This used to be "^\\$[ \t]*![ \t]*" which looks more correct.
   ;; The drawback was that you couldn't make empty comment lines by pressing
   ;; C-M-j repeatedly - only the first line became a comment line.
   ;; This version has the drawback that the "$" can be anywhere in the line,
   ;; and something inappropriate might be interpreted as a comment.
-  (set (make-local-variable 'comment-start-skip) "\\$[ \t]*![ \t]*")
+  (setq-local comment-start-skip "\\$[ \t]*![ \t]*")
 
   (if (boundp 'imenu-generic-expression)
       (progn (setq imenu-generic-expression dcl-imenu-generic-expression)
@@ -619,7 +619,7 @@ There is some minimal font-lock support (see vars
   (make-local-variable 'dcl-electric-reindent-regexps)
 
   ;; font lock
-  (set (make-local-variable 'font-lock-defaults) dcl-font-lock-defaults)
+  (setq-local font-lock-defaults dcl-font-lock-defaults)
 
   (tempo-use-tag-list 'dcl-tempo-tags))
 
diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el
index 12788ea..b7e0c45 100644
--- a/lisp/progmodes/elisp-mode.el
+++ b/lisp/progmodes/elisp-mode.el
@@ -38,9 +38,10 @@ It has `lisp-mode-abbrev-table' as its parent."
   :parents (list lisp-mode-abbrev-table))
 
 (defvar emacs-lisp-mode-syntax-table
-  (let ((table (make-syntax-table lisp--mode-syntax-table)))
-    (modify-syntax-entry ?\[ "(]  " table)
-    (modify-syntax-entry ?\] ")[  " table)
+  (let ((table (make-syntax-table lisp-data-mode-syntax-table)))
+    ;; These are redundant, now.
+    ;;(modify-syntax-entry ?\[ "(]  " table)
+    ;;(modify-syntax-entry ?\] ")[  " table)
     table)
   "Syntax table used in `emacs-lisp-mode'.")
 
@@ -1826,12 +1827,9 @@ Runs in a batch-mode Emacs.  Interactively use variable
   (interactive (list buffer-file-name))
   (let* ((file (or file
                    (car command-line-args-left)))
-         (dummy-elc-file)
          (byte-compile-log-buffer
           (generate-new-buffer " *dummy-byte-compile-log-buffer*"))
-         (byte-compile-dest-file-function
-          (lambda (source)
-            (setq dummy-elc-file (make-temp-file (file-name-nondirectory 
source)))))
+         (byte-compile-dest-file-function #'ignore)
          (collected)
          (byte-compile-log-warning-function
           (lambda (string &optional position fill level)
@@ -1841,7 +1839,6 @@ Runs in a batch-mode Emacs.  Interactively use variable
     (unwind-protect
         (byte-compile-file file)
       (ignore-errors
-        (delete-file dummy-elc-file)
         (kill-buffer byte-compile-log-buffer)))
     (prin1 :elisp-flymake-output-start)
     (terpri)
diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el
index 104d889..aadfb81 100644
--- a/lisp/progmodes/etags.el
+++ b/lisp/progmodes/etags.el
@@ -258,9 +258,9 @@ One argument, the tag info returned by 
`snarf-tag-function'.")
 Return non-nil if it is a valid tags table, and
 in that case, also make the tags table state variables
 buffer-local and set them to nil."
-  (set (make-local-variable 'tags-table-files) nil)
-  (set (make-local-variable 'tags-completion-table) nil)
-  (set (make-local-variable 'tags-included-tables) nil)
+  (setq-local tags-table-files nil)
+  (setq-local tags-completion-table nil)
+  (setq-local tags-included-tables nil)
   ;; We used to initialize find-tag-marker-ring and tags-location-ring
   ;; here, to new empty rings.  But that is wrong, because those
   ;; are global.
@@ -1234,34 +1234,29 @@ error message."
   "If `etags-verify-tags-table', make buffer-local format variables.
 If current buffer is a valid etags TAGS file, then give it
 buffer-local values of tags table format variables."
-  (and (etags-verify-tags-table)
-       ;; It is annoying to flash messages on the screen briefly,
-       ;; and this message is not useful.  -- rms
-       ;; (message "%s is an `etags' TAGS file" buffer-file-name)
-       (mapc (lambda (elt) (set (make-local-variable (car elt)) (cdr elt)))
-            '((file-of-tag-function . etags-file-of-tag)
-              (tags-table-files-function . etags-tags-table-files)
-              (tags-completion-table-function . etags-tags-completion-table)
-              (snarf-tag-function . etags-snarf-tag)
-              (goto-tag-location-function . etags-goto-tag-location)
-              (find-tag-regexp-search-function . re-search-forward)
-              (find-tag-regexp-tag-order . (tag-re-match-p))
-              (find-tag-regexp-next-line-after-failure-p . t)
-              (find-tag-search-function . search-forward)
-              (find-tag-tag-order . (tag-exact-file-name-match-p
-                                      tag-file-name-match-p
-                                     tag-exact-match-p
-                                     tag-implicit-name-match-p
-                                     tag-symbol-match-p
-                                     tag-word-match-p
-                                     tag-partial-file-name-match-p
-                                     tag-any-match-p))
-              (find-tag-next-line-after-failure-p . nil)
-              (list-tags-function . etags-list-tags)
-              (tags-apropos-function . etags-tags-apropos)
-              (tags-included-tables-function . etags-tags-included-tables)
-              (verify-tags-table-function . etags-verify-tags-table)
-              ))))
+  (when (etags-verify-tags-table)
+    (setq-local file-of-tag-function 'etags-file-of-tag)
+    (setq-local tags-table-files-function 'etags-tags-table-files)
+    (setq-local tags-completion-table-function 'etags-tags-completion-table)
+    (setq-local snarf-tag-function 'etags-snarf-tag)
+    (setq-local goto-tag-location-function 'etags-goto-tag-location)
+    (setq-local find-tag-regexp-search-function 're-search-forward)
+    (setq-local find-tag-regexp-tag-order '(tag-re-match-p))
+    (setq-local find-tag-regexp-next-line-after-failure-p t)
+    (setq-local find-tag-search-function 'search-forward)
+    (setq-local find-tag-tag-order '(tag-exact-file-name-match-p
+                                     tag-file-name-match-p
+                                     tag-exact-match-p
+                                     tag-implicit-name-match-p
+                                     tag-symbol-match-p
+                                     tag-word-match-p
+                                     tag-partial-file-name-match-p
+                                     tag-any-match-p))
+    (setq-local find-tag-next-line-after-failure-p nil)
+    (setq-local list-tags-function 'etags-list-tags)
+    (setq-local tags-apropos-function 'etags-tags-apropos)
+    (setq-local tags-included-tables-function 'etags-tags-included-tables)
+    (setq-local verify-tags-table-function 'etags-verify-tags-table)))
 
 (defun etags-verify-tags-table ()
   "Return non-nil if the current buffer is a valid etags TAGS file."
@@ -1593,16 +1588,16 @@ hits the start of file."
   "Return non-nil if current buffer is empty.
 If empty, make buffer-local values of the tags table format variables
 that do nothing."
-  (and (zerop (buffer-size))
-       (mapc (lambda (sym) (set (make-local-variable sym) 'ignore))
-            '(tags-table-files-function
-              tags-completion-table-function
-              find-tag-regexp-search-function
-              find-tag-search-function
-              tags-apropos-function
-              tags-included-tables-function))
-       (set (make-local-variable 'verify-tags-table-function)
-            (lambda () (zerop (buffer-size))))))
+  (when (zerop (buffer-size))
+    (setq-local tags-table-files-function #'ignore)
+    (setq-local tags-completion-table-function #'ignore)
+    (setq-local find-tag-regexp-search-function #'ignore)
+    (setq-local find-tag-search-function #'ignore)
+    (setq-local tags-apropos-function #'ignore)
+    (setq-local tags-included-tables-function #'ignore)
+    (setq-local verify-tags-table-function
+                (lambda () (zerop (buffer-size))))))
+
 
 ;; Match qualifier functions for tagnames.
 ;; These functions assume the etags file format defined in etc/ETAGS.EBNF.
diff --git a/lisp/progmodes/executable.el b/lisp/progmodes/executable.el
index bae2bb6..cc72809 100644
--- a/lisp/progmodes/executable.el
+++ b/lisp/progmodes/executable.el
@@ -197,7 +197,7 @@ command to find the next error.  The buffer is also in 
`comint-mode' and
                                      buffer-file-name))))
   (require 'compile)
   (save-some-buffers (not compilation-ask-about-save))
-  (set (make-local-variable 'executable-command) command)
+  (setq-local executable-command command)
   (let ((compilation-error-regexp-alist executable-error-regexp-alist))
     (compilation-start command t (lambda (_x) "*interpretation*"))))
 
diff --git a/lisp/progmodes/f90.el b/lisp/progmodes/f90.el
index 1fbbc89..3c5c29b 100644
--- a/lisp/progmodes/f90.el
+++ b/lisp/progmodes/f90.el
@@ -1179,29 +1179,26 @@ Turning on F90 mode calls the value of the variable 
`f90-mode-hook'
 with no args, if that value is non-nil."
   :group 'f90
   :abbrev-table f90-mode-abbrev-table
-  (set (make-local-variable 'indent-line-function) 'f90-indent-line)
-  (set (make-local-variable 'indent-region-function) 'f90-indent-region)
-  (set (make-local-variable 'comment-start) "!")
-  (set (make-local-variable 'comment-start-skip) "!+ *")
-  (set (make-local-variable 'comment-indent-function) 'f90-comment-indent)
-  (set (make-local-variable 'abbrev-all-caps) t)
-  (set (make-local-variable 'normal-auto-fill-function) 'f90-do-auto-fill)
+  (setq-local indent-line-function #'f90-indent-line)
+  (setq-local indent-region-function #'f90-indent-region)
+  (setq-local comment-start "!")
+  (setq-local comment-start-skip "!+ *")
+  (setq-local comment-indent-function 'f90-comment-indent)
+  (setq-local abbrev-all-caps t)
+  (setq-local normal-auto-fill-function #'f90-do-auto-fill)
   (setq indent-tabs-mode nil)           ; auto buffer local
-  (set (make-local-variable 'fill-paragraph-function) 'f90-fill-paragraph)
-  (set (make-local-variable 'font-lock-defaults)
-       '((f90-font-lock-keywords f90-font-lock-keywords-1
-                                 f90-font-lock-keywords-2
-                                 f90-font-lock-keywords-3
-                                 f90-font-lock-keywords-4)
-         nil t))
-  (set (make-local-variable 'imenu-case-fold-search) t)
-  (set (make-local-variable 'imenu-generic-expression)
-       f90-imenu-generic-expression)
-  (set (make-local-variable 'beginning-of-defun-function)
-       'f90-beginning-of-subprogram)
-  (set (make-local-variable 'end-of-defun-function) 'f90-end-of-subprogram)
-  (set (make-local-variable 'add-log-current-defun-function)
-       #'f90-current-defun))
+  (setq-local fill-paragraph-function #'f90-fill-paragraph)
+  (setq-local font-lock-defaults
+              '((f90-font-lock-keywords f90-font-lock-keywords-1
+                                        f90-font-lock-keywords-2
+                                        f90-font-lock-keywords-3
+                                        f90-font-lock-keywords-4)
+                nil t))
+  (setq-local imenu-case-fold-search t)
+  (setq-local imenu-generic-expression f90-imenu-generic-expression)
+  (setq-local beginning-of-defun-function #'f90-beginning-of-subprogram)
+  (setq-local end-of-defun-function #'f90-end-of-subprogram)
+  (setq-local add-log-current-defun-function #'f90-current-defun))
 
 
 ;; Inline-functions.
diff --git a/lisp/progmodes/flymake-cc.el b/lisp/progmodes/flymake-cc.el
index d1985b4..19cef85 100644
--- a/lisp/progmodes/flymake-cc.el
+++ b/lisp/progmodes/flymake-cc.el
@@ -50,7 +50,7 @@ SOURCE."
   ;; TODO: if you can understand it, use `compilation-mode's regexps
   ;; or even some of its machinery here.
   ;;
-  ;;    (set (make-local-variable 'compilation-locs)
+  ;;    (setq-local compilation-locs
   ;;         (make-hash-table :test 'equal :weakness 'value))
   ;;    (compilation-parse-errors (point-min) (point-max)
   ;;                              'gnu 'gcc-include)
diff --git a/lisp/progmodes/fortran.el b/lisp/progmodes/fortran.el
index d84c379..1142c32 100644
--- a/lisp/progmodes/fortran.el
+++ b/lisp/progmodes/fortran.el
@@ -861,36 +861,34 @@ with no args, if that value is non-nil."
   :group 'fortran
   :syntax-table fortran-mode-syntax-table
   :abbrev-table fortran-mode-abbrev-table
-  (set (make-local-variable 'indent-line-function) 'fortran-indent-line)
-  (set (make-local-variable 'indent-region-function)
+  (setq-local indent-line-function 'fortran-indent-line)
+  (setq-local indent-region-function
        (lambda (start end)
          (let (fortran-blink-matching-if ; avoid blinking delay
                indent-region-function)
            (indent-region start end nil))))
-  (set (make-local-variable 'require-final-newline) mode-require-final-newline)
+  (setq-local require-final-newline mode-require-final-newline)
   ;; The syntax tables don't understand the column-0 comment-markers.
-  (set (make-local-variable 'comment-use-syntax) nil)
-  (set (make-local-variable 'comment-padding) "$$$")
-  (set (make-local-variable 'comment-start) fortran-comment-line-start)
-  (set (make-local-variable 'comment-start-skip)
+  (setq-local comment-use-syntax nil)
+  (setq-local comment-padding "$$$")
+  (setq-local comment-start fortran-comment-line-start)
+  (setq-local comment-start-skip
        ;; We can't reuse `fortran-comment-line-start-skip' directly because
        ;; it contains backrefs whereas we need submatch-1 to end at the
        ;; beginning of the comment delimiter.
        ;; (concat "\\(\\)\\(![ \t]*\\|" fortran-comment-line-start-skip "\\)")
        "\\(\\)\\(?:^[CcDd*]\\|!\\)\\(?:\\([^ \t\n]\\)\\2+\\)?[ \t]*")
-  (set (make-local-variable 'comment-indent-function) 'fortran-comment-indent)
-  (set (make-local-variable 'comment-region-function) 'fortran-comment-region)
-  (set (make-local-variable 'uncomment-region-function)
-       'fortran-uncomment-region)
-  (set (make-local-variable 'comment-insert-comment-function)
-       'fortran-indent-comment)
-  (set (make-local-variable 'abbrev-all-caps) t)
-  (set (make-local-variable 'normal-auto-fill-function) 'fortran-auto-fill)
-  (set (make-local-variable 'indent-tabs-mode) (fortran-analyze-file-format))
+  (setq-local comment-indent-function 'fortran-comment-indent)
+  (setq-local comment-region-function 'fortran-comment-region)
+  (setq-local uncomment-region-function 'fortran-uncomment-region)
+  (setq-local comment-insert-comment-function 'fortran-indent-comment)
+  (setq-local abbrev-all-caps t)
+  (setq-local normal-auto-fill-function 'fortran-auto-fill)
+  (setq-local indent-tabs-mode (fortran-analyze-file-format))
   (setq mode-line-process '(indent-tabs-mode fortran-tab-mode-string))
-  (set (make-local-variable 'fill-column) fortran-line-length)
-  (set (make-local-variable 'fill-paragraph-function) 'fortran-fill-paragraph)
-  (set (make-local-variable 'font-lock-defaults)
+  (setq-local fill-column fortran-line-length)
+  (setq-local fill-paragraph-function 'fortran-fill-paragraph)
+  (setq-local font-lock-defaults
        '((fortran-font-lock-keywords
           fortran-font-lock-keywords-1
           fortran-font-lock-keywords-2
@@ -898,20 +896,19 @@ with no args, if that value is non-nil."
           fortran-font-lock-keywords-4)
          nil t ((?/ . "$/") ("_$" . "w"))
          fortran-beginning-of-subprogram))
-  (set (make-local-variable 'syntax-propertize-function)
+  (setq-local syntax-propertize-function
        (fortran-make-syntax-propertize-function fortran-line-length))
-  (set (make-local-variable 'imenu-case-fold-search) t)
-  (set (make-local-variable 'imenu-generic-expression)
-       fortran-imenu-generic-expression)
-  (set (make-local-variable 'imenu-syntax-alist) '(("_$" . "w")))
-  (set (make-local-variable 'beginning-of-defun-function)
-       #'fortran-beginning-of-subprogram)
-  (set (make-local-variable 'end-of-defun-function)
-       #'fortran-end-of-subprogram)
-  (set (make-local-variable 'add-log-current-defun-function)
-       #'fortran-current-defun)
-  (set (make-local-variable 'dabbrev-case-fold-search) 'case-fold-search)
-  (set (make-local-variable 'gud-find-expr-function) 'fortran-gud-find-expr)
+  (setq-local imenu-case-fold-search t)
+  (setq-local imenu-generic-expression fortran-imenu-generic-expression)
+  (setq-local imenu-syntax-alist '(("_$" . "w")))
+  (setq-local beginning-of-defun-function
+              #'fortran-beginning-of-subprogram)
+  (setq-local end-of-defun-function
+              #'fortran-end-of-subprogram)
+  (setq-local add-log-current-defun-function
+              #'fortran-current-defun)
+  (setq-local dabbrev-case-fold-search 'case-fold-search)
+  (setq-local gud-find-expr-function 'fortran-gud-find-expr)
   (add-hook 'hack-local-variables-hook 'fortran-hack-local-variables nil t))
 
 
@@ -1221,25 +1218,32 @@ Auto-indent does not happen if a numeric ARG is used."
 ;; Note that unlike the latter, we don't have to worry about nested
 ;; subprograms (?).
 ;; FIXME push-mark?
-(defun fortran-beginning-of-subprogram ()
-  "Move point to the beginning of the current Fortran subprogram."
+(defun fortran-beginning-of-subprogram (&optional arg)
+  "Move point to the beginning of the current Fortran subprogram.
+If ARG is negative, and point is between subprograms, the
+\"current\" subprogram is the next one."
   (interactive)
-  (let ((case-fold-search t))
-    ;; If called already at the start of subprogram, go to the previous.
-    (beginning-of-line (if (bolp) 0 1))
-    (save-match-data
-      (or (looking-at fortran-start-prog-re)
-          ;; This leaves us at bob if before the first subprogram.
-          (eq (fortran-previous-statement) 'first-statement)
-          (if (or (catch 'ok
-                    (while (re-search-backward fortran-end-prog-re nil 'move)
-                      (if (fortran-check-end-prog-re) (throw 'ok t))))
-                  ;; If the search failed, must be at bob.
-                  ;; First code line is the start of the subprogram.
-                  ;; FIXME use a more rigorous test, cf fortran-next-statement?
-                  ;; Though that needs to handle continuations too.
-                  (not (looking-at "^\\([ \t]*[0-9]\\|[ \t]+[^!#]\\)")))
-              (fortran-next-statement))))))
+  (if (and arg
+           (< arg 0))
+      (progn
+        (fortran-end-of-subprogram)
+        (fortran-beginning-of-subprogram))
+    (let ((case-fold-search t))
+      ;; If called already at the start of subprogram, go to the previous.
+      (beginning-of-line (if (bolp) 0 1))
+      (save-match-data
+        (or (looking-at fortran-start-prog-re)
+            ;; This leaves us at bob if before the first subprogram.
+            (eq (fortran-previous-statement) 'first-statement)
+            (if (or (catch 'ok
+                      (while (re-search-backward fortran-end-prog-re nil 'move)
+                        (if (fortran-check-end-prog-re) (throw 'ok t))))
+                    ;; If the search failed, must be at bob.
+                    ;; First code line is the start of the subprogram.
+                    ;; FIXME use a more rigorous test, cf 
fortran-next-statement?
+                    ;; Though that needs to handle continuations too.
+                    (not (looking-at "^\\([ \t]*[0-9]\\|[ \t]+[^!#]\\)")))
+                (fortran-next-statement)))))))
 
 ;; This is simpler than f-beginning-of-s because the end of a
 ;; subprogram is never implicit.
diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el
index 9030056..4c248f7 100644
--- a/lisp/progmodes/gdb-mi.el
+++ b/lisp/progmodes/gdb-mi.el
@@ -744,7 +744,7 @@ NOARG must be t when this macro is used outside `gud-def'."
       ;; Use the old gud-gbd filter, not because it works, but because it
       ;; will properly display GDB's answers rather than hanging waiting for
       ;; answers that aren't coming.
-      (set (make-local-variable 'gud-marker-filter) #'gud-gdb-marker-filter))
+      (setq-local gud-marker-filter #'gud-gdb-marker-filter))
     (funcall filter proc string)))
 
 (defvar gdb-control-level 0)
@@ -831,8 +831,8 @@ detailed description of this mode.
   (let ((proc (get-buffer-process gud-comint-buffer)))
     (add-function :around (process-filter proc) #'gdb--check-interpreter))
 
-  (set (make-local-variable 'gud-minor-mode) 'gdbmi)
-  (set (make-local-variable 'gdb-control-level) 0)
+  (setq-local gud-minor-mode 'gdbmi)
+  (setq-local gdb-control-level 0)
   (setq comint-input-sender 'gdb-send)
   (when (ring-empty-p comint-input-ring) ; cf shell-mode
     (let ((hfile (expand-file-name (or (getenv "GDBHISTFILE")
@@ -861,9 +861,9 @@ detailed description of this mode.
       (and (stringp hsize)
           (integerp (setq hsize (string-to-number hsize)))
           (> hsize 0)
-          (set (make-local-variable 'comint-input-ring-size) hsize))
+           (setq-local comint-input-ring-size hsize))
       (if (stringp hfile)
-         (set (make-local-variable 'comint-input-ring-file-name) hfile))
+          (setq-local comint-input-ring-file-name hfile))
       (comint-read-input-ring t)))
   (gud-def gud-tbreak "tbreak %f:%l" "\C-t"
           "Set temporary breakpoint at current line.")
@@ -966,8 +966,7 @@ detailed description of this mode.
   (define-key gud-minor-mode-map [left-margin C-mouse-3]
     'gdb-mouse-jump)
 
-  (set (make-local-variable 'gud-gdb-completion-function)
-       'gud-gdbmi-completions)
+  (setq-local gud-gdb-completion-function 'gud-gdbmi-completions)
 
   (add-hook 'completion-at-point-functions #'gud-gdb-completion-at-point
             nil 'local)
@@ -1141,8 +1140,8 @@ no input, and GDB is waiting for input."
                     (lambda () (gdb-tooltip-print expr)))))))
 
 (defun gdb-init-buffer ()
-  (set (make-local-variable 'gud-minor-mode) 'gdbmi)
-  (set (make-local-variable 'tool-bar-map) gud-tool-bar-map)
+  (setq-local gud-minor-mode 'gdbmi)
+  (setq-local tool-bar-map gud-tool-bar-map)
   (when gud-tooltip-mode
     (make-local-variable 'gdb-define-alist)
     (gdb-create-define-alist)
@@ -1558,10 +1557,10 @@ this trigger is subscribed to `gdb-buf-publisher' and 
called with
            (when mode (funcall mode))
            (setq gdb-buffer-type buffer-type)
             (when thread
-              (set (make-local-variable 'gdb-thread-number) thread))
-           (set (make-local-variable 'gud-minor-mode)
-                (buffer-local-value 'gud-minor-mode gud-comint-buffer))
-           (set (make-local-variable 'tool-bar-map) gud-tool-bar-map)
+              (setq-local gdb-thread-number thread))
+            (setq-local gud-minor-mode
+                        (buffer-local-value 'gud-minor-mode gud-comint-buffer))
+            (setq-local tool-bar-map gud-tool-bar-map)
             (rename-buffer (funcall (gdb-rules-name-maker rules)))
            (when trigger
               (gdb-add-subscriber gdb-buf-publisher
@@ -3364,8 +3363,7 @@ corresponding to the mode line clicked."
   (setq gdb-thread-position (make-marker))
   (add-to-list 'overlay-arrow-variable-list 'gdb-thread-position)
   (setq header-line-format gdb-threads-header)
-  (set (make-local-variable 'font-lock-defaults)
-       '(gdb-threads-font-lock-keywords))
+  (setq-local font-lock-defaults '(gdb-threads-font-lock-keywords))
   'gdb-invalidate-threads)
 
 (defun gdb-thread-list-handler-custom ()
@@ -3920,8 +3918,7 @@ DOC is an optional documentation string."
 (define-derived-mode gdb-memory-mode gdb-parent-mode "Memory"
   "Major mode for examining memory."
   (setq header-line-format gdb-memory-header)
-  (set (make-local-variable 'font-lock-defaults)
-       '(gdb-memory-font-lock-keywords))
+  (setq-local font-lock-defaults '(gdb-memory-font-lock-keywords))
   'gdb-invalidate-memory)
 
 (defun gdb-memory-buffer-name ()
@@ -4013,9 +4010,8 @@ DOC is an optional documentation string."
   ;; TODO Rename overlay variable for disassembly mode
   (add-to-list 'overlay-arrow-variable-list 'gdb-disassembly-position)
   (setq fringes-outside-margins t)
-  (set (make-local-variable 'gdb-disassembly-position) (make-marker))
-  (set (make-local-variable 'font-lock-defaults)
-       '(gdb-disassembly-font-lock-keywords))
+  (setq-local gdb-disassembly-position (make-marker))
+  (setq-local font-lock-defaults '(gdb-disassembly-font-lock-keywords))
   'gdb-invalidate-disassembly)
 
 (defun gdb-disassembly-handler-custom ()
@@ -4222,8 +4218,7 @@ member."
   (setq gdb-stack-position (make-marker))
   (add-to-list 'overlay-arrow-variable-list 'gdb-stack-position)
   (setq truncate-lines t)  ;; Make it easier to see overlay arrow.
-  (set (make-local-variable 'font-lock-defaults)
-       '(gdb-frames-font-lock-keywords))
+  (setq-local font-lock-defaults '(gdb-frames-font-lock-keywords))
   'gdb-invalidate-frames)
 
 (defun gdb-select-frame (&optional event)
diff --git a/lisp/progmodes/grep.el b/lisp/progmodes/grep.el
index dafba22..5dc99cc 100644
--- a/lisp/progmodes/grep.el
+++ b/lisp/progmodes/grep.el
@@ -100,7 +100,7 @@ To change the default value, use \\[customize] or call the 
function
   :set #'grep-apply-setting
   :version "22.1")
 
-(defcustom grep-match-regexp "\033\\[0?1;31m\\(.*?\\)\033\\[[0-9]*m"
+(defcustom grep-match-regexp "\033\\[\\(?:0?1;\\)?31m\\(.*?\\)\033\\[[0-9]*m"
   "Regular expression matching grep markers to highlight.
 It matches SGR ANSI escape sequences which are emitted by grep to
 color its output.  This variable is used in `grep-filter'."
@@ -412,7 +412,7 @@ Notice that using \\[next-error] or \\[compile-goto-error] 
modifies
                (- mend beg))))))
      nil nil
      (3 '(face nil display ":")))
-    ("^Binary file \\(.+\\) matches$" 1 nil nil 0 1))
+    ("^Binary file \\(.+\\) matches" 1 nil nil 0 1))
   "Regexp used to match grep hits.
 See `compilation-error-regexp-alist' for format details.")
 
@@ -568,8 +568,7 @@ Set up `compilation-exit-message-function' and run 
`grep-setup-hook'."
     ;; GREP_COLORS is used in GNU grep 2.5.2 and later versions
     (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)
+  (setq-local compilation-exit-message-function #'grep-exit-message)
   (run-hooks 'grep-setup-hook))
 
 (defun grep-exit-message (status code msg)
@@ -880,22 +879,22 @@ The value depends on `grep-command', `grep-template',
 (define-compilation-mode grep-mode "Grep"
   "Sets `grep-last-buffer' and `compilation-window-height'."
   (setq grep-last-buffer (current-buffer))
-  (set (make-local-variable 'tool-bar-map) grep-mode-tool-bar-map)
-  (set (make-local-variable 'compilation-error-face)
-       grep-hit-face)
-  (set (make-local-variable 'compilation-error-regexp-alist)
-       grep-regexp-alist)
-  (set (make-local-variable 'compilation-mode-line-errors)
-       grep-mode-line-matches)
+  (setq-local tool-bar-map grep-mode-tool-bar-map)
+  (setq-local compilation-error-face
+              grep-hit-face)
+  (setq-local compilation-error-regexp-alist
+              grep-regexp-alist)
+  (setq-local compilation-mode-line-errors
+              grep-mode-line-matches)
   ;; compilation-directory-matcher can't be nil, so we set it to a regexp that
   ;; can never match.
-  (set (make-local-variable 'compilation-directory-matcher)
-       (list regexp-unmatchable))
-  (set (make-local-variable 'compilation-process-setup-function)
-       #'grep-process-setup)
-  (set (make-local-variable 'compilation-disable-input) t)
-  (set (make-local-variable 'compilation-error-screen-columns)
-       grep-error-screen-columns)
+  (setq-local compilation-directory-matcher
+              (list regexp-unmatchable))
+  (setq-local compilation-process-setup-function
+              #'grep-process-setup)
+  (setq-local compilation-disable-input t)
+  (setq-local compilation-error-screen-columns
+              grep-error-screen-columns)
   (add-hook 'compilation-filter-hook #'grep-filter nil t))
 
 (defun grep--save-buffers ()
diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el
index 81021bc..134c2fc 100644
--- a/lisp/progmodes/gud.el
+++ b/lisp/progmodes/gud.el
@@ -758,7 +758,7 @@ the buffer in which this command was invoked."
      "Multiple debugging requires restarting in text command mode"))
 
   (gud-common-init command-line nil 'gud-gdb-marker-filter)
-  (set (make-local-variable 'gud-minor-mode) 'gdb)
+  (setq-local gud-minor-mode 'gdb)
 
   (gud-def gud-break  "break %f:%l"  "\C-b" "Set breakpoint at current line.")
   (gud-def gud-tbreak "tbreak %f:%l" "\C-t"
@@ -788,7 +788,7 @@ the buffer in which this command was invoked."
 
   (add-hook 'completion-at-point-functions #'gud-gdb-completion-at-point
             nil 'local)
-  (set (make-local-variable 'gud-gdb-completion-function) 'gud-gdb-completions)
+  (setq-local gud-gdb-completion-function 'gud-gdb-completions)
 
   (local-set-key "\C-i" 'completion-at-point)
   (setq comint-prompt-regexp "^(.*gdb[+]?) *")
@@ -1044,7 +1044,7 @@ and source-file directory for your debugger."
       (error "The sdb support requires a valid tags table to work"))
 
   (gud-common-init command-line nil 'gud-sdb-marker-filter 'gud-sdb-find-file)
-  (set (make-local-variable 'gud-minor-mode) 'sdb)
+  (setq-local gud-minor-mode 'sdb)
 
   (gud-def gud-break  "%l b" "\C-b"   "Set breakpoint at current line.")
   (gud-def gud-tbreak "%l c" "\C-t"   "Set temporary breakpoint at current 
line.")
@@ -1323,7 +1323,7 @@ and source-file directory for your debugger."
     (gud-common-init command-line 'gud-dbx-massage-args
                     'gud-dbx-marker-filter)))
 
-  (set (make-local-variable 'gud-minor-mode) 'dbx)
+  (setq-local gud-minor-mode 'dbx)
 
   (cond
    (gud-mips-p
@@ -1424,7 +1424,7 @@ directories if your program contains sources from more 
than one directory."
 
   (gud-common-init command-line 'gud-xdb-massage-args
                   'gud-xdb-marker-filter)
-  (set (make-local-variable 'gud-minor-mode) 'xdb)
+  (setq-local gud-minor-mode 'xdb)
 
   (gud-def gud-break  "b %f:%l"    "\C-b" "Set breakpoint at current line.")
   (gud-def gud-tbreak "b %f:%l\\t" "\C-t"
@@ -1578,7 +1578,7 @@ and source-file directory for your debugger."
 
   (gud-common-init command-line 'gud-perldb-massage-args
                   'gud-perldb-marker-filter)
-  (set (make-local-variable 'gud-minor-mode) 'perldb)
+  (setq-local gud-minor-mode 'perldb)
 
   (gud-def gud-break  "b %l"         "\C-b" "Set breakpoint at current line.")
   (gud-def gud-remove "B %l"         "\C-d" "Remove breakpoint at current 
line")
@@ -1683,7 +1683,7 @@ and source-file directory for your debugger."
 
 ;;;###autoload
 (defun pdb (command-line)
-  "Run COMMAND-LINE in the `*gud-FILE*' buffer.
+  "Run COMMAND-LINE in the `*gud-FILE*' buffer to debug Python programs.
 
 COMMAND-LINE should include the pdb executable
 name (`gud-pdb-command-name') and the file to be debugged.
@@ -1696,7 +1696,7 @@ directory and source-file directory for your debugger."
    (list (gud-query-cmdline 'pdb)))
 
   (gud-common-init command-line nil 'gud-pdb-marker-filter)
-  (set (make-local-variable 'gud-minor-mode) 'pdb)
+  (setq-local gud-minor-mode 'pdb)
 
   (gud-def gud-break  "break %d%f:%l"  "\C-b" "Set breakpoint at current 
line.")
   (gud-def gud-remove "clear %d%f:%l"  "\C-d" "Remove breakpoint at current 
line")
@@ -2418,7 +2418,7 @@ gud, see `gud-mode'."
 
   (gud-common-init command-line 'gud-jdb-massage-args
                   'gud-jdb-marker-filter)
-  (set (make-local-variable 'gud-minor-mode) 'jdb)
+  (setq-local gud-minor-mode 'jdb)
 
   ;; If a -classpath option was provided, set gud-jdb-classpath
   (if gud-jdb-classpath-string
@@ -2566,17 +2566,21 @@ You may use the `gud-def' macro in the initialization 
hook to define other
 commands.
 
 Other commands for interacting with the debugger process are inherited from
-comint mode, which see."
+`comint-mode', which see.
+
+Commands:
+
+\\{gud-mode-map}"
   (setq mode-line-process '(":%s"))
   (define-key (current-local-map) "\C-c\C-l" 'gud-refresh)
-  (set (make-local-variable 'gud-last-frame) nil)
+  (setq-local gud-last-frame nil)
   (if (boundp 'tool-bar-map)            ; not --without-x
       (setq-local tool-bar-map gud-tool-bar-map))
   (make-local-variable 'comint-prompt-regexp)
   ;; Don't put repeated commands in command history many times.
-  (set (make-local-variable 'comint-input-ignoredups) t)
+  (setq-local comint-input-ignoredups t)
   (make-local-variable 'paragraph-start)
-  (set (make-local-variable 'gud-delete-prompt-marker) (make-marker))
+  (setq-local gud-delete-prompt-marker (make-marker))
   (add-hook 'kill-buffer-hook 'gud-kill-buffer-hook nil t))
 
 (defcustom gud-chdir-before-run t
@@ -2649,10 +2653,10 @@ comint mode, which see."
           (if massage-args (funcall massage-args file args) args))
     ;; Since comint clobbered the mode, we don't set it until now.
     (gud-mode)
-    (set (make-local-variable 'gud-target-name)
+    (setq-local gud-target-name
         (and file-word (file-name-nondirectory file))))
-  (set (make-local-variable 'gud-marker-filter) marker-filter)
-  (if find-file (set (make-local-variable 'gud-find-file) find-file))
+  (setq-local gud-marker-filter marker-filter)
+  (if find-file (setq-local gud-find-file find-file))
   (setq gud-last-last-frame nil)
 
   (set-process-filter (get-buffer-process (current-buffer)) 'gud-filter)
@@ -3348,23 +3352,23 @@ Treats actions as defuns."
 ;;;###autoload
 (define-derived-mode gdb-script-mode prog-mode "GDB-Script"
   "Major mode for editing GDB scripts."
-  (set (make-local-variable 'comment-start) "#")
-  (set (make-local-variable 'comment-start-skip) "#+\\s-*")
-  (set (make-local-variable 'outline-regexp) "[ \t]")
-  (set (make-local-variable 'imenu-generic-expression)
-       '((nil "^define[ \t]+\\(\\w+\\)" 1)))
-  (set (make-local-variable 'indent-line-function) 'gdb-script-indent-line)
-  (set (make-local-variable 'beginning-of-defun-function)
-       #'gdb-script-beginning-of-defun)
-  (set (make-local-variable 'end-of-defun-function)
-       #'gdb-script-end-of-defun)
-  (set (make-local-variable 'font-lock-defaults)
-       '(gdb-script-font-lock-keywords nil nil ((?_ . "w")) nil
-        (font-lock-syntactic-face-function
-         . gdb-script-font-lock-syntactic-face)))
+  (setq-local comment-start "#")
+  (setq-local comment-start-skip "#+\\s-*")
+  (setq-local outline-regexp "[ \t]")
+  (setq-local imenu-generic-expression
+              '((nil "^define[ \t]+\\(\\w+\\)" 1)))
+  (setq-local indent-line-function 'gdb-script-indent-line)
+  (setq-local beginning-of-defun-function
+              #'gdb-script-beginning-of-defun)
+  (setq-local end-of-defun-function
+              #'gdb-script-end-of-defun)
+  (setq-local font-lock-defaults
+              '(gdb-script-font-lock-keywords nil nil ((?_ . "w")) nil
+                (font-lock-syntactic-face-function
+                 . gdb-script-font-lock-syntactic-face)))
   ;; Recognize docstrings.
-  (set (make-local-variable 'syntax-propertize-function)
-       gdb-script-syntax-propertize-function)
+  (setq-local syntax-propertize-function
+              gdb-script-syntax-propertize-function)
   (add-hook 'syntax-propertize-extend-region-functions
             #'syntax-propertize-multiline 'append 'local))
 
@@ -3471,8 +3475,8 @@ only tooltips in the buffer containing the overlay arrow."
 ACTIVATEP non-nil means activate mouse motion events."
   (if activatep
       (progn
-        (set (make-local-variable 'gud-tooltip-mouse-motions-active) t)
-        (set (make-local-variable 'track-mouse) t))
+        (setq-local gud-tooltip-mouse-motions-active t)
+        (setq-local track-mouse t))
     (when gud-tooltip-mouse-motions-active
       (kill-local-variable 'gud-tooltip-mouse-motions-active)
       (kill-local-variable 'track-mouse))))
diff --git a/lisp/progmodes/hideif.el b/lisp/progmodes/hideif.el
index 25e7523..7cbc970 100644
--- a/lisp/progmodes/hideif.el
+++ b/lisp/progmodes/hideif.el
@@ -302,17 +302,17 @@ Several variables affect how the hiding is done:
         ;; We can still simulate the behavior of older hideif versions (i.e.
         ;; `hide-ifdef-env' being buffer local) by clearing this variable
         ;; (C-c @ C) every time before hiding current buffer.
-;;      (set (make-local-variable 'hide-ifdef-env)
+;;      (setq-local hide-ifdef-env
 ;;           (default-value 'hide-ifdef-env))
         (set 'hide-ifdef-env (default-value 'hide-ifdef-env))
         ;; Some C/C++ headers might have other ways to prevent reinclusion and
         ;; thus would like `hide-ifdef-expand-reinclusion-protection' to be 
nil.
-        (set (make-local-variable 'hide-ifdef-expand-reinclusion-protection)
-             (default-value 'hide-ifdef-expand-reinclusion-protection))
-        (set (make-local-variable 'hide-ifdef-hiding)
-             (default-value 'hide-ifdef-hiding))
-        (set (make-local-variable 'hif-outside-read-only) buffer-read-only)
-        (set (make-local-variable 'line-move-ignore-invisible) t)
+        (setq-local hide-ifdef-expand-reinclusion-protection
+                    (default-value 'hide-ifdef-expand-reinclusion-protection))
+        (setq-local hide-ifdef-hiding
+                    (default-value 'hide-ifdef-hiding))
+        (setq-local hif-outside-read-only buffer-read-only)
+        (setq-local line-move-ignore-invisible t)
         (add-hook 'change-major-mode-hook
                   (lambda () (hide-ifdef-mode -1)) nil t)
 
@@ -1792,7 +1792,7 @@ It does not do the work that's pointless to redo on a 
recursive entry."
 (defun hide-ifdef-toggle-shadowing ()
   "Toggle shadowing."
   (interactive)
-  (set (make-local-variable 'hide-ifdef-shadow) (not hide-ifdef-shadow))
+  (setq-local hide-ifdef-shadow (not hide-ifdef-shadow))
   (message "Shadowing %s" (if hide-ifdef-shadow "ON" "OFF"))
   (save-restriction
     (widen)
diff --git a/lisp/progmodes/hideshow.el b/lisp/progmodes/hideshow.el
index 4dee72c..c882b7b 100644
--- a/lisp/progmodes/hideshow.el
+++ b/lisp/progmodes/hideshow.el
@@ -948,7 +948,7 @@ Key bindings:
         (add-hook 'change-major-mode-hook
                   #'turn-off-hideshow
                   nil t)
-        (set (make-local-variable 'line-move-ignore-invisible) t)
+        (setq-local line-move-ignore-invisible t)
         (add-to-invisibility-spec '(hs . t)))
     (remove-from-invisibility-spec '(hs . t))
     ;; hs-show-all does nothing unless h-m-m is non-nil.
diff --git a/lisp/progmodes/icon.el b/lisp/progmodes/icon.el
index bb43215..dd0ee95 100644
--- a/lisp/progmodes/icon.el
+++ b/lisp/progmodes/icon.el
@@ -163,25 +163,24 @@ Variables controlling indentation style:
 Turning on Icon mode calls the value of the variable `icon-mode-hook'
 with no args, if that value is non-nil."
   :abbrev-table icon-mode-abbrev-table
-  (set (make-local-variable 'paragraph-start) (concat "$\\|" page-delimiter))
-  (set (make-local-variable 'paragraph-separate) paragraph-start)
-  (set (make-local-variable 'indent-line-function) #'icon-indent-line)
-  (set (make-local-variable 'comment-start) "# ")
-  (set (make-local-variable 'comment-end) "")
-  (set (make-local-variable 'comment-start-skip) "# *")
-  (set (make-local-variable 'comment-indent-function) 'icon-comment-indent)
-  (set (make-local-variable 'indent-line-function) 'icon-indent-line)
+  (setq-local paragraph-start (concat "$\\|" page-delimiter))
+  (setq-local paragraph-separate paragraph-start)
+  (setq-local indent-line-function #'icon-indent-line)
+  (setq-local comment-start "# ")
+  (setq-local comment-end "")
+  (setq-local comment-start-skip "# *")
+  (setq-local comment-indent-function 'icon-comment-indent)
+  (setq-local indent-line-function 'icon-indent-line)
   ;; font-lock support
-  (set (make-local-variable 'font-lock-defaults)
-       '((icon-font-lock-keywords
-          icon-font-lock-keywords-1 icon-font-lock-keywords-2)
-         nil nil ((?_ . "w")) beginning-of-defun
-         ;; Obsoleted by Emacs 19.35 parse-partial-sexp's COMMENTSTOP.
-         ;;(font-lock-comment-start-regexp . "#")
-         (font-lock-mark-block-function . mark-defun)))
+  (setq-local font-lock-defaults
+              '((icon-font-lock-keywords
+                 icon-font-lock-keywords-1 icon-font-lock-keywords-2)
+                nil nil ((?_ . "w")) beginning-of-defun
+                ;; Obsoleted by Emacs 19.35 parse-partial-sexp's COMMENTSTOP.
+                ;;(font-lock-comment-start-regexp . "#")
+                (font-lock-mark-block-function . mark-defun)))
   ;; imenu support
-  (set (make-local-variable 'imenu-generic-expression)
-       icon-imenu-generic-expression)
+  (setq-local imenu-generic-expression icon-imenu-generic-expression)
   ;; hideshow support
   ;; we start from the assertion that `hs-special-modes-alist' is autoloaded.
   (unless (assq 'icon-mode hs-special-modes-alist)
diff --git a/lisp/progmodes/inf-lisp.el b/lisp/progmodes/inf-lisp.el
index 59db646..93d5d0f 100644
--- a/lisp/progmodes/inf-lisp.el
+++ b/lisp/progmodes/inf-lisp.el
@@ -124,9 +124,9 @@ mode.  Default is whitespace followed by 0 or 1 
single-letter colon-keyword
 (define-key lisp-mode-map "\C-c\C-v" 'lisp-show-variable-documentation)
 
 
-;;; This function exists for backwards compatibility.
-;;; Previous versions of this package bound commands to C-c <letter>
-;;; bindings, which is not allowed by the Emacs standard.
+;; This function exists for backwards compatibility.
+;; Previous versions of this package bound commands to C-c <letter>
+;; bindings, which is not allowed by the Emacs standard.
 
 ;;;  "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
@@ -274,7 +274,8 @@ If you accidentally suspend your process, use 
\\[comint-continue-subjob]
 to continue it."
   (setq comint-prompt-regexp inferior-lisp-prompt)
   (setq mode-line-process '(":%s"))
-  (lisp-mode-variables t)
+  (lisp-mode-variables)
+  (set-syntax-table lisp-mode-syntax-table)
   (setq comint-get-old-input (function lisp-get-old-input))
   (setq comint-input-filter (function lisp-input-filter)))
 
diff --git a/lisp/progmodes/ld-script.el b/lisp/progmodes/ld-script.el
index b17f255..656af69 100644
--- a/lisp/progmodes/ld-script.el
+++ b/lisp/progmodes/ld-script.el
@@ -173,10 +173,9 @@
 ;;;###autoload
 (define-derived-mode ld-script-mode prog-mode "LD-Script"
    "A major mode to edit GNU ld script files"
-  (set (make-local-variable 'comment-start) "/* ")
-  (set (make-local-variable 'comment-end)   " */")
-  (set (make-local-variable 'font-lock-defaults)
-       '(ld-script-font-lock-keywords nil)))
+  (setq-local comment-start "/* ")
+  (setq-local comment-end   " */")
+  (setq-local font-lock-defaults '(ld-script-font-lock-keywords nil)))
 
 (provide 'ld-script)
 
diff --git a/lisp/progmodes/make-mode.el b/lisp/progmodes/make-mode.el
index 3e49f84..8b6a7fc 100644
--- a/lisp/progmodes/make-mode.el
+++ b/lisp/progmodes/make-mode.el
@@ -343,8 +343,9 @@ not be enclosed in { } or ( )."
   "List of keywords understood by gmake.")
 
 (defconst makefile-bsdmake-statements
-  '(".elif" ".elifdef" ".elifmake" ".elifndef" ".elifnmake" ".else" ".endfor"
-    ".endif" ".for" ".if" ".ifdef" ".ifmake" ".ifndef" ".ifnmake" ".undef")
+  '("elif" "elifdef" "elifmake" "elifndef" "elifnmake" "else" "endfor"
+    "endif" "for" "if" "ifdef" "ifmake" "ifndef" "ifnmake" "poison"
+    "undef" "include")
   "List of keywords understood by BSD make.")
 
 (defun makefile-make-font-lock-keywords (var keywords space
@@ -376,8 +377,9 @@ not be enclosed in { } or ( )."
     ("[^$]\\(\\$[@%*]\\)"
      1 'makefile-targets append)
 
-    ;; Fontify conditionals and includes.
-    (,(concat "^\\(?: [ \t]*\\)?"
+    ,@(if keywords
+          ;; Fontify conditionals and includes.
+          `((,(concat "^\\(?: [ \t]*\\)?"
              (replace-regexp-in-string
               " " "[ \t]+"
               (if (eq (car keywords) t)
@@ -385,7 +387,7 @@ not be enclosed in { } or ( )."
                                              (regexp-opt (cdr keywords) t))
                 (regexp-opt keywords t)))
              "\\>[ \t]*\\([^: \t\n#]*\\)")
-     (1 font-lock-keyword-face) (2 font-lock-variable-name-face))
+             (1 font-lock-keyword-face) (2 font-lock-variable-name-face))))
 
     ,@(if negation
          `((,negation (1 font-lock-negation-char-face prepend)
@@ -493,13 +495,17 @@ not be enclosed in { } or ( )."
      1 'makefile-makepp-perl t)))
 
 (defconst makefile-bsdmake-font-lock-keywords
-  (makefile-make-font-lock-keywords
-   ;; A lot more could be done for variables here:
-   makefile-var-use-regex
-   makefile-bsdmake-statements
-   t
-   "^\\(?: [ \t]*\\)?\\.\\(?:el\\)?if\\(n?\\)\\(?:def\\|make\\)?\\>[ 
\t]*\\(!?\\)"
-   '("^[ \t]*\\.for[ \t].+[ \t]\\(in\\)\\>" 1 font-lock-keyword-face)))
+  (append
+   (makefile-make-font-lock-keywords
+    ;; A lot more could be done for variables here:
+    makefile-var-use-regex
+    nil
+    t
+    "^\\(?: [ \t]*\\)?\\.\\(?:el\\)?if\\(n?\\)\\(?:def\\|make\\)?\\>[ 
\t]*\\(!?\\)"
+    '("^[ \t]*\\.for[ \t].+[ \t]\\(in\\)\\>" 1 font-lock-keyword-face))
+   `((,(concat "^\\. *" (regexp-opt makefile-bsdmake-statements) "\\>") 0
+      font-lock-keyword-face))))
+
 
 (defconst makefile-imake-font-lock-keywords
   (append
diff --git a/lisp/progmodes/meta-mode.el b/lisp/progmodes/meta-mode.el
index 87c20a2..e15ec72 100644
--- a/lisp/progmodes/meta-mode.el
+++ b/lisp/progmodes/meta-mode.el
@@ -919,57 +919,55 @@ The environment marked is the one that contains point or 
follows point."
 (define-derived-mode meta-common-mode prog-mode "-Meta-common-"
   "Common initialization for Metafont or MetaPost mode."
   :abbrev-table meta-mode-abbrev-table
-  (set (make-local-variable 'paragraph-start)
-       (concat page-delimiter "\\|$"))
-  (set (make-local-variable 'paragraph-separate)
-       (concat page-delimiter "\\|$"))
+  (setq-local paragraph-start (concat page-delimiter "\\|$"))
+  (setq-local paragraph-separate (concat page-delimiter "\\|$"))
 
-  (set (make-local-variable 'paragraph-ignore-fill-prefix) t)
+  (setq-local paragraph-ignore-fill-prefix t)
 
-  (set (make-local-variable 'comment-start-skip) "%+[ \t\f]*")
-  (set (make-local-variable 'comment-start) "%")
-  (set (make-local-variable 'comment-end) "")
-  (set (make-local-variable 'comment-multi-line) nil)
+  (setq-local comment-start-skip "%+[ \t\f]*")
+  (setq-local comment-start "%")
+  (setq-local comment-end "")
+  (setq-local comment-multi-line nil)
 
   ;; We use `back-to-indentation' but \f is no indentation sign.
   (modify-syntax-entry ?\f "_   ")
 
-  (set (make-local-variable 'parse-sexp-ignore-comments) t)
+  (setq-local parse-sexp-ignore-comments t)
 
   (add-hook 'completion-at-point-functions #'meta-completions-at-point nil t)
-  (set (make-local-variable 'comment-indent-function) #'meta-comment-indent)
-  (set (make-local-variable 'indent-line-function) #'meta-indent-line)
+  (setq-local comment-indent-function #'meta-comment-indent)
+  (setq-local indent-line-function #'meta-indent-line)
   ;; No need to define a mode-specific 'indent-region-function.
   ;; Simply use the generic 'indent-region and 'comment-region.
 
   ;; Set defaults for font-lock mode.
-  (set (make-local-variable 'font-lock-defaults)
-       '(meta-font-lock-keywords
-         nil nil ((?_ . "w")) nil
-         (font-lock-comment-start-regexp . "%"))))
+  (setq-local font-lock-defaults
+              '(meta-font-lock-keywords
+                nil nil ((?_ . "w")) nil
+                (font-lock-comment-start-regexp . "%"))))
 
 
 ;;;###autoload
 (define-derived-mode metafont-mode meta-common-mode "Metafont"
   "Major mode for editing Metafont sources."
   ;; Set defaults for completion function.
-  (set (make-local-variable 'meta-symbol-list) nil)
-  (set (make-local-variable 'meta-symbol-changed) nil)
+  (setq-local meta-symbol-list nil)
+  (setq-local meta-symbol-changed nil)
   (apply 'meta-add-symbols metafont-symbol-list)
-  (set (make-local-variable 'meta-complete-list)
-        (list (list "\\<\\(\\sw+\\)" 1 'meta-symbol-list)
-              (list "" 'ispell-complete-word))))
+  (setq-local meta-complete-list
+              (list (list "\\<\\(\\sw+\\)" 1 'meta-symbol-list)
+                    (list "" 'ispell-complete-word))))
 
 ;;;###autoload
 (define-derived-mode metapost-mode meta-common-mode "MetaPost"
   "Major mode for editing MetaPost sources."
   ;; Set defaults for completion function.
-  (set (make-local-variable 'meta-symbol-list) nil)
-  (set (make-local-variable 'meta-symbol-changed) nil)
+  (setq-local meta-symbol-list nil)
+  (setq-local meta-symbol-changed nil)
   (apply 'meta-add-symbols metapost-symbol-list)
-  (set (make-local-variable 'meta-complete-list)
-        (list (list "\\<\\(\\sw+\\)" 1 'meta-symbol-list)
-              (list "" 'ispell-complete-word))))
+  (setq-local meta-complete-list
+              (list (list "\\<\\(\\sw+\\)" 1 'meta-symbol-list)
+                    (list "" 'ispell-complete-word))))
 
 
 ;;; Just in case ...
diff --git a/lisp/progmodes/mixal-mode.el b/lisp/progmodes/mixal-mode.el
index b9f6059..1f88e87 100644
--- a/lisp/progmodes/mixal-mode.el
+++ b/lisp/progmodes/mixal-mode.el
@@ -1141,18 +1141,18 @@ Assumes that file has been compiled with debugging 
support."
 ;;;###autoload
 (define-derived-mode mixal-mode prog-mode "mixal"
   "Major mode for the mixal asm language."
-  (set (make-local-variable 'comment-start) "*")
-  (set (make-local-variable 'comment-start-skip) "^\\*[ \t]*")
-  (set (make-local-variable 'font-lock-defaults)
-       '(mixal-font-lock-keywords))
-  (set (make-local-variable 'syntax-propertize-function)
-       mixal-syntax-propertize-function)
+  (setq-local comment-start "*")
+  (setq-local comment-start-skip "^\\*[ \t]*")
+  (setq-local font-lock-defaults
+              '(mixal-font-lock-keywords))
+  (setq-local syntax-propertize-function
+              mixal-syntax-propertize-function)
   ;; might add an indent function in the future
-  ;;  (set (make-local-variable 'indent-line-function) 'mixal-indent-line)
-  (set (make-local-variable 'compile-command)
-       (concat "mixasm "
-              (if buffer-file-name
-                  (shell-quote-argument buffer-file-name)))))
+  ;;  (setq-local indent-line-function 'mixal-indent-line)
+  (setq-local compile-command
+              (concat "mixasm "
+                      (if buffer-file-name
+                          (shell-quote-argument buffer-file-name)))))
 
 (provide 'mixal-mode)
 
diff --git a/lisp/progmodes/modula2.el b/lisp/progmodes/modula2.el
index aa41230..a77a4e2 100644
--- a/lisp/progmodes/modula2.el
+++ b/lisp/progmodes/modula2.el
@@ -308,14 +308,14 @@ followed by the first character of the construct.
    `m2-indent' controls the number of spaces for each indentation.
    `m2-compile-command' holds the command to compile a Modula-2 program.
    `m2-link-command' holds the command to link a Modula-2 program."
-  (set (make-local-variable 'paragraph-start) (concat "$\\|" page-delimiter))
-  (set (make-local-variable 'paragraph-separate) paragraph-start)
-  (set (make-local-variable 'paragraph-ignore-fill-prefix) t)
-  (set (make-local-variable 'comment-start) "(* ")
-  (set (make-local-variable 'comment-end) " *)")
-  (set (make-local-variable 'comment-start-skip) "\\(?:(\\*+\\|//+\\) *")
-  (set (make-local-variable 'parse-sexp-ignore-comments) t)
-  (set (make-local-variable 'font-lock-defaults)
+  (setq-local paragraph-start (concat "$\\|" page-delimiter))
+  (setq-local paragraph-separate paragraph-start)
+  (setq-local paragraph-ignore-fill-prefix t)
+  (setq-local comment-start "(* ")
+  (setq-local comment-end " *)")
+  (setq-local comment-start-skip "\\(?:(\\*+\\|//+\\) *")
+  (setq-local parse-sexp-ignore-comments t)
+  (setq-local font-lock-defaults
        '((m3-font-lock-keywords
           m3-font-lock-keywords-1 m3-font-lock-keywords-2)
          nil nil ((?_ . "w") (?. . "w") (?< . ". 1") (?> . ". 4")) nil
diff --git a/lisp/progmodes/perl-mode.el b/lisp/progmodes/perl-mode.el
index bb19436..fd8a51b 100644
--- a/lisp/progmodes/perl-mode.el
+++ b/lisp/progmodes/perl-mode.el
@@ -299,12 +299,21 @@
                ;; $a = "foo y \"toto\" bar" where we'd end up changing the
                ;; syntax of the backslash and hence de-escaping the embedded
                ;; double quote.
-               (put-text-property (match-beginning 3) (match-end 3)
-                                  'syntax-table
-                                  (if (assoc (char-after (match-beginning 3))
-                                             perl-quote-like-pairs)
-                                      (string-to-syntax "|")
-                                    (string-to-syntax "\"")))
+               (let* ((b3 (match-beginning 3))
+                      (c (char-after b3)))
+                 (put-text-property
+                  b3 (match-end 3) 'syntax-table
+                  (cond
+                   ((assoc c perl-quote-like-pairs)
+                    (string-to-syntax "|"))
+                   ;; If the separator is a normal quote and the operation
+                   ;; only takes a single arg, then there's nothing
+                   ;; special to do.
+                   ((and (memq c '(?\" ?\'))
+                         (memq (char-after (match-beginning 2)) '(?m ?q)))
+                    nil)
+                   (t
+                    (string-to-syntax "\"")))))
                (perl-syntax-propertize-special-constructs end))))))
       ;; Here documents.
       ((concat
@@ -379,7 +388,8 @@
             (put-text-property (1- (point)) (point) 'syntax-table
                                (string-to-syntax "> c"))))))
      ((or (null (setq char (nth 3 state)))
-          (and (characterp char) (eq (char-syntax (nth 3 state)) ?\")))
+          (and (characterp char)
+               (null (get-text-property (nth 8 state) 'syntax-table))))
       ;; Normal text, or comment, or docstring, or normal string.
       nil)
      ((eq (nth 3 state) ?\n)
@@ -400,6 +410,7 @@
                                                (point)))
                                '("tr" "s" "y"))))
             (close (cdr (assq char perl-quote-like-pairs)))
+            (middle nil)
             (st (perl-quote-syntax-table char)))
         (when (with-syntax-table st
                (if close
@@ -430,6 +441,7 @@
                           ;; In the case of s{...}{...}, we only handle the
                           ;; first part here and the next below.
                           (when (and twoargs (not close))
+                            (setq middle (point))
                             (nth 8 (parse-partial-sexp
                                     (point) limit
                                     nil nil state 'syntax-table)))))))
@@ -437,11 +449,14 @@
          (when (eq (char-before (1- (point))) ?$)
            (put-text-property (- (point) 2) (1- (point))
                               'syntax-table '(1)))
-         (put-text-property (1- (point)) (point)
-                            'syntax-table
-                            (if close
-                                (string-to-syntax "|")
-                              (string-to-syntax "\"")))
+         (if (and middle (memq char '(?\" ?\')))
+             (put-text-property (1- middle) middle
+                            'syntax-table '(1))
+           (put-text-property (1- (point)) (point)
+                              'syntax-table
+                              (if close
+                                  (string-to-syntax "|")
+                                (string-to-syntax "\""))))
          ;; If we have two args with a non-self-paired starter (e.g.
          ;; s{...}{...}) we're right after the first arg, so we still have to
          ;; handle the second part.
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index 449eadc..0ed5f1f 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -1,7 +1,7 @@
 ;;; project.el --- Operations on the current project  -*- lexical-binding: t; 
-*-
 
 ;; Copyright (C) 2015-2020 Free Software Foundation, Inc.
-;; Version: 0.5.2
+;; Version: 0.5.3
 ;; Package-Requires: ((emacs "26.3") (xref "1.0.2"))
 
 ;; This is a GNU ELPA :core package.  Avoid using functionality that
@@ -1275,13 +1275,15 @@ the menu entries in the dispatch menu.")
    "  "))
 
 ;;;###autoload
-(defun project-switch-project ()
+(defun project-switch-project (dir)
   "\"Switch\" to another project by running an Emacs command.
 The available commands are presented as a dispatch menu
-made from `project-switch-commands'."
-  (interactive)
-  (let ((dir (project-prompt-project-dir))
-        (choice nil))
+made from `project-switch-commands'.
+
+When called in a program, it will use the project corresponding
+to directory DIR."
+  (interactive (list (project-prompt-project-dir)))
+  (let ((choice nil))
     (while (not choice)
       (setq choice (assq (read-event (project--keymap-prompt))
                          project-switch-commands)))
diff --git a/lisp/progmodes/ps-mode.el b/lisp/progmodes/ps-mode.el
index 6db7a14..bcf7bfd 100644
--- a/lisp/progmodes/ps-mode.el
+++ b/lisp/progmodes/ps-mode.el
@@ -501,18 +501,18 @@ point to the corresponding spot in the PostScript window, 
if input
 to the interpreter was sent from that window.
 Typing \\<ps-run-mode-map>\\[ps-run-goto-error] when the cursor is at the 
number has the same effect."
   (setq-local syntax-propertize-function #'ps-mode-syntax-propertize)
-  (set (make-local-variable 'font-lock-defaults)
-       '((ps-mode-font-lock-keywords
-         ps-mode-font-lock-keywords-1
-         ps-mode-font-lock-keywords-2
-         ps-mode-font-lock-keywords-3)
-        nil))
+  (setq-local font-lock-defaults
+              '((ps-mode-font-lock-keywords
+                 ps-mode-font-lock-keywords-1
+                 ps-mode-font-lock-keywords-2
+                 ps-mode-font-lock-keywords-3)
+                nil))
   (smie-setup nil #'ps-mode-smie-rules)
   (setq-local electric-indent-chars
               (append '(?> ?\] ?\}) electric-indent-chars))
-  (set (make-local-variable 'comment-start) "%")
+  (setq-local comment-start "%")
   ;; NOTE: `\' has a special meaning in strings only
-  (set (make-local-variable 'comment-start-skip) "%+[ \t]*")
+  (setq-local comment-start-skip "%+[ \t]*")
   ;; enable doc-view-minor-mode => C-c C-c starts viewing the current ps file
   ;; with doc-view-mode.
   (doc-view-minor-mode 1))
@@ -910,11 +910,11 @@ plus the usually uncoded characters inserted on positions 
1 through 28."
 (define-derived-mode ps-run-mode comint-mode "Interactive PS"
   "Major mode in interactive PostScript window.
 This mode is invoked from `ps-mode' and should not be called directly."
-  (set (make-local-variable 'font-lock-defaults)
-       '((ps-run-font-lock-keywords
-         ps-run-font-lock-keywords-1
-         ps-run-font-lock-keywords-2)
-        t))
+  (setq-local font-lock-defaults
+              '((ps-run-font-lock-keywords
+                 ps-run-font-lock-keywords-1
+                 ps-run-font-lock-keywords-2)
+                t))
   (setq mode-line-process '(":%s")))
 
 (defun ps-run-running ()
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index e9c3b39..d75944a 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -4,8 +4,8 @@
 
 ;; Author: Fabián E. Gallina <fgallina@gnu.org>
 ;; URL: https://github.com/fgallina/python.el
-;; Version: 0.27
-;; Package-Requires: ((emacs "24.1") (cl-lib "1.0"))
+;; Version: 0.27.1
+;; Package-Requires: ((emacs "24.2") (cl-lib "1.0"))
 ;; Maintainer: emacs-devel@gnu.org
 ;; Created: Jul 2010
 ;; Keywords: languages
@@ -875,7 +875,7 @@ work on `python-indent-calculate-indentation' instead."
                  (python-util-forward-comment)
                  (current-indentation))))
           (if (and indentation (not (zerop indentation)))
-              (set (make-local-variable 'python-indent-offset) indentation)
+              (setq-local python-indent-offset indentation)
             (when python-indent-guess-indent-offset-verbose
               (message "Can't guess python-indent-offset, using defaults: %s"
                        python-indent-offset))))))))
@@ -2623,7 +2623,7 @@ also `with-current-buffer'."
        (set-buffer python-shell--font-lock-buffer)
        (when (not font-lock-mode)
          (font-lock-mode 1))
-       (set (make-local-variable 'delay-mode-hooks) t)
+       (setq-local delay-mode-hooks t)
        (let ((python-indent-guess-indent-offset nil))
          (when (not (derived-mode-p 'python-mode))
            (python-mode))
@@ -2702,7 +2702,7 @@ With argument MSG show activation message."
   (interactive "p")
   (python-shell-with-shell-buffer
     (python-shell-font-lock-kill-buffer)
-    (set (make-local-variable 'python-shell--font-lock-buffer) nil)
+    (setq-local python-shell--font-lock-buffer nil)
     (add-hook 'post-command-hook
               #'python-shell-font-lock-post-command-hook nil 'local)
     (add-hook 'kill-buffer-hook
@@ -2725,7 +2725,7 @@ With argument MSG show deactivation message."
        (cdr (python-util-comint-last-prompt))
        (line-end-position)
        '(face nil font-lock-face nil)))
-    (set (make-local-variable 'python-shell--font-lock-buffer) nil)
+    (setq-local python-shell--font-lock-buffer nil)
     (remove-hook 'post-command-hook
                  #'python-shell-font-lock-post-command-hook 'local)
     (remove-hook 'kill-buffer-hook
@@ -2741,8 +2741,8 @@ With argument MSG show deactivation message."
 With argument MSG show activation/deactivation message."
   (interactive "p")
   (python-shell-with-shell-buffer
-    (set (make-local-variable 'python-shell-font-lock-enable)
-         (not python-shell-font-lock-enable))
+    (setq-local python-shell-font-lock-enable
+                (not python-shell-font-lock-enable))
     (if python-shell-font-lock-enable
         (python-shell-font-lock-turn-on msg)
       (python-shell-font-lock-turn-off msg))
@@ -2765,9 +2765,9 @@ eventually provide a shell."
 (defun python-shell-comint-watch-for-first-prompt-output-filter (output)
   "Run `python-shell-first-prompt-hook' when first prompt is found in OUTPUT."
   (when (not python-shell--first-prompt-received)
-    (set (make-local-variable 
'python-shell--first-prompt-received-output-buffer)
-         (concat python-shell--first-prompt-received-output-buffer
-                 (ansi-color-filter-apply output)))
+    (setq-local python-shell--first-prompt-received-output-buffer
+                (concat python-shell--first-prompt-received-output-buffer
+                        (ansi-color-filter-apply output)))
     (when (python-shell-comint-end-of-output-p
            python-shell--first-prompt-received-output-buffer)
       (if (string-match-p
@@ -2775,7 +2775,7 @@ eventually provide a shell."
            (or python-shell--first-prompt-received-output-buffer ""))
           ;; Skip pdb prompts and reset the buffer.
           (setq python-shell--first-prompt-received-output-buffer nil)
-        (set (make-local-variable 'python-shell--first-prompt-received) t)
+        (setq-local python-shell--first-prompt-received t)
         (setq python-shell--first-prompt-received-output-buffer nil)
         (with-current-buffer (current-buffer)
           (let ((inhibit-quit nil))
@@ -2815,30 +2815,30 @@ variable.
 \(Type \\[describe-mode] in the process buffer for a list of commands.)"
   (when python-shell--parent-buffer
     (python-util-clone-local-variables python-shell--parent-buffer))
-  (set (make-local-variable 'indent-tabs-mode) nil)
+  (setq-local indent-tabs-mode nil)
   ;; Users can interactively override default values for
   ;; `python-shell-interpreter' and `python-shell-interpreter-args'
   ;; when calling `run-python'.  This ensures values let-bound in
   ;; `python-shell-make-comint' are locally set if needed.
-  (set (make-local-variable 'python-shell-interpreter)
-       (or python-shell--interpreter python-shell-interpreter))
-  (set (make-local-variable 'python-shell-interpreter-args)
-       (or python-shell--interpreter-args python-shell-interpreter-args))
-  (set (make-local-variable 'python-shell--prompt-calculated-input-regexp) nil)
-  (set (make-local-variable 'python-shell--block-prompt) nil)
-  (set (make-local-variable 'python-shell--prompt-calculated-output-regexp) 
nil)
+  (setq-local python-shell-interpreter
+              (or python-shell--interpreter python-shell-interpreter))
+  (setq-local python-shell-interpreter-args
+              (or python-shell--interpreter-args 
python-shell-interpreter-args))
+  (setq-local python-shell--prompt-calculated-input-regexp nil)
+  (setq-local python-shell--block-prompt nil)
+  (setq-local python-shell--prompt-calculated-output-regexp nil)
   (python-shell-prompt-set-calculated-regexps)
   (setq comint-prompt-regexp python-shell--prompt-calculated-input-regexp)
-  (set (make-local-variable 'comint-prompt-read-only) t)
+  (setq-local comint-prompt-read-only t)
   (setq mode-line-process '(":%s"))
-  (set (make-local-variable 'comint-output-filter-functions)
-       '(ansi-color-process-output
-         python-shell-comint-watch-for-first-prompt-output-filter
-         python-comint-postoutput-scroll-to-bottom
-         comint-watch-for-password-prompt))
+  (setq-local comint-output-filter-functions
+              '(ansi-color-process-output
+                python-shell-comint-watch-for-first-prompt-output-filter
+                python-comint-postoutput-scroll-to-bottom
+                comint-watch-for-password-prompt))
   (setq-local comint-highlight-input nil)
-  (set (make-local-variable 'compilation-error-regexp-alist)
-       python-shell-compilation-regexp-alist)
+  (setq-local compilation-error-regexp-alist
+              python-shell-compilation-regexp-alist)
   (add-hook 'completion-at-point-functions
             #'python-shell-completion-at-point nil 'local)
   (define-key inferior-python-mode-map "\t"
@@ -3605,7 +3605,7 @@ __PYTHON_EL_native_completion_setup()" process)
 With argument MSG show deactivation message."
   (interactive "p")
   (python-shell-with-shell-buffer
-    (set (make-local-variable 'python-shell-completion-native-enable) nil)
+    (setq-local python-shell-completion-native-enable nil)
     (when msg
       (message "Shell native completion is disabled, using fallback"))))
 
@@ -3614,7 +3614,7 @@ With argument MSG show deactivation message."
 With argument MSG show deactivation message."
   (interactive "p")
   (python-shell-with-shell-buffer
-    (set (make-local-variable 'python-shell-completion-native-enable) t)
+    (setq-local python-shell-completion-native-enable t)
     (python-shell-completion-native-turn-on-maybe msg)))
 
 (defun python-shell-completion-native-turn-on-maybe (&optional msg)
@@ -3994,7 +3994,7 @@ Argument OUTPUT is a string with the output from the 
comint process."
                  (tracked-buffer-window (get-buffer-window tracked-buffer))
                  (tracked-buffer-line-pos))
             (with-current-buffer tracked-buffer
-              (set (make-local-variable 'overlay-arrow-position) (make-marker))
+              (setq-local overlay-arrow-position (make-marker))
               (setq tracked-buffer-line-pos (progn
                                               (goto-char (point-min))
                                               (forward-line (1- line-number))
@@ -5535,48 +5535,43 @@ REPORT-FN is Flymake's callback function."
   "Major mode for editing Python files.
 
 \\{python-mode-map}"
-  (set (make-local-variable 'tab-width) 8)
-  (set (make-local-variable 'indent-tabs-mode) nil)
+  (setq-local tab-width 8)
+  (setq-local indent-tabs-mode nil)
 
-  (set (make-local-variable 'comment-start) "# ")
-  (set (make-local-variable 'comment-start-skip) "#+\\s-*")
+  (setq-local comment-start "# ")
+  (setq-local comment-start-skip "#+\\s-*")
 
-  (set (make-local-variable 'parse-sexp-lookup-properties) t)
-  (set (make-local-variable 'parse-sexp-ignore-comments) t)
+  (setq-local parse-sexp-lookup-properties t)
+  (setq-local parse-sexp-ignore-comments t)
 
-  (set (make-local-variable 'forward-sexp-function)
-       'python-nav-forward-sexp)
+  (setq-local forward-sexp-function #'python-nav-forward-sexp)
 
-  (set (make-local-variable 'font-lock-defaults)
-       `(,python-font-lock-keywords
-         nil nil nil nil
-         (font-lock-syntactic-face-function
-          . python-font-lock-syntactic-face-function)))
+  (setq-local font-lock-defaults
+              `(,python-font-lock-keywords
+                nil nil nil nil
+                (font-lock-syntactic-face-function
+                 . python-font-lock-syntactic-face-function)))
 
-  (set (make-local-variable 'syntax-propertize-function)
-       python-syntax-propertize-function)
+  (setq-local syntax-propertize-function
+              python-syntax-propertize-function)
 
-  (set (make-local-variable 'indent-line-function)
-       #'python-indent-line-function)
-  (set (make-local-variable 'indent-region-function) #'python-indent-region)
+  (setq-local indent-line-function #'python-indent-line-function)
+  (setq-local indent-region-function #'python-indent-region)
   ;; Because indentation is not redundant, we cannot safely reindent code.
-  (set (make-local-variable 'electric-indent-inhibit) t)
-  (set (make-local-variable 'electric-indent-chars)
-       (cons ?: electric-indent-chars))
+  (setq-local electric-indent-inhibit t)
+  (setq-local electric-indent-chars
+              (cons ?: electric-indent-chars))
 
   ;; Add """ ... """ pairing to electric-pair-mode.
   (add-hook 'post-self-insert-hook
             #'python-electric-pair-string-delimiter 'append t)
 
-  (set (make-local-variable 'paragraph-start) "\\s-*$")
-  (set (make-local-variable 'fill-paragraph-function)
-       #'python-fill-paragraph)
-  (set (make-local-variable 'normal-auto-fill-function) #'python-do-auto-fill)
+  (setq-local paragraph-start "\\s-*$")
+  (setq-local fill-paragraph-function #'python-fill-paragraph)
+  (setq-local normal-auto-fill-function #'python-do-auto-fill)
 
-  (set (make-local-variable 'beginning-of-defun-function)
-       #'python-nav-beginning-of-defun)
-  (set (make-local-variable 'end-of-defun-function)
-       #'python-nav-end-of-defun)
+  (setq-local beginning-of-defun-function #'python-nav-beginning-of-defun)
+  (setq-local end-of-defun-function #'python-nav-end-of-defun)
 
   (add-hook 'completion-at-point-functions
             #'python-completion-at-point nil 'local)
@@ -5584,26 +5579,25 @@ REPORT-FN is Flymake's callback function."
   (add-hook 'post-self-insert-hook
             #'python-indent-post-self-insert-function 'append 'local)
 
-  (set (make-local-variable 'imenu-create-index-function)
-       #'python-imenu-create-index)
+  (setq-local imenu-create-index-function
+              #'python-imenu-create-index)
 
-  (set (make-local-variable 'add-log-current-defun-function)
-       #'python-info-current-defun)
+  (setq-local add-log-current-defun-function
+              #'python-info-current-defun)
 
   (add-hook 'which-func-functions #'python-info-current-defun nil t)
 
-  (set (make-local-variable 'skeleton-further-elements)
-       '((abbrev-mode nil)
-         (< '(backward-delete-char-untabify (min python-indent-offset
-                                                 (current-column))))
-         (^ '(- (1+ (current-indentation))))))
+  (setq-local skeleton-further-elements
+              '((abbrev-mode nil)
+                (< '(backward-delete-char-untabify (min python-indent-offset
+                                                        (current-column))))
+                (^ '(- (1+ (current-indentation))))))
 
   (with-no-warnings
     ;; suppress warnings about eldoc-documentation-function being obsolete
    (if (null eldoc-documentation-function)
        ;; Emacs<25
-       (set (make-local-variable 'eldoc-documentation-function)
-            #'python-eldoc-function)
+       (setq-local eldoc-documentation-function #'python-eldoc-function)
      (if (boundp 'eldoc-documentation-functions)
          (add-hook 'eldoc-documentation-functions #'python-eldoc-function nil 
t)
        (add-function :before-until (local 'eldoc-documentation-function)
@@ -5620,16 +5614,14 @@ REPORT-FN is Flymake's callback function."
      python-hideshow-forward-sexp-function
      nil))
 
-  (set (make-local-variable 'outline-regexp)
-       (python-rx (* space) block-start))
-  (set (make-local-variable 'outline-heading-end-regexp) ":[^\n]*\n")
-  (set (make-local-variable 'outline-level)
-       #'(lambda ()
-           "`outline-level' function for Python mode."
-           (1+ (/ (current-indentation) python-indent-offset))))
+  (setq-local outline-regexp (python-rx (* space) block-start))
+  (setq-local outline-heading-end-regexp ":[^\n]*\n")
+  (setq-local outline-level
+              (lambda ()
+                "`outline-level' function for Python mode."
+                (1+ (/ (current-indentation) python-indent-offset))))
 
-  (set (make-local-variable 'prettify-symbols-alist)
-       python-prettify-symbols-alist)
+  (setq-local prettify-symbols-alist python-prettify-symbols-alist)
 
   (python-skeleton-add-menu-items)
 
diff --git a/lisp/progmodes/simula.el b/lisp/progmodes/simula.el
index be3edfd..44d4a9c 100644
--- a/lisp/progmodes/simula.el
+++ b/lisp/progmodes/simula.el
@@ -365,22 +365,22 @@ Variables controlling indentation style:
 
 Turning on SIMULA mode calls the value of the variable simula-mode-hook
 with no arguments, if that value is non-nil."
-  (set (make-local-variable 'comment-column) 40)
-  ;; (set (make-local-variable 'end-comment-column) 75)
-  (set (make-local-variable 'paragraph-start) "[ \t]*$\\|\f")
-  (set (make-local-variable 'paragraph-separate) paragraph-start)
-  (set (make-local-variable 'indent-line-function) 'simula-indent-line)
-  (set (make-local-variable 'comment-start) "! ")
-  (set (make-local-variable 'comment-end) " ;")
-  (set (make-local-variable 'comment-start-skip) "!+ *")
-  (set (make-local-variable 'parse-sexp-ignore-comments) nil)
-  (set (make-local-variable 'comment-multi-line) t)
-  (set (make-local-variable 'font-lock-defaults)
-       '((simula-font-lock-keywords simula-font-lock-keywords-1
-          simula-font-lock-keywords-2 simula-font-lock-keywords-3)
-         nil t ((?_ . "w"))))
-  (set (make-local-variable 'syntax-propertize-function)
-       simula-syntax-propertize-function)
+  (setq-local comment-column 40)
+  ;; (setq-local end-comment-column 75)
+  (setq-local paragraph-start "[ \t]*$\\|\f")
+  (setq-local paragraph-separate paragraph-start)
+  (setq-local indent-line-function 'simula-indent-line)
+  (setq-local comment-start "! ")
+  (setq-local comment-end " ;")
+  (setq-local comment-start-skip "!+ *")
+  (setq-local parse-sexp-ignore-comments nil)
+  (setq-local comment-multi-line t)
+  (setq-local font-lock-defaults
+              '((simula-font-lock-keywords simula-font-lock-keywords-1
+                 simula-font-lock-keywords-2 simula-font-lock-keywords-3)
+                nil t ((?_ . "w"))))
+  (setq-local syntax-propertize-function
+              simula-syntax-propertize-function)
   (abbrev-mode 1))
 
 (defun simula-indent-exp ()
diff --git a/lisp/progmodes/sql.el b/lisp/progmodes/sql.el
index 0bf9a51..78f8577 100644
--- a/lisp/progmodes/sql.el
+++ b/lisp/progmodes/sql.el
@@ -6,7 +6,6 @@
 ;; Maintainer: Michael Mauger <michael@mauger.com>
 ;; Version: 3.6
 ;; Keywords: comm languages processes
-;; URL: https://savannah.gnu.org/projects/emacs/
 
 ;; This file is part of GNU Emacs.
 
@@ -1725,7 +1724,7 @@ to add functions and PL/SQL keywords.")
                            "ORDER BY 2 DESC, 3 DESC, 4 DESC, 5 DESC, 6 DESC, 
1;")
                    nil nil)
       (with-current-buffer b
-        (set (make-local-variable 'sql-product) 'oracle)
+        (setq-local sql-product 'oracle)
         (sql-product-font-lock t nil)
         (font-lock-mode +1)))))
 
@@ -2812,7 +2811,7 @@ configured."
       ((syntax-alist (sql-product-font-lock-syntax-alist)))
 
     ;; Get the product-specific keywords.
-    (set (make-local-variable 'sql-mode-font-lock-keywords)
+    (setq-local sql-mode-font-lock-keywords
          (append
           (unless (eq sql-product 'ansi)
             (sql-get-product-feature sql-product :font-lock))
@@ -2824,7 +2823,7 @@ configured."
 
     ;; Setup font-lock.  Force re-parsing of `font-lock-defaults'.
     (kill-local-variable 'font-lock-set-defaults)
-    (set (make-local-variable 'font-lock-defaults)
+    (setq-local font-lock-defaults
          (list 'sql-mode-font-lock-keywords
                keywords-only t syntax-alist))
 
@@ -4134,8 +4133,8 @@ details or extends the listing to include other schemas 
objects."
     (sql-execute-feature sqlbuf "*List All*" :list-all enhanced nil)
     (with-current-buffer sqlbuf
       ;; Contains the name of database objects
-      (set (make-local-variable 'sql-contains-names) t)
-      (set (make-local-variable 'sql-buffer) sqlbuf))))
+      (setq-local sql-contains-names t)
+      (setq-local sql-buffer sqlbuf))))
 
 (defun sql-list-table (name &optional enhanced)
   "List the details of a database table named NAME.
@@ -4190,7 +4189,7 @@ must tell Emacs.  Here's how to do that in your init file:
       (easy-menu-add sql-mode-menu))
 
   ;; (smie-setup sql-smie-grammar #'sql-smie-rules)
-  (set (make-local-variable 'comment-start) "--")
+  (setq-local comment-start "--")
   ;; Make each buffer in sql-mode remember the "current" SQLi buffer.
   (make-local-variable 'sql-buffer)
   ;; Add imenu support for sql-mode.  Note that imenu-generic-expression
@@ -4200,12 +4199,12 @@ must tell Emacs.  Here's how to do that in your init 
file:
        imenu-case-fold-search t)
   ;; Make `sql-send-paragraph' work on paragraphs that contain indented
   ;; lines.
-  (set (make-local-variable 'paragraph-separate) "[\f]*$")
-  (set (make-local-variable 'paragraph-start) "[\n\f]")
+  (setq-local paragraph-separate "[\f]*$")
+  (setq-local paragraph-start "[\n\f]")
   ;; Abbrevs
   (setq-local abbrev-all-caps 1)
   ;; Contains the name of database objects
-  (set (make-local-variable 'sql-contains-names) t)
+  (setq-local sql-contains-names t)
   (setq-local syntax-propertize-function
               (syntax-propertize-rules
                ;; Handle escaped apostrophes within strings.
@@ -4304,9 +4303,8 @@ you entered, right above the output it created.
   :after-hook (sql--adjust-interactive-setup)
 
   ;; Get the `sql-product' for this interactive session.
-  (set (make-local-variable 'sql-product)
-       (or sql-interactive-product
-          sql-product))
+  (setq-local sql-product (or sql-interactive-product
+                           sql-product))
 
   ;; Setup the mode.
   (setq mode-name
@@ -4323,7 +4321,7 @@ you entered, right above the output it created.
   (sql-product-font-lock t nil)
 
   ;; Enable commenting and uncommenting of the region.
-  (set (make-local-variable 'comment-start) "--")
+  (setq-local comment-start "--")
   ;; Abbreviation table init and case-insensitive.  It is not activated
   ;; by default.
   (setq local-abbrev-table sql-mode-abbrev-table)
@@ -4332,27 +4330,27 @@ you entered, right above the output it created.
   (let ((proc (get-buffer-process (current-buffer))))
     (when proc (set-process-sentinel proc #'sql-stop)))
   ;; Save the connection and login params
-  (set (make-local-variable 'sql-user)       sql-user)
-  (set (make-local-variable 'sql-database)   sql-database)
-  (set (make-local-variable 'sql-server)     sql-server)
-  (set (make-local-variable 'sql-port)       sql-port)
-  (set (make-local-variable 'sql-connection) sql-connection)
+  (setq-local sql-user       sql-user)
+  (setq-local sql-database   sql-database)
+  (setq-local sql-server     sql-server)
+  (setq-local sql-port       sql-port)
+  (setq-local sql-connection sql-connection)
   (setq-default sql-connection nil)
   ;; Contains the name of database objects
-  (set (make-local-variable 'sql-contains-names) t)
+  (setq-local sql-contains-names t)
   ;; Keep track of existing object names
-  (set (make-local-variable 'sql-completion-object) nil)
-  (set (make-local-variable 'sql-completion-column) nil)
+  (setq-local sql-completion-object nil)
+  (setq-local sql-completion-column nil)
   ;; Create a useful name for renaming this buffer later.
-  (set (make-local-variable 'sql-alternate-buffer-name)
-       (sql-make-alternate-buffer-name))
+  (setq-local sql-alternate-buffer-name
+              (sql-make-alternate-buffer-name))
   ;; User stuff.  Initialize before the hook.
-  (set (make-local-variable 'sql-prompt-regexp)
-       (or (sql-get-product-feature sql-product :prompt-regexp) "^"))
-  (set (make-local-variable 'sql-prompt-length)
-       (sql-get-product-feature sql-product :prompt-length))
-  (set (make-local-variable 'sql-prompt-cont-regexp)
-       (sql-get-product-feature sql-product :prompt-cont-regexp))
+  (setq-local sql-prompt-regexp
+              (or (sql-get-product-feature sql-product :prompt-regexp) "^"))
+  (setq-local sql-prompt-length
+              (sql-get-product-feature sql-product :prompt-length))
+  (setq-local sql-prompt-cont-regexp
+              (sql-get-product-feature sql-product :prompt-cont-regexp))
   (make-local-variable 'sql-output-newline-count)
   (make-local-variable 'sql-preoutput-hold)
   (add-hook 'comint-preoutput-filter-functions
@@ -4370,7 +4368,7 @@ you entered, right above the output it created.
           sql-prompt-regexp))
   (setq left-margin (or sql-prompt-length 0))
   ;; Install input sender
-  (set (make-local-variable 'comint-input-sender) #'sql-input-sender)
+  (setq-local comint-input-sender #'sql-input-sender)
   ;; People wanting a different history file for each
   ;; buffer/process/client/whatever can change separator and file-name
   ;; on the sql-interactive-mode-hook.
@@ -4651,8 +4649,7 @@ the call to \\[sql-product-interactive] with
 
               ;; Set the new buffer name
               (setq new-sqli-buffer (current-buffer))
-              (set (make-local-variable 'sql-buffer)
-                   (buffer-name new-sqli-buffer))
+              (setq-local sql-buffer (buffer-name new-sqli-buffer))
 
               ;; Set `sql-buffer' in the start buffer
               (with-current-buffer start-buffer
diff --git a/lisp/progmodes/subword.el b/lisp/progmodes/subword.el
index 0f2c943..b0df909 100644
--- a/lisp/progmodes/subword.el
+++ b/lisp/progmodes/subword.el
@@ -332,7 +332,7 @@ as parts of words: e.g., in `superword-mode',
 searching subwords in order to avoid unwanted reentrancy.")
 
 (defun subword-setup-buffer ()
-  (set (make-local-variable 'find-word-boundary-function-table)
+  (setq-local find-word-boundary-function-table
        (if (or subword-mode superword-mode)
            subword-find-word-boundary-function-table
          subword-empty-char-table)))
diff --git a/lisp/progmodes/tcl.el b/lisp/progmodes/tcl.el
index ff3fb96..dbf6684 100644
--- a/lisp/progmodes/tcl.el
+++ b/lisp/progmodes/tcl.el
@@ -616,41 +616,39 @@ Turning on Tcl mode runs `tcl-mode-hook'.  Read the 
documentation for
 `tcl-mode-hook' to see what kinds of interesting hook functions
 already exist."
   (unless (and (boundp 'filladapt-mode) filladapt-mode)
-    (set (make-local-variable 'paragraph-ignore-fill-prefix) t))
+    (setq-local paragraph-ignore-fill-prefix t))
 
-  (set (make-local-variable 'indent-line-function) #'tcl-indent-line)
-  (set (make-local-variable 'comment-indent-function) #'tcl-comment-indent)
+  (setq-local indent-line-function #'tcl-indent-line)
+  (setq-local comment-indent-function #'tcl-comment-indent)
   ;; Tcl doesn't require a final newline.
-  ;; (make-local-variable 'require-final-newline)
-  ;; (setq require-final-newline t)
+  ;; (setq-local require-final-newline t)
 
-  (set (make-local-variable 'comment-start) "# ")
-  (set (make-local-variable 'comment-start-skip)
-       "\\(\\(^\\|[;{[]\\)\\s-*\\)#+ *")
-  (set (make-local-variable 'comment-end) "")
+  (setq-local comment-start "# ")
+  (setq-local comment-start-skip
+              "\\(\\(^\\|[;{[]\\)\\s-*\\)#+ *")
+  (setq-local comment-end "")
 
-  (set (make-local-variable 'outline-regexp) ".")
-  (set (make-local-variable 'outline-level) 'tcl-outline-level)
+  (setq-local outline-regexp ".")
+  (setq-local outline-level 'tcl-outline-level)
 
-  (set (make-local-variable 'font-lock-defaults)
-       '(tcl-font-lock-keywords nil nil nil beginning-of-defun))
-  (set (make-local-variable 'syntax-propertize-function)
-       tcl-syntax-propertize-function)
+  (setq-local font-lock-defaults
+              '(tcl-font-lock-keywords nil nil nil beginning-of-defun))
+  (setq-local syntax-propertize-function
+              tcl-syntax-propertize-function)
   (add-hook 'syntax-propertize-extend-region-functions
             #'syntax-propertize-multiline 'append 'local)
 
-  (set (make-local-variable 'imenu-generic-expression)
-       tcl-imenu-generic-expression)
+  (setq-local imenu-generic-expression tcl-imenu-generic-expression)
 
   ;; Settings for new dabbrev code.
-  (set (make-local-variable 'dabbrev-case-fold-search) nil)
-  (set (make-local-variable 'dabbrev-case-replace) nil)
-  (set (make-local-variable 'dabbrev-abbrev-skip-leading-regexp) "[$!]")
-  (set (make-local-variable 'dabbrev-abbrev-char-regexp) "\\sw\\|\\s_")
-
-  (set (make-local-variable 'parse-sexp-ignore-comments) t)
-  (set (make-local-variable 'defun-prompt-regexp) tcl-omit-ws-regexp)
-  (set (make-local-variable 'add-log-current-defun-function)
+  (setq-local dabbrev-case-fold-search nil)
+  (setq-local dabbrev-case-replace nil)
+  (setq-local dabbrev-abbrev-skip-leading-regexp "[$!]")
+  (setq-local dabbrev-abbrev-char-regexp "\\sw\\|\\s_")
+
+  (setq-local parse-sexp-ignore-comments t)
+  (setq-local defun-prompt-regexp tcl-omit-ws-regexp)
+  (setq-local add-log-current-defun-function
        #'tcl-add-log-defun)
 
   (setq-local beginning-of-defun-function #'tcl-beginning-of-defun-function)
@@ -1201,14 +1199,14 @@ Variables controlling Inferior Tcl mode:
 
 The following commands are available:
 \\{inferior-tcl-mode-map}"
-  (set (make-local-variable 'comint-prompt-regexp)
-       (or tcl-prompt-regexp
-          (concat "^" (regexp-quote tcl-application) ">")))
+  (setq-local comint-prompt-regexp
+              (or tcl-prompt-regexp
+                  (concat "^" (regexp-quote tcl-application) ">")))
   (setq mode-line-process '(": %s"))
   (setq local-abbrev-table tcl-mode-abbrev-table)
   (set-syntax-table tcl-mode-syntax-table)
-  (set (make-local-variable 'defun-prompt-regexp) tcl-omit-ws-regexp)
-  (set (make-local-variable 'inferior-tcl-delete-prompt-marker) (make-marker))
+  (setq-local defun-prompt-regexp tcl-omit-ws-regexp)
+  (setq-local inferior-tcl-delete-prompt-marker (make-marker))
   (set-process-filter (get-buffer-process (current-buffer)) 'tcl-filter))
 
 ;;;###autoload
@@ -1229,7 +1227,7 @@ See documentation for function `inferior-tcl-mode' for 
more information."
     (unless (process-tty-name (inferior-tcl-proc))
       (tcl-send-string (inferior-tcl-proc)
                        "set ::tcl_interactive 1; concat\n")))
-  (set (make-local-variable 'tcl-application) cmd)
+  (setq-local tcl-application cmd)
   (setq inferior-tcl-buffer "*inferior-tcl*")
   (pop-to-buffer "*inferior-tcl*"))
 
@@ -1493,7 +1491,7 @@ Prefix argument means switch to the Tcl buffer 
afterwards."
   (interactive "P")
   (auto-fill-mode arg)
   (if auto-fill-function
-      (set (make-local-variable 'comment-auto-fill-only-comments) t)
+      (setq-local comment-auto-fill-only-comments t)
     (kill-local-variable 'comment-auto-fill-only-comments)))
 
 (defun tcl-electric-hash (&optional count)
@@ -1574,7 +1572,7 @@ The first line is assumed to look like \"#!.../program 
...\"."
   (save-excursion
     (goto-char (point-min))
     (if (looking-at "#![^ \t]*/\\([^ \t\n/]+\\)\\([ \t]\\|$\\)")
-       (set (make-local-variable 'tcl-application) (match-string 1)))))
+        (setq-local tcl-application (match-string 1)))))
 
 (defun tcl-popup-menu (_e)
   "XEmacs menu support."
diff --git a/lisp/progmodes/which-func.el b/lisp/progmodes/which-func.el
index 266f40a..a524bba 100644
--- a/lisp/progmodes/which-func.el
+++ b/lisp/progmodes/which-func.el
@@ -293,7 +293,7 @@ If no function name is found, return nil."
                 (null which-function-imenu-failed))
         (ignore-errors (imenu--make-index-alist t))
         (unless imenu--index-alist
-          (set (make-local-variable 'which-function-imenu-failed) t)))
+          (setq-local which-function-imenu-failed t)))
       ;; If we have an index alist, use it.
       (when (and (null name)
                 (boundp 'imenu--index-alist) imenu--index-alist)
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index 9f5fc57..6e99e9d 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -1,7 +1,7 @@
 ;;; xref.el --- Cross-referencing commands              -*-lexical-binding:t-*-
 
 ;; Copyright (C) 2014-2020 Free Software Foundation, Inc.
-;; Version: 1.0.3
+;; Version: 1.0.4
 ;; Package-Requires: ((emacs "26.3"))
 
 ;; This is a GNU ELPA :core package.  Avoid functionality that is not
@@ -593,6 +593,25 @@ SELECT is `quit', also quit the *xref* window."
   (xref--search-property 'xref-item t)
   (xref-show-location-at-point))
 
+(defun xref-next-group ()
+  "Move to the first item of the next xref group and display its source."
+  (interactive)
+  (xref--search-property 'xref-group)
+  (xref--search-property 'xref-item)
+  (xref-show-location-at-point))
+
+(defun xref-prev-group ()
+  "Move to the first item of the previous xref group and display its source."
+  (interactive)
+  ;; Search for the xref group of the current item, provided that the
+  ;; point is not already in an xref group.
+  (unless (plist-member (text-properties-at (point)) 'xref-group)
+    (xref--search-property 'xref-group t))
+  ;; Search for the previous xref group.
+  (xref--search-property 'xref-group t)
+  (xref--search-property 'xref-item)
+  (xref-show-location-at-point))
+
 (defun xref--item-at-point ()
   (save-excursion
     (back-to-indentation)
@@ -738,6 +757,8 @@ references displayed in the current *xref* buffer."
   (let ((map (make-sparse-keymap)))
     (define-key map (kbd "n") #'xref-next-line)
     (define-key map (kbd "p") #'xref-prev-line)
+    (define-key map (kbd "N") #'xref-next-group)
+    (define-key map (kbd "P") #'xref-prev-group)
     (define-key map (kbd "r") #'xref-query-replace-in-results)
     (define-key map (kbd "RET") #'xref-goto-xref)
     (define-key map (kbd "TAB")  #'xref-quit-and-goto-xref)
@@ -1334,7 +1355,9 @@ The template should have the following fields:
   <R> for the regexp itself (in Extended format)"
   :type '(repeat
           (cons (symbol :tag "Program identifier")
-                (string :tag "Command template"))))
+                (string :tag "Command template")))
+  :version "28.1"
+  :package-version '(xref . "1.0.4"))
 
 (defcustom xref-search-program 'grep
   "The program to use for regexp search inside files.
@@ -1343,7 +1366,9 @@ This must reference a corresponding entry in 
`xref-search-program-alist'."
   :type `(choice
           (const :tag "Use Grep" grep)
           (const :tag "Use ripgrep" ripgrep)
-          (symbol :tag "User defined")))
+          (symbol :tag "User defined"))
+  :version "28.1"
+  :package-version '(xref . "1.0.4"))
 
 ;;;###autoload
 (defun xref-matches-in-files (regexp files)
diff --git a/lisp/progmodes/xscheme.el b/lisp/progmodes/xscheme.el
index c699786..cdbafba 100644
--- a/lisp/progmodes/xscheme.el
+++ b/lisp/progmodes/xscheme.el
@@ -173,7 +173,7 @@ With argument, asks for a command line."
   (setq-default xscheme-process-command-line command-line)
   (switch-to-buffer
    (xscheme-start-process command-line process-name buffer-name))
-  (set (make-local-variable 'xscheme-process-command-line) command-line))
+  (setq-local xscheme-process-command-line command-line))
 
 (defun xscheme-read-command-line (arg)
   (let ((default
@@ -264,11 +264,11 @@ With argument, asks for a command line."
                      xscheme-buffer-name
                      t)))
   (let ((process-name (verify-xscheme-buffer buffer-name t)))
-    (set (make-local-variable 'xscheme-buffer-name) buffer-name)
-    (set (make-local-variable 'xscheme-process-name) process-name)
-    (set (make-local-variable 'xscheme-runlight)
-         (with-current-buffer buffer-name
-           xscheme-runlight))))
+    (setq-local xscheme-buffer-name buffer-name)
+    (setq-local xscheme-process-name process-name)
+    (setq-local xscheme-runlight
+                (with-current-buffer buffer-name
+                  xscheme-runlight))))
 
 (defun local-clear-scheme-interaction-buffer ()
   "Make the current buffer use the default scheme interaction buffer."
@@ -375,10 +375,10 @@ Entry to this mode runs `scheme-mode-hook' and then
         (kill-all-local-variables)
         (make-local-variable 'xscheme-runlight-string)
         (make-local-variable 'xscheme-runlight)
-        (set (make-local-variable 'xscheme-previous-mode) previous-mode)
+        (setq-local xscheme-previous-mode previous-mode)
         (let ((buffer (current-buffer)))
-          (set (make-local-variable 'xscheme-buffer-name) (buffer-name buffer))
-          (set (make-local-variable 'xscheme-last-input-end) (make-marker))
+          (setq-local xscheme-buffer-name (buffer-name buffer))
+          (setq-local xscheme-last-input-end (make-marker))
           (let ((process (get-buffer-process buffer)))
             (when process
               (setq-local xscheme-process-name (process-name process))
diff --git a/lisp/recentf.el b/lisp/recentf.el
index 61c39de..7463637 100644
--- a/lisp/recentf.el
+++ b/lisp/recentf.el
@@ -1127,7 +1127,7 @@ IGNORE arguments."
   (unless recentf-list
     (error "The list of recent files is empty"))
   (recentf-dialog (format "*%s - Edit list*" recentf-menu-title)
-    (set (make-local-variable 'recentf-edit-list) nil)
+    (setq-local recentf-edit-list nil)
     (widget-insert
      (format-message
       "Click on OK to delete selected files from the recent list.
@@ -1196,8 +1196,8 @@ IGNORE other arguments."
 
 (defun recentf-open-files-items (files)
   "Return a list of widgets to display FILES in a dialog buffer."
-  (set (make-local-variable 'recentf--files-with-key)
-       (recentf-trunc-list files 10))
+  (setq-local recentf--files-with-key
+              (recentf-trunc-list files 10))
   (mapcar 'recentf-open-files-item
           (append
            ;; When requested group the files with shortcuts together
diff --git a/lisp/replace.el b/lisp/replace.el
index 3a2ab1d..5ebc549 100644
--- a/lisp/replace.el
+++ b/lisp/replace.el
@@ -1706,7 +1706,7 @@ See also `multi-occur'."
            (buffer-undo-list t)
            (occur--final-pos nil))
        (erase-buffer)
-        (set (make-local-variable 'occur-highlight-regexp) regexp)
+        (setq-local occur-highlight-regexp regexp)
        (let ((count
               (if (stringp nlines)
                    ;; Treat nlines as a regexp to collect.
diff --git a/lisp/reveal.el b/lisp/reveal.el
index f9e3864..b4558e1 100644
--- a/lisp/reveal.el
+++ b/lisp/reveal.el
@@ -233,7 +233,7 @@ Also see the `reveal-auto-hide' variable."
   :keymap reveal-mode-map
   (if reveal-mode
       (progn
-       (set (make-local-variable 'search-invisible) t)
+        (setq-local search-invisible t)
        (add-hook 'post-command-hook 'reveal-post-command nil t))
     (kill-local-variable 'search-invisible)
     (remove-hook 'post-command-hook 'reveal-post-command t)))
diff --git a/lisp/ruler-mode.el b/lisp/ruler-mode.el
index 82e6178..d97abca 100644
--- a/lisp/ruler-mode.el
+++ b/lisp/ruler-mode.el
@@ -584,8 +584,8 @@ format first."
   (when (and (not ruler-mode)
             (local-variable-p 'header-line-format)
             (not (local-variable-p 'ruler-mode-header-line-format-old)))
-    (set (make-local-variable 'ruler-mode-header-line-format-old)
-        header-line-format))
+    (setq-local ruler-mode-header-line-format-old
+                header-line-format))
   (setq header-line-format ruler-mode-header-line-format))
 
 ;;;###autoload
diff --git a/lisp/scroll-lock.el b/lisp/scroll-lock.el
index f20ea1b..31808be 100644
--- a/lisp/scroll-lock.el
+++ b/lisp/scroll-lock.el
@@ -64,7 +64,7 @@ MS-Windows systems if `w32-scroll-lock-modifier' is non-nil."
       (progn
        (setq scroll-lock-preserve-screen-pos-save
              scroll-preserve-screen-position)
-       (set (make-local-variable 'scroll-preserve-screen-position) 'always))
+        (setq-local scroll-preserve-screen-position 'always))
     (setq scroll-preserve-screen-position
          scroll-lock-preserve-screen-pos-save)))
 
diff --git a/lisp/server.el b/lisp/server.el
index 056f324..84c2e00 100644
--- a/lisp/server.el
+++ b/lisp/server.el
@@ -268,6 +268,12 @@ the \"-f\" switch otherwise."
   :type 'string
   :version "23.1")
 
+(defcustom server-client-instructions t
+  "If non-nil, display instructions on how to exit the client on connection.
+If nil, no instructions are displayed."
+  :version "28.1"
+  :type 'boolean)
+
 ;; We do not use `temporary-file-directory' here, because emacsclient
 ;; does not read the init file.
 (defvar server-socket-dir
@@ -1333,6 +1339,8 @@ The following commands are accepted by the client:
   ;; inhibit-quit flag, which is good since `commands' (as well as
   ;; find-file-noselect via the major-mode) can run arbitrary code,
   ;; including code that needs to wait.
+  (when (and frame server-raise-frame)
+    (select-frame-set-input-focus frame))
   (with-local-quit
     (condition-case err
         (let ((buffers (server-visit-files files proc nowait)))
@@ -1365,8 +1373,10 @@ The following commands are accepted by the client:
             nil)
            ((and frame (null buffers))
             (run-hooks 'server-after-make-frame-hook)
-            (message "%s" (substitute-command-keys
-                           "When done with this frame, type 
\\[delete-frame]")))
+            (when server-client-instructions
+              (message "%s"
+                       (substitute-command-keys
+                        "When done with this frame, type \\[delete-frame]"))))
            ((not (null buffers))
             (run-hooks 'server-after-make-frame-hook)
             (server-switch-buffer
@@ -1377,9 +1387,11 @@ The following commands are accepted by the client:
              ;; where it may be displayed.
              (plist-get (process-plist proc) 'frame))
             (run-hooks 'server-switch-hook)
-            (unless nowait
-              (message "%s" (substitute-command-keys
-                             "When done with a buffer, type 
\\[server-edit]")))))
+            (when (and (not nowait)
+                       server-client-instructions)
+              (message "%s"
+                       (substitute-command-keys
+                        "When done with a buffer, type \\[server-edit]")))))
           (when (and frame (null tty-name))
             (server-unselect-display frame)))
       ((quit error)
@@ -1681,9 +1693,7 @@ be a cons cell (LINENUMBER . COLUMNNUMBER)."
                   (switch-to-buffer next-buffer))
              ;; After all the above, we might still have ended up with
              ;; a minibuffer/dedicated-window (if there's no other).
-             (error (pop-to-buffer next-buffer)))))))
-    (when server-raise-frame
-      (select-frame-set-input-focus (window-frame)))))
+             (error (pop-to-buffer next-buffer)))))))))
 
 ;;;###autoload
 (defun server-save-buffers-kill-terminal (arg)
diff --git a/lisp/shell.el b/lisp/shell.el
index 5fed651..5cc9a18 100644
--- a/lisp/shell.el
+++ b/lisp/shell.el
@@ -471,32 +471,32 @@ Shell buffers.  It implements `shell-completion-execonly' 
for
 
 (defun shell-completion-vars ()
   "Setup completion vars for `shell-mode' and `read-shell-command'."
-  (set (make-local-variable 'comint-completion-fignore)
-       shell-completion-fignore)
-  (set (make-local-variable 'comint-delimiter-argument-list)
-       shell-delimiter-argument-list)
-  (set (make-local-variable 'comint-file-name-chars) shell-file-name-chars)
-  (set (make-local-variable 'comint-file-name-quote-list)
-       shell-file-name-quote-list)
-  (set (make-local-variable 'comint-file-name-prefix)
-       (or (file-remote-p default-directory) ""))
-  (set (make-local-variable 'comint-dynamic-complete-functions)
-       shell-dynamic-complete-functions)
+  (setq-local comint-completion-fignore
+              shell-completion-fignore)
+  (setq-local comint-delimiter-argument-list
+              shell-delimiter-argument-list)
+  (setq-local comint-file-name-chars shell-file-name-chars)
+  (setq-local comint-file-name-quote-list
+              shell-file-name-quote-list)
+  (setq-local comint-file-name-prefix
+              (or (file-remote-p default-directory) ""))
+  (setq-local comint-dynamic-complete-functions
+              shell-dynamic-complete-functions)
   (setq-local comint-unquote-function #'shell--unquote-argument)
   (setq-local comint-requote-function #'shell--requote-argument)
-  (set (make-local-variable 'pcomplete-parse-arguments-function)
-       #'shell--parse-pcomplete-arguments)
-  (set (make-local-variable 'pcomplete-termination-string)
-       (cond ((not comint-completion-addsuffix) "")
-             ((stringp comint-completion-addsuffix)
-              comint-completion-addsuffix)
-             ((not (consp comint-completion-addsuffix)) " ")
-             (t (cdr comint-completion-addsuffix))))
-  (set (make-local-variable 'pcomplete-command-completion-function)
-       #'shell-command-completion-function)
+  (setq-local pcomplete-parse-arguments-function
+              #'shell--parse-pcomplete-arguments)
+  (setq-local pcomplete-termination-string
+              (cond ((not comint-completion-addsuffix) "")
+                    ((stringp comint-completion-addsuffix)
+                     comint-completion-addsuffix)
+                    ((not (consp comint-completion-addsuffix)) " ")
+                    (t (cdr comint-completion-addsuffix))))
+  (setq-local pcomplete-command-completion-function
+              #'shell-command-completion-function)
   ;; Don't use pcomplete's defaulting mechanism, rely on
   ;; shell-dynamic-complete-functions instead.
-  (set (make-local-variable 'pcomplete-default-completion-function) #'ignore)
+  (setq-local pcomplete-default-completion-function #'ignore)
   (setq-local comint-input-autoexpand shell-input-autoexpand)
   ;; Not needed in shell-mode because it's inherited from comint-mode, but
   ;; placed here for read-shell-command.
@@ -596,7 +596,7 @@ buffer."
       (and (stringp hsize)
           (integerp (setq hsize (string-to-number hsize)))
           (> hsize 0)
-          (set (make-local-variable 'comint-input-ring-size) hsize))
+           (setq-local comint-input-ring-size hsize))
       (setq comint-input-ring-file-name
             (concat
              remote
diff --git a/lisp/simple.el b/lisp/simple.el
index 1f90db3..9787ad1 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -1922,7 +1922,7 @@ to get different commands to edit and resubmit."
                     (setq execute-extended-command--last-typed
                               (minibuffer-contents)))
                   nil 'local)
-       (set (make-local-variable 'minibuffer-default-add-function)
+        (setq-local minibuffer-default-add-function
             (lambda ()
               ;; Get a command name at point in the original buffer
               ;; to propose it after M-n.
@@ -2372,10 +2372,10 @@ negative number -N means the Nth entry of \"future 
history.\""
     (unless (memq last-command '(next-history-element
                                 previous-history-element))
       (let ((prompt-end (minibuffer-prompt-end)))
-       (set (make-local-variable 'minibuffer-temporary-goal-position)
-            (cond ((<= (point) prompt-end) prompt-end)
-                  ((eobp) nil)
-                  (t (point))))))
+        (setq-local minibuffer-temporary-goal-position
+                    (cond ((<= (point) prompt-end) prompt-end)
+                          ((eobp) nil)
+                          (t (point))))))
     (goto-char (point-max))
     (delete-minibuffer-contents)
     (setq minibuffer-history-position nabs)
@@ -2548,14 +2548,14 @@ Return 0 if current buffer is not a minibuffer."
 (defun minibuffer-history-isearch-setup ()
   "Set up a minibuffer for using isearch to search the minibuffer history.
 Intended to be added to `minibuffer-setup-hook'."
-  (set (make-local-variable 'isearch-search-fun-function)
-       'minibuffer-history-isearch-search)
-  (set (make-local-variable 'isearch-message-function)
-       'minibuffer-history-isearch-message)
-  (set (make-local-variable 'isearch-wrap-function)
-       'minibuffer-history-isearch-wrap)
-  (set (make-local-variable 'isearch-push-state-function)
-       'minibuffer-history-isearch-push-state)
+  (setq-local isearch-search-fun-function
+              #'minibuffer-history-isearch-search)
+  (setq-local isearch-message-function
+              #'minibuffer-history-isearch-message)
+  (setq-local isearch-wrap-function
+              #'minibuffer-history-isearch-wrap)
+  (setq-local isearch-push-state-function
+              #'minibuffer-history-isearch-push-state)
   (add-hook 'isearch-mode-end-hook 'minibuffer-history-isearch-end nil t))
 
 (defun minibuffer-history-isearch-end ()
@@ -3585,8 +3585,8 @@ to `shell-command-history'."
   (minibuffer-with-setup-hook
       (lambda ()
         (shell-completion-vars)
-       (set (make-local-variable 'minibuffer-default-add-function)
-            'minibuffer-default-add-shell-commands))
+        (setq-local minibuffer-default-add-function
+                    #'minibuffer-default-add-shell-commands))
     (apply #'read-from-minibuffer prompt initial-contents
           minibuffer-local-shell-command-map
           nil
@@ -6426,7 +6426,8 @@ for it.")
             (<= position (point-max)))
        (if widen-automatically
            (widen)
-         (error "Global mark position is outside accessible part of buffer")))
+         (error "Global mark position is outside accessible part of buffer %s"
+                 (buffer-name buffer))))
     (goto-char position)
     (switch-to-buffer buffer)))
 
@@ -7201,6 +7202,12 @@ rests."
   "Move point to visible beginning of current logical line.
 This disregards any invisible newline characters.
 
+When moving from position that has no `field' property, this
+command doesn't enter text which has non-nil `field' property.
+In particular, when invoked in the minibuffer, the command will
+stop short of entering the text of the minibuffer prompt.
+See `inhibit-field-text-motion' for how to inhibit this.
+
 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.
 \(But if the buffer doesn't end in a newline, it stops at the
@@ -7430,8 +7437,8 @@ Mode' for details."
            (if (local-variable-p var)
                (push (cons var (symbol-value var))
                      visual-line--saved-state))))
-       (set (make-local-variable 'line-move-visual) t)
-       (set (make-local-variable 'truncate-partial-width-windows) nil)
+        (setq-local line-move-visual t)
+        (setq-local truncate-partial-width-windows nil)
        (setq truncate-lines nil
              word-wrap t
              fringe-indicator-alist
@@ -8824,10 +8831,9 @@ Called from `temp-buffer-show-hook'."
       (let ((base-position completion-base-position)
             (insert-fun completion-list-insert-choice-function))
         (completion-list-mode)
-        (set (make-local-variable 'completion-base-position) base-position)
-        (set (make-local-variable 'completion-list-insert-choice-function)
-            insert-fun))
-      (set (make-local-variable 'completion-reference-buffer) mainbuf)
+        (setq-local completion-base-position base-position)
+        (setq-local completion-list-insert-choice-function insert-fun))
+      (setq-local completion-reference-buffer mainbuf)
       (if base-dir (setq default-directory base-dir))
       (when completion-tab-width
         (setq tab-width completion-tab-width))
@@ -9287,8 +9293,7 @@ to a non-nil value."
   (cond
    ((and (not buffer-read-only) view-mode)
     (View-exit-and-edit)
-    (make-local-variable 'view-read-only)
-    (setq view-read-only t))           ; Must leave view mode.
+    (setq-local view-read-only t))             ; Must leave view mode.
    ((and buffer-read-only view-read-only
          ;; If view-mode is already active, `view-mode-enter' is a nop.
          (not view-mode)
@@ -9306,8 +9311,8 @@ and setting it to nil."
     (setq buffer-invisibility-spec vis-mode-saved-buffer-invisibility-spec)
     (kill-local-variable 'vis-mode-saved-buffer-invisibility-spec))
   (when visible-mode
-    (set (make-local-variable 'vis-mode-saved-buffer-invisibility-spec)
-        buffer-invisibility-spec)
+    (setq-local vis-mode-saved-buffer-invisibility-spec
+                buffer-invisibility-spec)
     (setq buffer-invisibility-spec nil)))
 
 (defvar messages-buffer-mode-map
diff --git a/lisp/skeleton.el b/lisp/skeleton.el
index 6e2c10d..5578a93 100644
--- a/lisp/skeleton.el
+++ b/lisp/skeleton.el
@@ -312,10 +312,15 @@ automatically, and you are prompted to fill in the 
variable parts.")))
         (save-excursion (insert "\n")))
     (unwind-protect
        (setq prompt (cond ((stringp prompt)
-                            (read-string (format prompt skeleton-subprompt)
-                                         (setq initial-input
-                                               (or initial-input
-                                                   (symbol-value 'input)))))
+                            ;; The user may issue commands to move
+                            ;; around (like `C-M-v').  Ensure that we
+                            ;; insert the skeleton at the correct
+                            ;; (initial) point.
+                            (save-excursion
+                              (read-string (format prompt skeleton-subprompt)
+                                           (setq initial-input
+                                                 (or initial-input
+                                                     (symbol-value 'input))))))
                            ((functionp prompt)
                             (funcall prompt))
                            (t (eval prompt))))
diff --git a/lisp/speedbar.el b/lisp/speedbar.el
index 3468780..e2cfe98 100644
--- a/lisp/speedbar.el
+++ b/lisp/speedbar.el
@@ -979,10 +979,9 @@ supported at a time.
     (speedbar-set-timer dframe-update-speed)
     )
   ;; Frame modifications
-  (set (make-local-variable 'dframe-delete-frame-function)
-       'speedbar-handle-delete-frame)
+  (setq-local dframe-delete-frame-function 'speedbar-handle-delete-frame)
   ;; hscroll
-  (set (make-local-variable 'auto-hscroll-mode) nil)
+  (setq-local auto-hscroll-mode nil)
   ;; reset the selection variable
   (setq speedbar-last-selected-file nil))
 
@@ -1075,9 +1074,8 @@ in the selected file.
   (save-excursion
     (setq font-lock-keywords nil) ;; no font-locking please
     (setq truncate-lines t)
-    (make-local-variable 'frame-title-format)
-    (setq frame-title-format "Speedbar"
-         case-fold-search nil
+    (setq-local frame-title-format "Speedbar")
+    (setq case-fold-search nil
          buffer-read-only t)
     (speedbar-set-mode-line-format)
     ;; Add in our dframe hooks.
@@ -1814,16 +1812,13 @@ of the special mode functions."
              (setq v (intern-soft (concat ms "-speedbar-key-map")))
              (if (not v)
                  nil ;; don't add special keymap
-               (make-local-variable 'speedbar-special-mode-key-map)
-               (setq speedbar-special-mode-key-map
-                     (symbol-value v)))
+                (setq-local speedbar-special-mode-key-map
+                            (symbol-value v)))
              (setq v (intern-soft (concat ms "-speedbar-menu-items")))
              (if (not v)
                  nil ;; don't add special menus
-               (make-local-variable 'speedbar-easymenu-definition-special)
-               (setq speedbar-easymenu-definition-special
-                     (symbol-value v)))
-             )))))))
+                (setq-local speedbar-easymenu-definition-special
+                            (symbol-value v))))))))))
 
 (defun speedbar-remove-localized-speedbar-support (buffer)
   "Remove any traces that BUFFER supports speedbar in a specialized way."
diff --git a/lisp/startup.el b/lisp/startup.el
index e3c792e..84a8604 100644
--- a/lisp/startup.el
+++ b/lisp/startup.el
@@ -633,7 +633,7 @@ It is the default value of the variable `top-level'."
       (with-current-buffer "*Messages*"
         (messages-buffer-mode)
         ;; Make it easy to do like "tail -f".
-        (set (make-local-variable 'window-point-insertion-type) t)
+        (setq-local window-point-insertion-type t)
         ;; Give *Messages* the same default-directory as *scratch*,
         ;; just to keep things predictable.
        (setq default-directory (or dir (expand-file-name "~/")))))
@@ -2001,7 +2001,7 @@ splash screen in another window."
       (setq buffer-read-only nil)
       (erase-buffer)
       (setq default-directory command-line-default-directory)
-      (set (make-local-variable 'tab-width) 8)
+      (setq-local tab-width 8)
 
       (if pure-space-overflow
          (insert pure-space-overflow-message))
diff --git a/lisp/strokes.el b/lisp/strokes.el
index 11bc07a..0448720 100644
--- a/lisp/strokes.el
+++ b/lisp/strokes.el
@@ -1231,8 +1231,8 @@ the stroke as a character in some language."
 ;;     mode-popup-menu edit-strokes-menu) ; what about extent-specific stuff?
 ;;  (and (featurep 'menubar)
 ;;       current-menubar
-;;       (set (make-local-variable 'current-menubar)
-;;         (copy-sequence current-menubar))
+;;       (setq-local current-menubar
+;;                   (copy-sequence current-menubar))
 ;;       (add-submenu nil edit-strokes-menu)))
 
 ;;(let ((map edit-strokes-mode-map))
@@ -1363,13 +1363,13 @@ If STROKES-MAP is not given, `strokes-global-map' will 
be used instead."
      finally do (unless (eobp)
                   (kill-region (1+ (point)) (point-max))))
     (view-buffer "*Strokes List*" nil)
-    (set (make-local-variable 'view-mode-map)
-        (let ((map (copy-keymap view-mode-map)))
-          (define-key map "q" `(lambda ()
-                                 (interactive)
-                                 (View-quit)
-                                 (set-window-configuration ,config)))
-          map))
+    (setq-local view-mode-map
+                (let ((map (copy-keymap view-mode-map)))
+                  (define-key map "q" `(lambda ()
+                                         (interactive)
+                                         (View-quit)
+                                         (set-window-configuration ,config)))
+                  map))
     (goto-char (point-min))))
 
 (defun strokes-alphabetic-lessp (stroke1 stroke2)
diff --git a/lisp/subr.el b/lisp/subr.el
index 4b75268..ed235ee 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -2745,20 +2745,22 @@ floating point support."
   "Insert the character you type in the minibuffer and exit.
 Discard all previous input before inserting and exiting the minibuffer."
   (interactive)
-  (delete-minibuffer-contents)
-  (insert last-command-event)
-  (exit-minibuffer))
+  (when (minibufferp)
+    (delete-minibuffer-contents)
+    (insert last-command-event)
+    (exit-minibuffer)))
 
 (defun read-char-from-minibuffer-insert-other ()
   "Handle inserting of a character other than allowed.
 Display an error on trying to insert a disallowed character.
 Also discard all previous input in the minibuffer."
   (interactive)
-  (delete-minibuffer-contents)
-  (ding)
-  (discard-input)
-  (minibuffer-message "Wrong answer")
-  (sit-for 2))
+  (when (minibufferp)
+    (delete-minibuffer-contents)
+    (ding)
+    (discard-input)
+    (minibuffer-message "Wrong answer")
+    (sit-for 2)))
 
 (defvar empty-history)
 
@@ -2802,6 +2804,8 @@ There is no need to explicitly add `help-char' to CHARS;
                                  map read-char-from-minibuffer-map-hash)
                         map))
                 read-char-from-minibuffer-map))
+         ;; Protect this-command when called from pre-command-hook (bug#45029)
+         (this-command this-command)
          (result
           (read-from-minibuffer prompt nil map nil
                                 (or history 'empty-history)))
@@ -2856,28 +2860,31 @@ There is no need to explicitly add `help-char' to CHARS;
   "Insert the answer \"y\" and exit the minibuffer of `y-or-n-p'.
 Discard all previous input before inserting and exiting the minibuffer."
   (interactive)
-  (delete-minibuffer-contents)
-  (insert "y")
-  (exit-minibuffer))
+  (when (minibufferp)
+    (delete-minibuffer-contents)
+    (insert "y")
+    (exit-minibuffer)))
 
 (defun y-or-n-p-insert-n ()
   "Insert the answer \"n\" and exit the minibuffer of `y-or-n-p'.
 Discard all previous input before inserting and exiting the minibuffer."
   (interactive)
-  (delete-minibuffer-contents)
-  (insert "n")
-  (exit-minibuffer))
+  (when (minibufferp)
+    (delete-minibuffer-contents)
+    (insert "n")
+    (exit-minibuffer)))
 
 (defun y-or-n-p-insert-other ()
   "Handle inserting of other answers in the minibuffer of `y-or-n-p'.
 Display an error on trying to insert a disallowed character.
 Also discard all previous input in the minibuffer."
   (interactive)
-  (delete-minibuffer-contents)
-  (ding)
-  (discard-input)
-  (minibuffer-message "Please answer y or n")
-  (sit-for 2))
+  (when (minibufferp)
+    (delete-minibuffer-contents)
+    (ding)
+    (discard-input)
+    (minibuffer-message "Please answer y or n")
+    (sit-for 2)))
 
 (defvar empty-history)
 
@@ -2955,6 +2962,8 @@ is nil and `use-dialog-box' is non-nil."
                              (let ((help-form msg)) ; lexically bound msg
                                (help-form-show)))))
                        map))
+             ;; Protect this-command when called from pre-command-hook 
(bug#45029)
+             (this-command this-command)
              (str (read-from-minibuffer
                    prompt nil keymap nil
                    (or y-or-n-p-history-variable 'empty-history))))
@@ -3955,7 +3964,7 @@ is allowed once again.  (Immediately, if `inhibit-quit' 
is nil.)"
 ;; Don't throw `throw-on-input' on those events by default.
 (setq while-no-input-ignore-events
       '(focus-in focus-out help-echo iconify-frame
-        make-frame-visible selection-request buffer-switch))
+        make-frame-visible selection-request))
 
 (defmacro while-no-input (&rest body)
   "Execute BODY only as long as there's no pending input.
@@ -5258,6 +5267,8 @@ use `called-interactively-p'.
 
 To test whether a function can be called interactively, use
 `commandp'."
+  ;; Kept around for now.  See discussion at:
+  ;; https://lists.gnu.org/r/emacs-devel/2020-08/msg00564.html
   (declare (obsolete called-interactively-p "23.2"))
   (called-interactively-p 'interactive))
 
@@ -5898,4 +5909,22 @@ returned list are in the same order as in TREE.
 (defconst regexp-unmatchable "\\`a\\`"
   "Standard regexp guaranteed not to match any string at all.")
 
+(defun run-hook-query-error-with-timeout (hook)
+  "Run HOOK, catching errors, and querying the user about whether to continue.
+If a function in HOOK signals an error, the user will be prompted
+whether to continue or not.  If the user doesn't respond,
+evaluation will continue if the user doesn't respond within five
+seconds."
+  (run-hook-wrapped
+   hook
+   (lambda (fun)
+     (condition-case err
+         (funcall fun)
+       (error
+        (unless (y-or-n-p-with-timeout (format "Error %s; continue?" err)
+                                       5 t)
+          (error err))))
+     ;; Continue running.
+     nil)))
+
 ;;; subr.el ends here
diff --git a/lisp/svg.el b/lisp/svg.el
index eeb945f..1ca5965 100644
--- a/lisp/svg.el
+++ b/lisp/svg.el
@@ -184,6 +184,19 @@ otherwise.  IMAGE-TYPE should be a MIME image type, like
     `((xlink:href . ,(svg--image-data image image-type datap))
       ,@(svg--arguments svg args)))))
 
+(defun svg-embed-base-uri-image (svg relative-filename &rest args)
+  "Insert image placed at RELATIVE-FILENAME into the SVG structure.
+RELATIVE-FILENAME will be searched in `file-name-directory' of the
+image's `:base-uri' property.  If `:base-uri' is not specified for the
+image, then embedding won't work. Embedding large images using this
+function is much faster than `svg-embed'."
+  (svg--append
+   svg
+   (dom-node
+    'image
+    `((xlink:href . ,relative-filename)
+      ,@(svg--arguments svg args)))))
+
 (defun svg-text (svg text &rest args)
   "Add TEXT to SVG."
   (svg--append
diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index 2604955..1327bde 100644
--- a/lisp/tab-bar.el
+++ b/lisp/tab-bar.el
@@ -762,6 +762,8 @@ After the tab is created, the hooks in
          (from-tab (tab-bar--tab)))
 
     (when tab-bar-new-tab-choice
+      (when (minibuffer-selected-window)
+        (select-window (minibuffer-selected-window)))
       (delete-other-windows)
       ;; Create a new window to get rid of old window parameters
       ;; (e.g. prev/next buffers) of old window.
diff --git a/lisp/tar-mode.el b/lisp/tar-mode.el
index d460c8a..608d997 100644
--- a/lisp/tar-mode.el
+++ b/lisp/tar-mode.el
@@ -588,7 +588,7 @@ For instance, if mode is #o700, then it produces 
`rwx------'."
         (setq pos (tar-header-data-end descriptor))
         (progress-reporter-update progress-reporter pos)))
 
-    (set (make-local-variable 'tar-parse-info) (nreverse result))
+    (setq-local tar-parse-info (nreverse result))
     ;; A tar file should end with a block or two of nulls,
     ;; but let's not get a fatal error if it doesn't.
     (if (null descriptor)
@@ -718,21 +718,21 @@ See also: variables `tar-update-datestamp' and 
`tar-anal-blocksize'.
        (file-writable-p buffer-file-name)
        (setq buffer-read-only nil))    ; undo what `special-mode' did
   (make-local-variable 'tar-parse-info)
-  (set (make-local-variable 'require-final-newline) nil) ; binary data, dude...
-  (set (make-local-variable 'local-enable-local-variables) nil)
-  (set (make-local-variable 'next-line-add-newlines) nil)
-  (set (make-local-variable 'tar-file-name-coding-system)
-       (or file-name-coding-system
-          default-file-name-coding-system
-          locale-coding-system))
+  (setq-local require-final-newline nil) ; binary data, dude...
+  (setq-local local-enable-local-variables nil)
+  (setq-local next-line-add-newlines nil)
+  (setq-local tar-file-name-coding-system
+              (or file-name-coding-system
+                 default-file-name-coding-system
+                 locale-coding-system))
   ;; Prevent loss of data when saving the file.
-  (set (make-local-variable 'file-precious-flag) t)
+  (setq-local file-precious-flag t)
   (buffer-disable-undo)
   (widen)
   ;; Now move the Tar data into an auxiliary buffer, so we can use the main
   ;; buffer for the summary.
   (cl-assert (not (tar-data-swapped-p)))
-  (set (make-local-variable 'revert-buffer-function) #'tar-mode-revert)
+  (setq-local revert-buffer-function #'tar-mode-revert)
   ;; We started using write-contents-functions, but this hook is not
   ;; used during auto-save, so we now use
   ;; write-region-annotate-functions which hooks at a lower-level.
@@ -741,10 +741,10 @@ See also: variables `tar-update-datestamp' and 
`tar-anal-blocksize'.
   (add-hook 'change-major-mode-hook #'tar-change-major-mode-hook nil t)
   ;; Tar data is made of bytes, not chars.
   (set-buffer-multibyte nil)            ;Hopefully a no-op.
-  (set (make-local-variable 'tar-data-buffer)
-       (generate-new-buffer (format " *tar-data %s*"
-                                    (file-name-nondirectory
-                                     (or buffer-file-name (buffer-name))))))
+  (setq-local tar-data-buffer (generate-new-buffer
+                               (format " *tar-data %s*"
+                                       (file-name-nondirectory
+                                        (or buffer-file-name (buffer-name))))))
   (condition-case err
       (progn
         (tar-swap-data)
@@ -1004,8 +1004,8 @@ return nil.  Otherwise point is returned."
                 default-directory))
         (set-buffer-modified-p nil)
         (normal-mode)                   ; pick a mode.
-        (set (make-local-variable 'tar-superior-buffer) tar-buffer)
-        (set (make-local-variable 'tar-superior-descriptor) descriptor)
+        (setq-local tar-superior-buffer tar-buffer)
+        (setq-local tar-superior-descriptor descriptor)
         (setq buffer-read-only read-only-p)
         (tar-subfile-mode 1)))
     (cond
diff --git a/lisp/term.el b/lisp/term.el
index 34dc287..2e69af0 100644
--- a/lisp/term.el
+++ b/lisp/term.el
@@ -264,7 +264,7 @@
 ;; M-p     term-previous-input           Cycle backwards in input history
 ;; M-n     term-next-input               Cycle forwards
 ;; M-r     term-previous-matching-input  Previous input matching a regexp
-;; M-s     comint-next-matching-input    Next input that matches
+;; M-s     term-next-matching-input      Next input that matches
 ;; return  term-send-input
 ;; C-c C-a term-bol                      Beginning of line; skip prompt.
 ;; C-d     term-delchar-or-maybe-eof     Delete char unless at end of buff.
@@ -1005,12 +1005,12 @@ Entry to this mode runs the hooks on `term-mode-hook'."
   ;; we do not want indent to sneak in any tabs
   (setq indent-tabs-mode nil)
   (setq buffer-display-table term-display-table)
-  (set (make-local-variable 'term-home-marker) (copy-marker 0))
-  (set (make-local-variable 'term-height) (floor (window-screen-lines)))
-  (set (make-local-variable 'term-width) (window-max-chars-per-line))
-  (set (make-local-variable 'term-last-input-start) (make-marker))
-  (set (make-local-variable 'term-last-input-end) (make-marker))
-  (set (make-local-variable 'term-last-input-match) "")
+  (setq-local term-home-marker (copy-marker 0))
+  (setq-local term-height (floor (window-screen-lines)))
+  (setq-local term-width (window-max-chars-per-line))
+  (setq-local term-last-input-start (make-marker))
+  (setq-local term-last-input-end (make-marker))
+  (setq-local term-last-input-match "")
 
   ;; These local variables are set to their local values:
   (make-local-variable 'term-saved-home-marker)
@@ -1028,9 +1028,9 @@ Entry to this mode runs the hooks on `term-mode-hook'."
   ;; a properly configured ange-ftp, I've decided to be conservative
   ;; and put them in. -mm
 
-  (set (make-local-variable 'term-ansi-at-host) (system-name))
-  (set (make-local-variable 'term-ansi-at-dir) default-directory)
-  (set (make-local-variable 'term-ansi-at-message) nil)
+  (setq-local term-ansi-at-host (system-name))
+  (setq-local term-ansi-at-dir default-directory)
+  (setq-local term-ansi-at-message nil)
 
   ;; For user tracking purposes -mm
   (make-local-variable 'ange-ftp-default-user)
@@ -1073,15 +1073,15 @@ Entry to this mode runs the hooks on `term-mode-hook'."
   (make-local-variable 'term-scroll-to-bottom-on-output)
   (make-local-variable 'term-scroll-show-maximum-output)
   (make-local-variable 'term-ptyp)
-  (set (make-local-variable 'term-vertical-motion) 'vertical-motion)
-  (set (make-local-variable 'term-pending-delete-marker) (make-marker))
+  (setq-local term-vertical-motion 'vertical-motion)
+  (setq-local term-pending-delete-marker (make-marker))
   (make-local-variable 'term-current-face)
   (term-ansi-reset)
-  (set (make-local-variable 'term-pending-frame) nil)
+  (setq-local term-pending-frame nil)
   ;; Cua-mode's keybindings interfere with the term keybindings, disable it.
-  (set (make-local-variable 'cua-mode) nil)
+  (setq-local cua-mode nil)
 
-  (set (make-local-variable 'font-lock-defaults) '(nil t))
+  (setq-local font-lock-defaults '(nil t))
 
   (add-function :filter-return
                 (local 'filter-buffer-substring-function)
@@ -1423,8 +1423,7 @@ buffer.  The hook `term-exec-hook' is run after each 
exec."
       (when proc (delete-process proc)))
     ;; Crank up a new process
     (let ((proc (term-exec-1 name buffer command switches)))
-      (make-local-variable 'term-ptyp)
-      (setq term-ptyp process-connection-type) ; t if pty, nil if pipe.
+      (setq-local term-ptyp process-connection-type) ; t if pty, nil if pipe.
       ;; Jump to the end, and set the process mark.
       (goto-char (point-max))
       (set-marker (process-mark proc) (point))
@@ -3067,8 +3066,7 @@ See `term-prompt-regexp'."
                         (aset term-terminal-undecoded-bytes 0 ?\r))
                       (goto-char (point-max)))
                     ;; FIXME: Use (add-function :override (process-filter proc)
-                    (make-local-variable 'term-pager-old-filter)
-                    (setq term-pager-old-filter (process-filter proc))
+                    (setq-local term-pager-old-filter (process-filter proc))
                     ;; FIXME: Where is `term-pager-filter' set to a function?!
                     (set-process-filter proc term-pager-filter)
                     (setq i str-length))
@@ -3537,8 +3535,7 @@ The top-most line is line 0."
   ;;   (stop-process process))
   (setq term-pager-old-local-map (current-local-map))
   (use-local-map term-pager-break-map)
-  (make-local-variable 'term-old-mode-line-format)
-  (setq term-old-mode-line-format mode-line-format)
+  (setq-local term-old-mode-line-format mode-line-format)
   (setq mode-line-format
        (list "--  **MORE**  "
              mode-line-buffer-identification
diff --git a/lisp/textmodes/bibtex-style.el b/lisp/textmodes/bibtex-style.el
index 952b816..41650eb 100644
--- a/lisp/textmodes/bibtex-style.el
+++ b/lisp/textmodes/bibtex-style.el
@@ -66,12 +66,12 @@
 ;;;###autoload
 (define-derived-mode bibtex-style-mode nil "BibStyle"
   "Major mode for editing BibTeX style files."
-  (set (make-local-variable 'comment-start) "%")
-  (set (make-local-variable 'outline-regexp) "^[a-z]")
-  (set (make-local-variable 'imenu-generic-expression)
-       '((nil "\\<\\(FUNCTION\\|MACRO\\)\\s-+{\\([^}\n]+\\)}" 2)))
-  (set (make-local-variable 'indent-line-function) 'bibtex-style-indent-line)
-  (set (make-local-variable 'parse-sexp-ignore-comments) t)
+  (setq-local comment-start "%")
+  (setq-local outline-regexp "^[a-z]")
+  (setq-local imenu-generic-expression
+              '((nil "\\<\\(FUNCTION\\|MACRO\\)\\s-+{\\([^}\n]+\\)}" 2)))
+  (setq-local indent-line-function 'bibtex-style-indent-line)
+  (setq-local parse-sexp-ignore-comments t)
   (setq font-lock-defaults
        '(bibtex-style-font-lock-keywords nil t
          ((?. . "w")))))
diff --git a/lisp/textmodes/bibtex.el b/lisp/textmodes/bibtex.el
index 0a0a582..a78219e 100644
--- a/lisp/textmodes/bibtex.el
+++ b/lisp/textmodes/bibtex.el
@@ -40,6 +40,8 @@
 
 ;;; Code:
 
+(require 'iso8601)
+
 
 ;; User Options:
 
@@ -2761,12 +2763,16 @@ and `bibtex-autokey-names-stretch'."
 
 (defun bibtex-autokey-get-year ()
   "Return year field contents as a string obeying 
`bibtex-autokey-year-length'."
-  (let ((yearfield (bibtex-autokey-get-field '("year" "date"))))
-    ;; biblatex date field has format yyyy-mm-dd
-    (if (< 4 (length yearfield))
-        (setq yearfield (substring yearfield 0 4)))
-    (substring yearfield (max 0 (- (length yearfield)
-                                   bibtex-autokey-year-length)))))
+  (let* ((str (bibtex-autokey-get-field '("date" "year"))) ; possibly ""
+         (year (or (and (iso8601-valid-p str)
+                        (let ((year (decoded-time-year (iso8601-parse str))))
+                          (and year (number-to-string year))))
+                   ;; BibTeX permits a year field "(about 1984)", where only
+                   ;; the last four nonpunctuation characters must be numerals.
+                   (and (string-match 
"\\([0-9][0-9][0-9][0-9]\\)[^[:alnum:]]*\\'" str)
+                        (match-string 1 str))
+                   (user-error "Year or date field `%s' invalid" str))))
+    (substring year (max 0 (- (length year) bibtex-autokey-year-length)))))
 
 (defun bibtex-autokey-get-title ()
   "Get title field contents up to a terminator.
@@ -2849,12 +2855,12 @@ The name part:
 
 The year part:
  1. Build the year part of the key by truncating the content of the year
-    field to the rightmost `bibtex-autokey-year-length' digits (useful
-    values are 2 and 4).
- 2. If the year field (or any other field required to generate the key)
-    is absent, but the entry has a valid crossref field and
-    `bibtex-autokey-use-crossref' is non-nil, use the field of the
-    crossreferenced entry instead.
+    component of the date or year field to the rightmost
+    `bibtex-autokey-year-length' digits (useful values are 2 and 4).
+ 2. If both the year and date fields are absent, but the entry has a
+    valid crossref field and `bibtex-autokey-use-crossref' is
+    non-nil, use the date or year field of the crossreferenced entry
+    instead.
 
 The title part
  1. Change the content of the title field according to
diff --git a/lisp/textmodes/table.el b/lisp/textmodes/table.el
index 984cc08..e42615e 100644
--- a/lisp/textmodes/table.el
+++ b/lisp/textmodes/table.el
@@ -4073,10 +4073,12 @@ cache buffer into the designated cell in the table 
buffer."
       (set-buffer table-cell-buffer)
       (let ((cache-buffer (get-buffer-create table-cache-buffer-name))
            (org-coord (table--get-coordinate))
+            (fixed table-fixed-width-mode)
            (in-cell (equal (table--cell-to-coord (table--probe-cell))
                            (cons table-cell-info-lu-coordinate 
table-cell-info-rb-coordinate)))
            rectangle)
        (set-buffer cache-buffer)
+        (setq-local table-fixed-width-mode fixed)
        (setq rectangle
              (extract-rectangle
               1
diff --git a/lisp/textmodes/tex-mode.el b/lisp/textmodes/tex-mode.el
index 37ab11a..5923845 100644
--- a/lisp/textmodes/tex-mode.el
+++ b/lisp/textmodes/tex-mode.el
@@ -2331,9 +2331,14 @@ FILE is typically the output DVI or PDF file."
   :version "23.1"
   :group 'tex-run)
 
+(defun tex--quote-spec (fspec)
+  (cl-loop for (char . file) in fspec
+           collect (cons char (shell-quote-argument file))))
+
 (defun tex-format-cmd (format fspec)
   "Like `format-spec' but adds user-specified args to the command.
 Only applies the FSPEC to the args part of FORMAT."
+  (setq fspec (tex--quote-spec fspec))
   (if (not (string-match "\\([^ /\\]+\\) " format))
       (format-spec format fspec)
     (let* ((prefix (substring format 0 (match-beginning 0)))
@@ -2430,8 +2435,8 @@ Only applies the FSPEC to the args part of FORMAT."
            (prog1 (file-name-directory (expand-file-name file))
              (setq file (file-name-nondirectory file))))
          (root (file-name-sans-extension file))
-         (fspec (list (cons ?r (shell-quote-argument root))
-                      (cons ?f (shell-quote-argument file))))
+         (fspec (list (cons ?r root)
+                      (cons ?f file)))
          (default (tex-compile-default fspec)))
      (list default-directory
           (completing-read
diff --git a/lisp/thumbs.el b/lisp/thumbs.el
index 3aa7ff0..93b7c08 100644
--- a/lisp/thumbs.el
+++ b/lisp/thumbs.el
@@ -347,8 +347,7 @@ If MARKED is non-nil, the image is marked."
                   :conversion ,(if marked 'disabled)
                   :margin ,thumbs-margin)))
     (insert-image i)
-    (set (make-local-variable 'thumbs-current-image-size)
-         (image-size i t))))
+    (setq-local thumbs-current-image-size (image-size i t))))
 
 (defun thumbs-insert-thumb (img &optional marked)
   "Insert the thumbnail for IMG at point.
@@ -387,7 +386,7 @@ If MARKED is non-nil, the image is marked."
     (if dir (setq default-directory dir))
     (thumbs-do-thumbs-insertion list)
     (goto-char (point-min))
-    (set (make-local-variable 'thumbs-current-dir) default-directory)))
+    (setq-local thumbs-current-dir default-directory)))
 
 ;;;###autoload
 (defun thumbs-show-from-dir (dir &optional reg same-window)
diff --git a/lisp/timezone.el b/lisp/timezone.el
index 8ba70f1..1b5e422 100644
--- a/lisp/timezone.el
+++ b/lisp/timezone.el
@@ -1,4 +1,4 @@
-;;; timezone.el --- time zone package for GNU Emacs  -- lexical-binding: t -*-
+;;; timezone.el --- time zone package for GNU Emacs  -*- lexical-binding: t -*-
 
 ;; Copyright (C) 1990-1993, 1996, 1999, 2001-2020 Free Software
 ;; Foundation, Inc.
diff --git a/lisp/tool-bar.el b/lisp/tool-bar.el
index 8456216..37f42be 100644
--- a/lisp/tool-bar.el
+++ b/lisp/tool-bar.el
@@ -159,7 +159,8 @@ To define items in any other map, use 
`tool-bar-local-item'."
                       ((< (display-color-cells) 256)
                        ',(list xpm-lo-spec xpm-spec pbm-spec xbm-spec))
                       (t
-                       ',(list xpm-spec pbm-spec xbm-spec))))))
+                       ',(list xpm-spec pbm-spec xbm-spec)))
+                 t)))
 
 ;;;###autoload
 (defun tool-bar-local-item (icon def key map &rest props)
diff --git a/lisp/tree-widget.el b/lisp/tree-widget.el
index 45d3f28..e8a71a3 100644
--- a/lisp/tree-widget.el
+++ b/lisp/tree-widget.el
@@ -260,10 +260,9 @@ Typically it should contain something like this:
      \\='(:ascent center :mask (heuristic t)))"
   (or name (setq name (or tree-widget-theme "default")))
   (unless (string-equal name (tree-widget-theme-name))
-    (set (make-local-variable 'tree-widget--theme)
-         (make-vector 4 nil))
-      (tree-widget-set-parent-theme name)
-      (tree-widget-set-parent-theme "default")))
+    (setq-local tree-widget--theme (make-vector 4 nil))
+    (tree-widget-set-parent-theme name)
+    (tree-widget-set-parent-theme "default")))
 
 (defun tree-widget--locate-sub-directory (name path)
   "Locate all occurrences of the sub-directory NAME in PATH.
diff --git a/lisp/tutorial.el b/lisp/tutorial.el
index d07737e..ca84f86 100644
--- a/lisp/tutorial.el
+++ b/lisp/tutorial.el
@@ -50,6 +50,9 @@
   "Tutorial language.")
 (make-variable-buffer-local 'tutorial--lang)
 
+(defvar tutorial--buffer nil
+  "The selected tutorial buffer.")
+
 (defun tutorial--describe-nonstandard-key (value)
   "Give more information about a changed key binding.
 This is used in `help-with-tutorial'.  The information includes
@@ -655,6 +658,15 @@ with some explanatory links."
         (unless (eq prop-val 'key-sequence)
          (delete-region prop-start prop-end))))))
 
+(defun tutorial--save-on-kill ()
+  "Query the user about saving the tutorial when killing Emacs."
+  (when (buffer-live-p tutorial--buffer)
+    (with-current-buffer tutorial--buffer
+      (if (y-or-n-p "Save your position in the tutorial? ")
+         (tutorial--save-tutorial-to (tutorial--saved-file))
+       (message "Tutorial position not saved"))))
+  t)
+
 (defun tutorial--save-tutorial ()
   "Save the tutorial buffer.
 This saves the part of the tutorial before and after the area
@@ -802,6 +814,7 @@ Run the Viper tutorial? "))
       ;; (Re)build the tutorial buffer if it is not ok
       (unless old-tut-is-ok
         (switch-to-buffer (get-buffer-create tut-buf-name))
+        (setq tutorial--buffer (current-buffer))
         ;; (unless old-tut-buf (text-mode))
         (unless lang (error "Variable lang is nil"))
         (setq tutorial--lang lang)
@@ -814,6 +827,7 @@ Run the Viper tutorial? "))
         ;; a hook to save it when the buffer is killed.
         (setq buffer-auto-save-file-name nil)
         (add-hook 'kill-buffer-hook 'tutorial--save-tutorial nil t)
+        (add-hook 'kill-emacs-query-functions 'tutorial--save-on-kill)
 
         ;; Insert the tutorial. First offer to resume last tutorial
         ;; editing session.
diff --git a/lisp/url/url-cookie.el b/lisp/url/url-cookie.el
index bee3a6b..e185a79 100644
--- a/lisp/url/url-cookie.el
+++ b/lisp/url/url-cookie.el
@@ -162,7 +162,7 @@ i.e. 1970-1-1) are loaded as expiring one year from now 
instead."
               ";; version-control: never\n"
               ";; no-byte-compile: t\n"
               ";; End:\n")
-      (set (make-local-variable 'version-control) 'never)
+      (setq-local version-control 'never)
       (write-file fname))
     (setq url-cookies-changed-since-last-save nil))))
 
diff --git a/lisp/url/url-http.el b/lisp/url/url-http.el
index 75330d3..1271b9b 100644
--- a/lisp/url/url-http.el
+++ b/lisp/url/url-http.el
@@ -741,12 +741,12 @@ should be shown to the user."
                   ;; without changing the API.  Instead url-retrieve should
                   ;; either simply not return the "destination" buffer, or it
                   ;; should take an optional `dest-buf' argument.
-                  (set (make-local-variable 'url-redirect-buffer)
-                       (url-retrieve-internal
-                        redirect-uri url-callback-function
-                        url-callback-arguments
-                        (url-silent url-current-object)
-                        (not (url-use-cookies url-current-object))))
+                   (setq-local url-redirect-buffer
+                               (url-retrieve-internal
+                                redirect-uri url-callback-function
+                                url-callback-arguments
+                                (url-silent url-current-object)
+                                (not (url-use-cookies url-current-object))))
                   (url-mark-buffer-as-dead buffer))
               ;; We hit url-max-redirections, so issue an error and
               ;; stop redirecting.
diff --git a/lisp/url/url-util.el b/lisp/url/url-util.el
index 0a7e7e2..bd9543b 100644
--- a/lisp/url/url-util.el
+++ b/lisp/url/url-util.el
@@ -574,8 +574,8 @@ Has a preference for looking backward when not directly on 
a symbol."
   (save-excursion
     (goto-char (point-min))
     (unless url-current-mime-headers
-      (set (make-local-variable 'url-current-mime-headers)
-          (mail-header-extract)))))
+      (setq-local url-current-mime-headers
+                  (mail-header-extract)))))
 
 (defun url-make-private-file (file)
   "Make FILE only readable and writable by the current user.
diff --git a/lisp/vc/ediff-ptch.el b/lisp/vc/ediff-ptch.el
index 08640fc..580d488 100644
--- a/lisp/vc/ediff-ptch.el
+++ b/lisp/vc/ediff-ptch.el
@@ -465,6 +465,9 @@ are two possible targets for this %spatch.  However, these 
files do not exist."
                                     file1 file2 (if multi-patch-p "multi-" 
""))))
                    (princ "
 \nPlease enter an alternative patch target ...\n"))
+                  (when (and (string= file1 file2)
+                             (y-or-n-p (format "Create %s?" file1)))
+                    (write-region (point-min) (point-min) file1))
                  (let ((directory t)
                        target)
                    (while directory
diff --git a/lisp/vc/log-edit.el b/lisp/vc/log-edit.el
index feafe5f..5f978da 100644
--- a/lisp/vc/log-edit.el
+++ b/lisp/vc/log-edit.el
@@ -387,7 +387,8 @@ The first subexpression is the actual text of the field.")
          nil lax))
      ("^\n"
       (progn (goto-char (match-end 0)) (1+ (match-end 0))) nil
-      (0 '(:height 0.1 :inverse-video t :extend t))))
+      (0 '(face (:height 0.1 :inverse-video t :extend t)
+           display-line-numbers-disable t rear-nonsticky t))))
     (log-edit--match-first-line (0 'log-edit-summary))))
 
 (defvar log-edit-font-lock-gnu-style nil
@@ -490,6 +491,9 @@ commands (under C-x v for VC, for example).
 
 \\{log-edit-mode-map}"
   (setq-local font-lock-defaults '(log-edit-font-lock-keywords t))
+  (make-local-variable 'font-lock-extra-managed-props)
+  (cl-pushnew 'rear-nonsticky font-lock-extra-managed-props)
+  (cl-pushnew 'display-line-numbers-disable font-lock-extra-managed-props)
   (setq-local jit-lock-contextually t)  ;For the "first line is summary".
   (setq-local fill-paragraph-function #'log-edit-fill-entry)
   (make-local-variable 'log-edit-comment-ring-index)
@@ -983,16 +987,17 @@ where LOGBUFFER is the name of the ChangeLog buffer, and 
each
                (visiting-buffer (find-buffer-visiting file)))
            ;; If there is a buffer visiting FILE, and it has a local
            ;; value for `change-log-default-name', use that.
-           (if (and visiting-buffer
+           (or (and visiting-buffer
                     (local-variable-p 'change-log-default-name
-                                      visiting-buffer))
-               (with-current-buffer visiting-buffer
-                 change-log-default-name)
-             ;; `find-change-log' uses `change-log-default-name' if set
-             ;; and sets it before exiting, so we need to work around
-             ;; that memoizing which is undesired here.
-             (setq change-log-default-name nil)
-             (find-change-log)))))
+                                      visiting-buffer)
+                    (with-current-buffer visiting-buffer
+                      change-log-default-name))
+               ;; `find-change-log' uses `change-log-default-name' if set
+               ;; and sets it before exiting, so we need to work around
+               ;; that memoizing which is undesired here.
+               (progn
+                 (setq change-log-default-name nil)
+                 (find-change-log))))))
     (when (or (find-buffer-visiting changelog-file-name)
               (file-exists-p changelog-file-name)
               add-log-dont-create-changelog-file)
diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el
index 0da4509..84c964e 100644
--- a/lisp/vc/vc-git.el
+++ b/lisp/vc/vc-git.el
@@ -72,7 +72,7 @@
 ;;                                          by git, so it's probably
 ;;                                          not a good idea.
 ;; - merge-news (file)                      see `merge-file'
-;; - mark-resolved (file)                          OK
+;; - mark-resolved (files)                         OK
 ;; - steal-lock (file &optional revision)          NOT NEEDED
 ;; HISTORY FUNCTIONS
 ;; * print-log (files buffer &optional shortlog start-revision limit)   OK
diff --git a/lisp/vc/vc-hg.el b/lisp/vc/vc-hg.el
index e7f67e9..c8a80d7 100644
--- a/lisp/vc/vc-hg.el
+++ b/lisp/vc/vc-hg.el
@@ -276,13 +276,12 @@ If `ask', you will be prompted for a branch type."
         ((eq state ?C) 'up-to-date) ;; Older mercurial versions use this.
         (t 'up-to-date))))))
 
-(defun vc-hg-working-revision (file)
+(defun vc-hg-working-revision (_file)
   "Hg-specific version of `vc-working-revision'."
-  (or (ignore-errors
-        (with-output-to-string
-          (vc-hg-command standard-output 0 file
-                         "parent" "--template" "{rev}")))
-      "0"))
+  (ignore-errors
+    (with-output-to-string
+      (vc-hg-command standard-output 0 nil
+                     "log" "-r" "." "--template" "{rev}"))))
 
 (defcustom vc-hg-symbolic-revision-styles
   '(builtin-active-bookmark
diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el
index f268f91..7d9af00 100644
--- a/lisp/vc/vc.el
+++ b/lisp/vc/vc.el
@@ -201,7 +201,7 @@
 ;;
 ;; STATE-CHANGING FUNCTIONS
 ;;
-;; * create-repo (backend)
+;; * create-repo ()
 ;;
 ;;   Create an empty repository in the current directory and initialize
 ;;   it so VC mode can add files to it.  For file-oriented systems, this
@@ -275,7 +275,7 @@
 ;;   If FILE is in the `added' state it should be returned to the
 ;;   `unregistered' state.
 ;;
-;; - merge-file (file rev1 rev2)
+;; - merge-file (file &optional rev1 rev2)
 ;;
 ;;   Merge the changes between REV1 and REV2 into the current working
 ;;   file (for non-distributed VCS).  It is expected that with an
@@ -333,19 +333,19 @@
 ;;   the case).  Not all backends support this.  At present, this is
 ;;   only ever used with LIMIT = 1 (by vc-annotate-show-log-revision-at-line).
 ;;
-;; * log-outgoing (backend remote-location)
+;; * log-outgoing (buffer remote-location)
 ;;
 ;;   Insert in BUFFER the revision log for the changes that will be
 ;;   sent when performing a push operation to REMOTE-LOCATION.
 ;;
-;; * log-incoming (backend remote-location)
+;; * log-incoming (buffer remote-location)
 ;;
 ;;   Insert in BUFFER the revision log for the changes that will be
 ;;   received when performing a pull operation from REMOTE-LOCATION.
 ;;
-;; - log-search (pattern)
+;; - log-search (buffer pattern)
 ;;
-;;   Search for PATTERN in the revision log.
+;;   Search for PATTERN in the revision log and output results into BUFFER.
 ;;
 ;; - log-view-mode ()
 ;;
@@ -478,7 +478,7 @@
 ;;
 ;;   Return the root of the VC controlled hierarchy for file.
 ;;
-;; - ignore (file &optional directory)
+;; - ignore (file &optional directory remove)
 ;;
 ;;   Ignore FILE under DIRECTORY (default is 'default-directory').
 ;;   FILE is a file wildcard relative to DIRECTORY.
@@ -487,7 +487,7 @@
 ;;   When called from Lisp code, if DIRECTORY is non-nil, the
 ;;   repository to use will be deduced by DIRECTORY.
 ;;
-;; - ignore-completion-table
+;; - ignore-completion-table (directory)
 ;;
 ;;   Return the completion table for files ignored by the current
 ;;   version control system, e.g., the entries in `.gitignore' and
@@ -2325,7 +2325,8 @@ checked out in that new branch."
          ;; to ask for a directory, branches are created at repository level.
          default-directory
        (read-directory-name "Directory: " default-directory default-directory 
t))
-      (read-string (if current-prefix-arg "New branch name: " "New tag name: 
"))
+      (read-string (if current-prefix-arg "New branch name: " "New tag name: ")
+                   nil 'vc-revision-history)
       current-prefix-arg)))
   (message "Making %s... " (if branchp "branch" "tag"))
   (when (file-directory-p dir) (setq dir (file-name-as-directory dir)))
diff --git a/lisp/wdired.el b/lisp/wdired.el
index ebe1961..b7dd4ee 100644
--- a/lisp/wdired.el
+++ b/lisp/wdired.el
@@ -242,12 +242,12 @@ See `wdired-mode'."
   (interactive)
   (unless (derived-mode-p 'dired-mode)
     (error "Not a Dired buffer"))
-  (set (make-local-variable 'wdired-old-content)
-       (buffer-substring (point-min) (point-max)))
-  (set (make-local-variable 'wdired-old-marks)
-       (dired-remember-marks (point-min) (point-max)))
-  (set (make-local-variable 'wdired-old-point) (point))
-  (set (make-local-variable 'query-replace-skip-read-only) t)
+  (setq-local wdired-old-content
+              (buffer-substring (point-min) (point-max)))
+  (setq-local wdired-old-marks
+              (dired-remember-marks (point-min) (point-max)))
+  (setq-local wdired-old-point (point))
+  (setq-local query-replace-skip-read-only t)
   (add-function :after-while (local 'isearch-filter-predicate)
                 #'wdired-isearch-filter-read-only)
   (use-local-map wdired-mode-map)
@@ -390,7 +390,7 @@ non-nil means return old filename."
   (dired-advertise)
   (remove-hook 'kill-buffer-hook 'wdired-check-kill-buffer t)
   (remove-hook 'after-change-functions 'wdired--restore-properties t)
-  (set (make-local-variable 'revert-buffer-function) 'dired-revert))
+  (setq-local revert-buffer-function 'dired-revert))
 
 
 (defun wdired-abort-changes ()
@@ -834,7 +834,7 @@ Like original function but it skips read-only words."
 ;; original name and permissions as a property
 (defun wdired-preprocess-perms ()
   (let ((inhibit-read-only t))
-    (set (make-local-variable 'wdired-col-perm) nil)
+    (setq-local wdired-col-perm nil)
     (save-excursion
       (goto-char (point-min))
       (while (not (eobp))
diff --git a/lisp/whitespace.el b/lisp/whitespace.el
index 02ee7bc..814f3e5 100644
--- a/lisp/whitespace.el
+++ b/lisp/whitespace.el
@@ -1986,13 +1986,13 @@ resultant list will be returned."
   ;; prepare local hooks
   (add-hook 'write-file-functions 'whitespace-write-file-hook nil t)
   ;; create whitespace local buffer environment
-  (set (make-local-variable 'whitespace-font-lock-keywords) nil)
-  (set (make-local-variable 'whitespace-display-table) nil)
-  (set (make-local-variable 'whitespace-display-table-was-local) nil)
-  (set (make-local-variable 'whitespace-active-style)
-       (if (listp whitespace-style)
-          whitespace-style
-        (list whitespace-style)))
+  (setq-local whitespace-font-lock-keywords nil)
+  (setq-local whitespace-display-table nil)
+  (setq-local whitespace-display-table-was-local nil)
+  (setq-local whitespace-active-style
+              (if (listp whitespace-style)
+                 whitespace-style
+               (list whitespace-style)))
   ;; turn on whitespace
   (when whitespace-active-style
     (whitespace-color-on)
@@ -2034,19 +2034,14 @@ resultant list will be returned."
   "Turn on color visualization."
   (when (whitespace-style-face-p)
     ;; save current point and refontify when necessary
-    (set (make-local-variable 'whitespace-point)
-         (point))
+    (setq-local whitespace-point (point))
     (setq whitespace-point--used
           (let ((ol (make-overlay (point) (point) nil nil t)))
             (delete-overlay ol) ol))
-    (set (make-local-variable 'whitespace-font-lock-refontify)
-        0)
-    (set (make-local-variable 'whitespace-bob-marker)
-        (point-min-marker))
-    (set (make-local-variable 'whitespace-eob-marker)
-        (point-max-marker))
-    (set (make-local-variable 'whitespace-buffer-changed)
-        nil)
+    (setq-local whitespace-font-lock-refontify 0)
+    (setq-local whitespace-bob-marker (point-min-marker))
+    (setq-local whitespace-eob-marker (point-max-marker))
+    (setq-local whitespace-buffer-changed nil)
     (add-hook 'post-command-hook #'whitespace-post-command-hook nil t)
     (add-hook 'before-change-functions #'whitespace-buffer-changed nil t)
     ;; Add whitespace-mode color into font lock.
diff --git a/lisp/window.el b/lisp/window.el
index daa5c67..67c3992 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -8390,9 +8390,9 @@ from the list of completions and default values."
           ;; here manually.
           (if (and (boundp 'icomplete-with-completion-tables)
                    (listp icomplete-with-completion-tables))
-              (set (make-local-variable 'icomplete-with-completion-tables)
-                   (cons rbts-completion-table
-                         icomplete-with-completion-tables))))
+              (setq-local icomplete-with-completion-tables
+                          (cons rbts-completion-table
+                                icomplete-with-completion-tables))))
       (read-buffer prompt (other-buffer (current-buffer))
                    (confirm-nonexistent-file-or-buffer)))))
 
diff --git a/lisp/xwidget.el b/lisp/xwidget.el
index caf57ae..9d502d7 100644
--- a/lisp/xwidget.el
+++ b/lisp/xwidget.el
@@ -451,7 +451,7 @@ function findactiveelement(doc){
 XW is the xwidget identifier, TEXT is retrieved from the webkit."
   (switch-to-buffer
    (generate-new-buffer "textarea"))
-  (set (make-local-variable 'xwidget-xwbl) xw)
+  (setq-local xwidget-xwbl xw)
   (insert text))
 
 (defun xwidget-webkit-end-edit-textarea ()
diff --git a/lwlib/lwlib-utils.c b/lwlib/lwlib-utils.c
index f15cb60..2b3aa55 100644
--- a/lwlib/lwlib-utils.c
+++ b/lwlib/lwlib-utils.c
@@ -148,6 +148,7 @@ XftFont *
 crxft_font_open_name (Display *dpy, int screen, const char *name)
 {
   XftFont *pub = NULL;
+  FcPattern *match = NULL;
   FcPattern *pattern = FcNameParse ((FcChar8 *) name);
   if (pattern)
     {
@@ -162,12 +163,18 @@ crxft_font_open_name (Display *dpy, int screen, const 
char *name)
          FcPatternAddDouble (pattern, FC_DPI, dpi);
        }
       FcDefaultSubstitute (pattern);
+      FcResult result;
+      match = FcFontMatch (NULL, pattern, &result);
+      FcPatternDestroy (pattern);
+    }
+  if (match)
+    {
       cairo_font_face_t *font_face
-       = cairo_ft_font_face_create_for_pattern (pattern);
+       = cairo_ft_font_face_create_for_pattern (match);
       if (font_face)
        {
          double pixel_size;
-         if ((FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &pixel_size)
+         if ((FcPatternGetDouble (match, FC_PIXEL_SIZE, 0, &pixel_size)
               != FcResultMatch)
              || pixel_size < 1)
            pixel_size = 10;
@@ -177,7 +184,7 @@ crxft_font_open_name (Display *dpy, int screen, const char 
*name)
          cairo_matrix_init_scale (&font_matrix, pixel_size, pixel_size);
          cairo_matrix_init_identity (&ctm);
          cairo_font_options_t *options = cairo_font_options_create ();
-         cairo_ft_font_options_substitute (options, pattern);
+         cairo_ft_font_options_substitute (options, match);
          pub->scaled_font = cairo_scaled_font_create (font_face, &font_matrix,
                                                       &ctm, options);
          cairo_font_face_destroy (font_face);
@@ -190,7 +197,7 @@ crxft_font_open_name (Display *dpy, int screen, const char 
*name)
          pub->height = lround (extents.height);
          pub->max_advance_width = lround (extents.max_x_advance);
        }
-      FcPatternDestroy (pattern);
+      FcPatternDestroy (match);
     }
   if (pub && pub->height <= 0)
     {
diff --git a/src/charset.c b/src/charset.c
index 520dd3a..f6b5173 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -800,7 +800,9 @@ RANGE is a cons (FROM .  TO), where FROM and TO indicate a 
range of
 characters contained in CHARSET.
 
 The optional 4th and 5th arguments FROM-CODE and TO-CODE specify the
-range of code points (in CHARSET) of target characters.  */)
+range of code points (in CHARSET) of target characters.  Note that
+these are not character codes, but code points in CHARSET; for the
+difference see `decode-char' and `list-charset-chars'.  */)
   (Lisp_Object function, Lisp_Object charset, Lisp_Object arg, Lisp_Object 
from_code, Lisp_Object to_code)
 {
   struct charset *cs;
diff --git a/src/chartab.c b/src/chartab.c
index cb2ced5..331e859 100644
--- a/src/chartab.c
+++ b/src/chartab.c
@@ -1000,10 +1000,10 @@ map_sub_char_table_for_charset (void (*c_function) 
(Lisp_Object, Lisp_Object),
    "mapping table" or a "deunifier table" of a certain charset.
 
    If CHARSET is not NULL (this is the case that `map-charset-chars'
-   is called with non-nil FROM-CODE and TO-CODE), it is a charset who
-   owns TABLE, and the function is called only on a character in the
+   is called with non-nil FROM-CODE and TO-CODE), it is a charset that
+   owns TABLE, and the function is called only for characters in the
    range FROM and TO.  FROM and TO are not character codes, but code
-   points of a character in CHARSET.
+   points of characters in CHARSET (see 'decode-char').
 
    This function is called in these two cases:
 
diff --git a/src/data.c b/src/data.c
index 384c259..76bacf7 100644
--- a/src/data.c
+++ b/src/data.c
@@ -1639,8 +1639,9 @@ default_value (Lisp_Object symbol)
 
 DEFUN ("default-boundp", Fdefault_boundp, Sdefault_boundp, 1, 1, 0,
        doc: /* Return t if SYMBOL has a non-void default value.
-This is the value that is seen in buffers that do not have their own values
-for this variable.  */)
+A variable may have a buffer-local or a `let'-bound local value.  This
+function says whether the variable has a non-void value outside of the
+current context.  Also see `default-value'.  */)
   (Lisp_Object symbol)
 {
   register Lisp_Object value;
diff --git a/src/emacs-module.c b/src/emacs-module.c
index 0f3ef59..b7cd835 100644
--- a/src/emacs-module.c
+++ b/src/emacs-module.c
@@ -784,7 +784,8 @@ 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 = module_decode_utf_8 (str, len);
+  Lisp_Object lstr
+    = len == 0 ? empty_multibyte_string : module_decode_utf_8 (str, len);
   return lisp_to_value (env, lstr);
 }
 
@@ -794,9 +795,8 @@ module_make_unibyte_string (emacs_env *env, const char 
*str, ptrdiff_t length)
   MODULE_FUNCTION_BEGIN (NULL);
   if (! (0 <= length && length <= STRING_BYTES_BOUND))
     overflow_error ();
-  Lisp_Object lstr = make_uninit_string (length);
-  memcpy (SDATA (lstr), str, length);
-  SDATA (lstr)[length] = 0;
+  Lisp_Object lstr
+    = length == 0 ? empty_unibyte_string : make_unibyte_string (str, length);
   return lisp_to_value (env, lstr);
 }
 
diff --git a/src/emacs.c b/src/emacs.c
index d0e65ce..00d3fc2 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -2380,10 +2380,13 @@ all of which are called before Emacs is actually 
killed.  */
   /* Fsignal calls emacs_abort () if it sees that waiting_for_input is
      set.  */
   waiting_for_input = 0;
-  if (noninteractive)
-    safe_run_hooks (Qkill_emacs_hook);
-  else
-    run_hook (Qkill_emacs_hook);
+  if (!NILP (find_symbol_value (Qkill_emacs_hook)))
+    {
+      if (noninteractive)
+       safe_run_hooks (Qkill_emacs_hook);
+      else
+       call1 (Qrun_hook_query_error_with_timeout, Qkill_emacs_hook);
+    }
 
 #ifdef HAVE_X_WINDOWS
   /* Transfer any clipboards we own to the clipboard manager.  */
@@ -2905,6 +2908,8 @@ syms_of_emacs (void)
   DEFSYM (Qrisky_local_variable, "risky-local-variable");
   DEFSYM (Qkill_emacs, "kill-emacs");
   DEFSYM (Qkill_emacs_hook, "kill-emacs-hook");
+  DEFSYM (Qrun_hook_query_error_with_timeout,
+         "run-hook-query-error-with-timeout");
 
 #ifdef HAVE_UNEXEC
   defsubr (&Sdump_emacs);
diff --git a/src/eval.c b/src/eval.c
index d9a424b..e2d70aa 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1709,6 +1709,7 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object 
data, bool keyboard_quit)
        break;
     }
 
+  bool debugger_called = false;
   if (/* Don't run the debugger for a memory-full error.
         (There is no room in memory to do that!)  */
       !NILP (error_symbol)
@@ -1722,7 +1723,7 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object 
data, bool keyboard_quit)
             if requested".  */
          || EQ (h->tag_or_ch, Qerror)))
     {
-      bool debugger_called
+      debugger_called
        = maybe_call_debugger (conditions, error_symbol, data);
       /* We can't return values to code which signaled an error, but we
         can continue code which has signaled a quit.  */
@@ -1730,6 +1731,19 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object 
data, bool keyboard_quit)
        return Qnil;
     }
 
+  /* If we're in batch mode, print a backtrace unconditionally to help with
+     debugging.  Make sure to use `debug' unconditionally to not interfere with
+     ERT or other packages that install custom debuggers.  */
+  if (!debugger_called && !NILP (error_symbol)
+      && (NILP (clause) || EQ (h->tag_or_ch, Qerror)) && noninteractive
+      && backtrace_on_error_noninteractive)
+    {
+      ptrdiff_t count = SPECPDL_INDEX ();
+      specbind (Vdebugger, Qdebug);
+      call_debugger (list2 (Qerror, Fcons (error_symbol, data)));
+      unbind_to (count, Qnil);
+    }
+
   if (!NILP (clause))
     {
       Lisp_Object unwind_data
@@ -4251,6 +4265,14 @@ Note that `debug-on-error', `debug-on-quit' and friends
 still determine whether to handle the particular condition.  */);
   Vdebug_on_signal = Qnil;
 
+  DEFVAR_BOOL ("backtrace-on-error-noninteractive",
+               backtrace_on_error_noninteractive,
+               doc: /* Non-nil means print backtrace on error in batch mode.
+If this is nil, errors in batch mode will just print the error
+message upon encountering an unhandled error, without showing
+the Lisp backtrace.  */);
+  backtrace_on_error_noninteractive = true;
+
   /* The value of num_nonmacro_input_events as of the last time we
    started to enter the debugger.  If we decide to enter the debugger
    again when this is still equal to num_nonmacro_input_events, then we
diff --git a/src/fileio.c b/src/fileio.c
index 283813f..702c143 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -3757,9 +3757,10 @@ characters in the buffer.  If VISIT is non-nil, BEG and 
END must be nil.
 If optional fifth argument REPLACE is non-nil, replace the current
 buffer contents (in the accessible portion) with the file contents.
 This is better than simply deleting and inserting the whole thing
-because (1) it preserves some marker positions and (2) it puts less data
-in the undo list.  When REPLACE is non-nil, the second return value is
-the number of characters that replace previous buffer contents.
+because (1) it preserves some marker positions (in unchanged portions
+at the start and end of the buffer) and (2) it puts less data in the
+undo list.  When REPLACE is non-nil, the second return value is the
+number of characters that replace previous buffer contents.
 
 This function does code conversion according to the value of
 `coding-system-for-read' or `file-coding-system-alist', and sets the
diff --git a/src/fns.c b/src/fns.c
index e4c9acc..646c3ed 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -4525,16 +4525,34 @@ sweep_weak_table (struct Lisp_Hash_Table *h, bool 
remove_entries_p)
 EMACS_UINT
 hash_string (char const *ptr, ptrdiff_t len)
 {
-  char const *p = ptr;
-  char const *end = p + len;
-  unsigned char c;
-  EMACS_UINT hash = 0;
-
-  while (p != end)
+  EMACS_UINT const *p   = (EMACS_UINT const *) ptr;
+  EMACS_UINT const *end = (EMACS_UINT const *) (ptr + len);
+  EMACS_UINT hash = len;
+  /* At most 8 steps.  We could reuse SXHASH_MAX_LEN, of course,
+   * but dividing by 8 is cheaper.  */
+  ptrdiff_t step = 1 + ((end - p) >> 3);
+
+  /* Beware: `end` might be unaligned, so `p < end` is not always the same
+   * as `p <= end - 1`.  */
+  while (p <= end - 1)
     {
-      c = *p++;
+      EMACS_UINT c = *p;
+      p += step;
       hash = sxhash_combine (hash, c);
     }
+  if (p < end)
+    { /* A few last bytes remain (smaller than an EMACS_UINT).  */
+      /* FIXME: We could do this without a loop, but it'd require
+         endian-dependent code :-(  */
+      char const *p1 = (char const *)p;
+      char const *end1 = (char const *)end;
+      do
+        {
+          unsigned char c = *p1++;
+          hash = sxhash_combine (hash, c);
+        }
+      while (p1 < end1);
+    }
 
   return hash;
 }
@@ -5418,7 +5436,8 @@ disregarding any coding systems.  If nil, use the current 
buffer.
 
 This function is useful for comparing two buffers running in the same
 Emacs, but is not guaranteed to return the same hash between different
-Emacs versions.
+Emacs versions.  It should be somewhat more efficient on larger
+buffers than `secure-hash' is, and should not allocate more memory.
 
 It should not be used for anything security-related.  See
 `secure-hash' for these applications.  */ )
@@ -5551,6 +5570,40 @@ Case is always significant and text properties are 
ignored. */)
 
   return make_int (string_byte_to_char (haystack, res - SSDATA (haystack)));
 }
+
+static void
+collect_interval (INTERVAL interval, Lisp_Object collector)
+{
+  nconc2 (collector,
+         list1(list3 (make_fixnum (interval->position),
+                      make_fixnum (interval->position + LENGTH (interval)),
+                      interval->plist)));
+}
+
+DEFUN ("object-intervals", Fobject_intervals, Sobject_intervals, 1, 1, 0,
+       doc: /* Return a copy of the text properties of OBJECT.
+OBJECT must be a buffer or a string.
+
+Altering this copy does not change the layout of the text properties
+in OBJECT.  */)
+  (register Lisp_Object object)
+{
+  Lisp_Object collector = Fcons (Qnil, Qnil);
+  INTERVAL intervals;
+
+  if (STRINGP (object))
+    intervals = string_intervals (object);
+  else if (BUFFERP (object))
+    intervals = buffer_intervals (XBUFFER (object));
+  else
+    wrong_type_argument (Qbuffer_or_string_p, object);
+
+  if (! intervals)
+    return Qnil;
+
+  traverse_intervals (intervals, 0, collect_interval, collector);
+  return CDR (collector);
+}
 
 
 void
@@ -5592,6 +5645,7 @@ syms_of_fns (void)
   defsubr (&Smaphash);
   defsubr (&Sdefine_hash_table_test);
   defsubr (&Sstring_search);
+  defsubr (&Sobject_intervals);
 
   /* Crypto and hashing stuff.  */
   DEFSYM (Qiv_auto, "iv-auto");
diff --git a/src/frame.c b/src/frame.c
index a67ec47..a827eaa 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -3580,7 +3580,9 @@ window managers may refuse to honor a HEIGHT that is not 
an integer
 multiple of the default frame font height.
 
 When called interactively, HEIGHT is the numeric prefix and the
-currently selected frame will be set to this height.  */)
+currently selected frame will be set to this height.
+
+If FRAME is nil, it defaults to the selected frame.  */)
   (Lisp_Object frame, Lisp_Object height, Lisp_Object pretend, Lisp_Object 
pixelwise)
 {
   struct frame *f = decode_live_frame (frame);
@@ -3603,7 +3605,9 @@ window managers may refuse to honor a WIDTH that is not 
an integer
 multiple of the default frame font width.
 
 When called interactively, WIDTH is the numeric prefix and the
-currently selected frame will be set to this width.    */)
+currently selected frame will be set to this width.
+
+If FRAME is nil, it defaults to the selected frame.  */)
   (Lisp_Object frame, Lisp_Object width, Lisp_Object pretend, Lisp_Object 
pixelwise)
 {
   struct frame *f = decode_live_frame (frame);
@@ -3619,7 +3623,9 @@ Optional argument PIXELWISE non-nil means to measure in 
pixels.  Note:
 When `frame-resize-pixelwise' is nil, some window managers may refuse to
 honor a WIDTH that is not an integer multiple of the default frame font
 width or a HEIGHT that is not an integer multiple of the default frame
-font height.  */)
+font height.
+
+If FRAME is nil, it defaults to the selected frame.  */)
   (Lisp_Object frame, Lisp_Object width, Lisp_Object height, Lisp_Object 
pixelwise)
 {
   struct frame *f = decode_live_frame (frame);
diff --git a/src/image.c b/src/image.c
index e2d142e..e2a3902 100644
--- a/src/image.c
+++ b/src/image.c
@@ -1703,17 +1703,6 @@ make_image_cache (void)
   return c;
 }
 
-/* Compare two lists (one of which must be proper), comparing each
-   element with `eq'.  */
-static bool
-equal_lists (Lisp_Object a, Lisp_Object b)
-{
-  while (CONSP (a) && CONSP (b) && EQ (XCAR (a), XCAR (b)))
-    a = XCDR (a), b = XCDR (b);
-
-  return EQ (a, b);
-}
-
 /* Find an image matching SPEC in the cache, and return it.  If no
    image is found, return NULL.  */
 static struct image *
@@ -1741,7 +1730,7 @@ search_image_cache (struct frame *f, Lisp_Object spec, 
EMACS_UINT hash,
 
   for (img = c->buckets[i]; img; img = img->next)
     if (img->hash == hash
-       && equal_lists (img->spec, spec)
+       && !NILP (Fequal (img->spec, spec))
        && (ignore_colors || (img->face_foreground == foreground
                               && img->face_background == background)))
       break;
@@ -1755,12 +1744,13 @@ static void
 uncache_image (struct frame *f, Lisp_Object spec)
 {
   struct image *img;
+  EMACS_UINT hash = sxhash (spec);
 
   /* Because the background colors are based on the current face, we
      can have multiple copies of an image with the same spec. We want
      to remove them all to ensure the user doesn't see an old version
      of the image when the face changes.  */
-  while ((img = search_image_cache (f, spec, sxhash (spec), 0, 0, true)))
+  while ((img = search_image_cache (f, spec, hash, 0, 0, true)))
     {
       free_image (f, img);
       /* As display glyphs may still be referring to the image ID, we
@@ -1913,6 +1903,55 @@ which is then usually a filename.  */)
   return Qnil;
 }
 
+static size_t
+image_frame_cache_size (struct frame *f)
+{
+  size_t total = 0;
+#if defined USE_CAIRO
+  struct image_cache *c = FRAME_IMAGE_CACHE (f);
+
+  if (!c)
+    return 0;
+
+  for (ptrdiff_t i = 0; i < c->used; ++i)
+    {
+      struct image *img = c->images[i];
+
+      if (img && img->pixmap && img->pixmap != NO_PIXMAP)
+       total += img->pixmap->width * img->pixmap->height  *
+         img->pixmap->bits_per_pixel / 8;
+    }
+#elif defined HAVE_NTGUI
+  struct image_cache *c = FRAME_IMAGE_CACHE (f);
+
+  if (!c)
+    return 0;
+
+  for (ptrdiff_t i = 0; i < c->used; ++i)
+    {
+      struct image *img = c->images[i];
+
+      if (img && img->pixmap && img->pixmap != NO_PIXMAP)
+       total += w32_image_size (img);
+    }
+#endif
+  return total;
+}
+
+DEFUN ("image-cache-size", Fimage_cache_size, Simage_cache_size, 0, 0, 0,
+       doc: /* Return the size of the image cache.  */)
+  (void)
+{
+  Lisp_Object tail, frame;
+  size_t total = 0;
+
+  FOR_EACH_FRAME (tail, frame)
+    if (FRAME_WINDOW_P (XFRAME (frame)))
+      total += image_frame_cache_size (XFRAME (frame));
+
+  return make_int (total);
+}
+
 
 DEFUN ("image-flush", Fimage_flush, Simage_flush,
        1, 2, 0,
@@ -9571,6 +9610,7 @@ enum svg_keyword_index
   SVG_TYPE,
   SVG_DATA,
   SVG_FILE,
+  SVG_BASE_URI,
   SVG_ASCENT,
   SVG_MARGIN,
   SVG_RELIEF,
@@ -9590,6 +9630,7 @@ static const struct image_keyword svg_format[SVG_LAST] =
   {":type",            IMAGE_SYMBOL_VALUE,                     1},
   {":data",            IMAGE_STRING_VALUE,                     0},
   {":file",            IMAGE_STRING_VALUE,                     0},
+  {":base-uri",                IMAGE_STRING_VALUE,                     0},
   {":ascent",          IMAGE_ASCENT_VALUE,                     0},
   {":margin",          IMAGE_NON_NEGATIVE_INTEGER_VALUE_OR_PAIR, 0},
   {":relief",          IMAGE_INTEGER_VALUE,                    0},
@@ -9662,6 +9703,9 @@ DEF_DLL_FN (gboolean, rsvg_handle_write,
 DEF_DLL_FN (gboolean, rsvg_handle_close, (RsvgHandle *, GError **));
 #  endif
 
+DEF_DLL_FN (void, rsvg_handle_set_dpi_x_y,
+           (RsvgHandle * handle, double dpi_x, double dpi_y));
+
 #  if LIBRSVG_CHECK_VERSION (2, 46, 0)
 DEF_DLL_FN (void, rsvg_handle_get_intrinsic_dimensions,
             (RsvgHandle *, gboolean *, RsvgLength *, gboolean *,
@@ -9718,6 +9762,7 @@ init_svg_functions (void)
   LOAD_DLL_FN (library, rsvg_handle_write);
   LOAD_DLL_FN (library, rsvg_handle_close);
 #endif
+  LOAD_DLL_FN (library, rsvg_handle_set_dpi_x_y);
 #if LIBRSVG_CHECK_VERSION (2, 46, 0)
   LOAD_DLL_FN (library, rsvg_handle_get_intrinsic_dimensions);
   LOAD_DLL_FN (library, rsvg_handle_get_geometry_for_layer);
@@ -9773,6 +9818,7 @@ init_svg_functions (void)
 #   undef rsvg_handle_set_base_uri
 #   undef rsvg_handle_write
 #  endif
+#  undef rsvg_handle_set_dpi_x_y
 
 #  define gdk_pixbuf_get_bits_per_sample fn_gdk_pixbuf_get_bits_per_sample
 #  define gdk_pixbuf_get_colorspace fn_gdk_pixbuf_get_colorspace
@@ -9806,6 +9852,7 @@ init_svg_functions (void)
 #   define rsvg_handle_set_base_uri fn_rsvg_handle_set_base_uri
 #   define rsvg_handle_write fn_rsvg_handle_write
 #  endif
+#  define rsvg_handle_set_dpi_x_y fn_rsvg_handle_set_dpi_x_y
 
 # endif /* !WINDOWSNT  */
 
@@ -9816,10 +9863,11 @@ static bool
 svg_load (struct frame *f, struct image *img)
 {
   bool success_p = 0;
-  Lisp_Object file_name;
+  Lisp_Object file_name, base_uri;
 
   /* If IMG->spec specifies a file name, create a non-file spec from it.  */
   file_name = image_spec_value (img->spec, QCfile, NULL);
+  base_uri = image_spec_value (img->spec, QCbase_uri, NULL);
   if (STRINGP (file_name))
     {
       int fd;
@@ -9839,15 +9887,16 @@ svg_load (struct frame *f, struct image *img)
          return 0;
        }
       /* If the file was slurped into memory properly, parse it.  */
-      success_p = svg_load_image (f, img, contents, size,
-                                 SSDATA (ENCODE_FILE (file)));
+      if (!STRINGP (base_uri))
+        base_uri = ENCODE_FILE (file);
+      success_p = svg_load_image (f, img, contents, size, SSDATA (base_uri));
       xfree (contents);
     }
   /* Else it's not a file, it's a Lisp object.  Load the image from a
      Lisp object rather than a file.  */
   else
     {
-      Lisp_Object data, original_filename;
+      Lisp_Object data;
 
       data = image_spec_value (img->spec, QCdata, NULL);
       if (!STRINGP (data))
@@ -9855,10 +9904,10 @@ svg_load (struct frame *f, struct image *img)
          image_error ("Invalid image data `%s'", data);
          return 0;
        }
-      original_filename = BVAR (current_buffer, filename);
+      if (!STRINGP (base_uri))
+        base_uri = BVAR (current_buffer, filename);
       success_p = svg_load_image (f, img, SSDATA (data), SBYTES (data),
-                                  (NILP (original_filename) ? NULL
-                                  : SSDATA (original_filename)));
+                                  (NILP (base_uri) ? NULL : SSDATA 
(base_uri)));
     }
 
   return success_p;
@@ -9866,11 +9915,8 @@ svg_load (struct frame *f, struct image *img)
 
 #if LIBRSVG_CHECK_VERSION (2, 46, 0)
 static double
-svg_css_length_to_pixels (RsvgLength length)
+svg_css_length_to_pixels (RsvgLength length, double dpi)
 {
-  /* FIXME: 96 appears to be a pretty standard DPI but we should
-     probably use the real DPI if we can get it.  */
-  double dpi = 96;
   double value = length.length;
 
   switch (length.unit)
@@ -9944,18 +9990,26 @@ svg_load_image (struct frame *f, struct image *img, 
char *contents,
   rsvg_handle = rsvg_handle_new_from_stream_sync (input_stream, base_file,
                                                  RSVG_HANDLE_FLAGS_NONE,
                                                  NULL, &err);
+
   if (base_file)
     g_object_unref (base_file);
   g_object_unref (input_stream);
 
   /* Check rsvg_handle too, to avoid librsvg 2.40.13 bug (Bug#36773#26).  */
   if (!rsvg_handle || err) goto rsvg_error;
+
+  rsvg_handle_set_dpi_x_y (rsvg_handle, FRAME_DISPLAY_INFO (f)->resx,
+                           FRAME_DISPLAY_INFO (f)->resy);
 #else
   /* Make a handle to a new rsvg object.  */
   rsvg_handle = rsvg_handle_new ();
   eassume (rsvg_handle);
 
+  rsvg_handle_set_dpi_x_y (rsvg_handle, FRAME_DISPLAY_INFO (f)->resx,
+                           FRAME_DISPLAY_INFO (f)->resy);
+
   /* Set base_uri for properly handling referenced images (via 'href').
+     Can be explicitly specified using `:base_uri' image property.
      See rsvg bug 596114 - "image refs are relative to curdir, not .svg file"
      <https://gitlab.gnome.org/GNOME/librsvg/issues/33>. */
   if (filename)
@@ -9978,6 +10032,7 @@ svg_load_image (struct frame *f, struct image *img, char 
*contents,
   /* Try the instrinsic dimensions first.  */
   gboolean has_width, has_height, has_viewbox;
   RsvgLength iwidth, iheight;
+  double dpi = FRAME_DISPLAY_INFO (f)->resx;
 
   rsvg_handle_get_intrinsic_dimensions (rsvg_handle,
                                         &has_width, &iwidth,
@@ -9987,19 +10042,19 @@ svg_load_image (struct frame *f, struct image *img, 
char *contents,
   if (has_width && has_height)
     {
       /* Success!  We can use these values directly.  */
-      viewbox_width = svg_css_length_to_pixels (iwidth);
-      viewbox_height = svg_css_length_to_pixels (iheight);
+      viewbox_width = svg_css_length_to_pixels (iwidth, dpi);
+      viewbox_height = svg_css_length_to_pixels (iheight, dpi);
     }
   else if (has_width && has_viewbox)
     {
-      viewbox_width = svg_css_length_to_pixels (iwidth);
-      viewbox_height = svg_css_length_to_pixels (iwidth)
+      viewbox_width = svg_css_length_to_pixels (iwidth, dpi);
+      viewbox_height = svg_css_length_to_pixels (iwidth, dpi)
         * viewbox.width / viewbox.height;
     }
   else if (has_height && has_viewbox)
     {
-      viewbox_height = svg_css_length_to_pixels (iheight);
-      viewbox_width = svg_css_length_to_pixels (iheight)
+      viewbox_height = svg_css_length_to_pixels (iheight, dpi);
+      viewbox_width = svg_css_length_to_pixels (iheight, dpi)
         * viewbox.height / viewbox.width;
     }
   else if (has_viewbox)
@@ -10108,18 +10163,26 @@ svg_load_image (struct frame *f, struct image *img, 
char *contents,
   rsvg_handle = rsvg_handle_new_from_stream_sync (input_stream, base_file,
                                                  RSVG_HANDLE_FLAGS_NONE,
                                                  NULL, &err);
+
   if (base_file)
     g_object_unref (base_file);
   g_object_unref (input_stream);
 
   /* Check rsvg_handle too, to avoid librsvg 2.40.13 bug (Bug#36773#26).  */
   if (!rsvg_handle || err) goto rsvg_error;
+
+  rsvg_handle_set_dpi_x_y (rsvg_handle, FRAME_DISPLAY_INFO (f)->resx,
+                           FRAME_DISPLAY_INFO (f)->resy);
 #else
   /* Make a handle to a new rsvg object.  */
   rsvg_handle = rsvg_handle_new ();
   eassume (rsvg_handle);
 
+  rsvg_handle_set_dpi_x_y (rsvg_handle, FRAME_DISPLAY_INFO (f)->resx,
+                           FRAME_DISPLAY_INFO (f)->resy);
+
   /* Set base_uri for properly handling referenced images (via 'href').
+     Can be explicitly specified using `:base_uri' image property.
      See rsvg bug 596114 - "image refs are relative to curdir, not .svg file"
      <https://gitlab.gnome.org/GNOME/librsvg/issues/33>. */
   if (filename)
@@ -10802,6 +10865,7 @@ non-numeric, there is no explicit limit on the size of 
images.  */);
 
 #if defined (HAVE_RSVG)
   DEFSYM (Qsvg, "svg");
+  DEFSYM (QCbase_uri, ":base-uri");
   add_image_type (Qsvg);
 #ifdef HAVE_NTGUI
   /* Other libraries used directly by svg code.  */
@@ -10831,6 +10895,7 @@ non-numeric, there is no explicit limit on the size of 
images.  */);
   defsubr (&Simage_size);
   defsubr (&Simage_mask_p);
   defsubr (&Simage_metadata);
+  defsubr (&Simage_cache_size);
 
 #ifdef GLYPH_DEBUG
   defsubr (&Simagep);
diff --git a/src/keyboard.c b/src/keyboard.c
index 6605419..e8d0747 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -384,11 +384,13 @@ next_kbd_event (union buffered_input_event *ptr)
   return ptr == kbd_buffer + KBD_BUFFER_SIZE - 1 ? kbd_buffer : ptr + 1;
 }
 
+#ifdef HAVE_X11
 static union buffered_input_event *
 prev_kbd_event (union buffered_input_event *ptr)
 {
   return ptr == kbd_buffer ? kbd_buffer + KBD_BUFFER_SIZE - 1 : ptr - 1;
 }
+#endif
 
 /* Like EVENT_START, but assume EVENT is an event.
    This pacifies gcc -Wnull-dereference, which might otherwise
@@ -741,9 +743,6 @@ void
 force_auto_save_soon (void)
 {
   last_auto_save = - auto_save_interval - 1;
-  /* FIXME: What's the relationship between forcing auto-save and adding
-     a buffer-switch event?  */
-  record_asynch_buffer_change ();
 }
 #endif
 
@@ -3431,8 +3430,7 @@ readable_events (int flags)
                       && event->ie.part == scroll_bar_handle
                       && event->ie.modifiers == 0)
 #endif
-                 && !((flags & READABLE_EVENTS_FILTER_EVENTS)
-                      && event->kind == BUFFER_SWITCH_EVENT))
+                )
                return 1;
              event = next_kbd_event (event);
            }
@@ -3583,12 +3581,6 @@ kbd_buffer_store_buffered_event (union 
buffered_input_event *event,
          return;
        }
     }
-  /* Don't insert two BUFFER_SWITCH_EVENT's in a row.
-     Just ignore the second one.  */
-  else if (event->kind == BUFFER_SWITCH_EVENT
-          && kbd_fetch_ptr != kbd_store_ptr
-          && prev_kbd_event (kbd_store_ptr)->kind == BUFFER_SWITCH_EVENT)
-    return;
 
   /* Don't let the very last slot in the buffer become full,
      since that would make the two pointers equal,
@@ -3622,7 +3614,6 @@ kbd_buffer_store_buffered_event (union 
buffered_input_event *event,
     case ICONIFY_EVENT: ignore_event = Qiconify_frame; break;
     case DEICONIFY_EVENT: ignore_event = Qmake_frame_visible; break;
     case SELECTION_REQUEST_EVENT: ignore_event = Qselection_request; break;
-    case BUFFER_SWITCH_EVENT: ignore_event = Qbuffer_switch; break;
     default: ignore_event = Qnil; break;
     }
 
@@ -3964,7 +3955,6 @@ kbd_buffer_get_event (KBOARD **kbp,
 #ifdef HAVE_XWIDGETS
       case XWIDGET_EVENT:
 #endif
-      case BUFFER_SWITCH_EVENT:
       case SAVE_SESSION_EVENT:
       case NO_EVENT:
       case HELP_EVENT:
@@ -5344,14 +5334,6 @@ make_lispy_event (struct input_event *event)
       return list2 (Qmove_frame, list1 (event->frame_or_window));
 #endif
 
-    case BUFFER_SWITCH_EVENT:
-      {
-       /* The value doesn't matter here; only the type is tested.  */
-       Lisp_Object obj;
-        XSETBUFFER (obj, current_buffer);
-        return obj;
-      }
-
     /* Just discard these, by returning nil.
        With MULTI_KBOARD, these events are used as placeholders
        when we need to randomly delete events from the queue.
@@ -6813,41 +6795,6 @@ get_input_pending (int flags)
   return input_pending;
 }
 
-/* Put a BUFFER_SWITCH_EVENT in the buffer
-   so that read_key_sequence will notice the new current buffer.  */
-
-void
-record_asynch_buffer_change (void)
-{
-  /* We don't need a buffer-switch event unless Emacs is waiting for input.
-     The purpose of the event is to make read_key_sequence look up the
-     keymaps again.  If we aren't in read_key_sequence, we don't need one,
-     and the event could cause trouble by messing up (input-pending-p).
-     Note: Fwaiting_for_user_input_p always returns nil when async
-     subprocesses aren't supported.  */
-  if (!NILP (Fwaiting_for_user_input_p ()))
-    {
-      struct input_event event;
-
-      EVENT_INIT (event);
-      event.kind = BUFFER_SWITCH_EVENT;
-      event.frame_or_window = Qnil;
-      event.arg = Qnil;
-
-      /* Make sure no interrupt happens while storing the event.  */
-#ifdef USABLE_SIGIO
-      if (interrupt_input)
-       kbd_buffer_store_event (&event);
-      else
-#endif
-       {
-         stop_polling ();
-         kbd_buffer_store_event (&event);
-         start_polling ();
-       }
-    }
-}
-
 /* Read any terminal input already buffered up by the system
    into the kbd_buffer, but do not wait.
 
@@ -11581,8 +11528,6 @@ syms_of_keyboard (void)
   /* Menu and tool bar item parts.  */
   DEFSYM (Qmenu_enable, "menu-enable");
 
-  DEFSYM (Qbuffer_switch, "buffer-switch");
-
 #ifdef HAVE_NTGUI
   DEFSYM (Qlanguage_change, "language-change");
   DEFSYM (Qend_session, "end-session");
diff --git a/src/keyboard.h b/src/keyboard.h
index 41da3a6..24e9a00 100644
--- a/src/keyboard.h
+++ b/src/keyboard.h
@@ -446,7 +446,6 @@ extern void push_kboard (struct kboard *);
 extern void push_frame_kboard (struct frame *);
 extern void pop_kboard (void);
 extern void temporarily_switch_to_single_kboard (struct frame *);
-extern void record_asynch_buffer_change (void);
 extern void input_poll_signal (int);
 extern void start_polling (void);
 extern void stop_polling (void);
diff --git a/src/lisp.h b/src/lisp.h
index 416c9b0..e833044 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -1897,16 +1897,17 @@ ASCII_CHAR_P (intmax_t c)
   return 0 <= c && c < 0x80;
 }
 
-/* A char-table is a kind of vectorlike, with contents are like a
-   vector but with a few other slots.  For some purposes, it makes
-   sense to handle a char-table with type struct Lisp_Vector.  An
-   element of a char table can be any Lisp objects, but if it is a sub
-   char-table, we treat it a table that contains information of a
-   specific range of characters.  A sub char-table is like a vector but
-   with two integer fields between the header and Lisp data, which means
+/* A char-table is a kind of vectorlike, with contents like a vector,
+   but with a few additional slots.  For some purposes, it makes sense
+   to handle a char-table as type 'struct Lisp_Vector'.  An element of
+   a char-table can be any Lisp object, but if it is a sub-char-table,
+   we treat it as a table that contains information of a specific
+   range of characters.  A sub-char-table is like a vector, but with
+   two integer fields between the header and Lisp data, which means
    that it has to be marked with some precautions (see mark_char_table
-   in alloc.c).  A sub char-table appears only in an element of a char-table,
-   and there's no way to access it directly from Emacs Lisp program.  */
+   in alloc.c).  A sub-char-table appears only in an element of a
+   char-table, and there's no way to access it directly from a Lisp
+   program.  */
 
 enum CHARTAB_SIZE_BITS
   {
@@ -1926,11 +1927,11 @@ struct Lisp_Char_Table
        contents, and extras slots.  */
     union vectorlike_header header;
 
-    /* This holds a default value,
-       which is used whenever the value for a specific character is nil.  */
+    /* This holds the default value, which is used whenever the value
+       for a specific character is nil.  */
     Lisp_Object defalt;
 
-    /* This points to another char table, which we inherit from when the
+    /* This points to another char table, from which we inherit when the
        value for a specific character is nil.  The `defalt' slot takes
        precedence over this.  */
     Lisp_Object parent;
@@ -1939,8 +1940,8 @@ struct Lisp_Char_Table
        meant for.  */
     Lisp_Object purpose;
 
-    /* The bottom sub char-table for characters of the range 0..127.  It
-       is nil if none of ASCII character has a specific value.  */
+    /* The bottom sub char-table for characters in the range 0..127.  It
+       is nil if no ASCII character has a specific value.  */
     Lisp_Object ascii;
 
     Lisp_Object contents[(1 << CHARTAB_SIZE_BITS_0)];
@@ -2015,7 +2016,7 @@ CHAR_TABLE_REF_ASCII (Lisp_Object ct, ptrdiff_t idx)
 }
 
 /* Almost equivalent to Faref (CT, IDX) with optimization for ASCII
-   characters.  Do not check validity of CT.  */
+   characters.  Does not check validity of CT.  */
 INLINE Lisp_Object
 CHAR_TABLE_REF (Lisp_Object ct, int idx)
 {
@@ -2025,7 +2026,7 @@ CHAR_TABLE_REF (Lisp_Object ct, int idx)
 }
 
 /* Equivalent to Faset (CT, IDX, VAL) with optimization for ASCII and
-   8-bit European characters.  Do not check validity of CT.  */
+   8-bit European characters.  Does not check validity of CT.  */
 INLINE void
 CHAR_TABLE_SET (Lisp_Object ct, int idx, Lisp_Object val)
 {
diff --git a/src/nsterm.m b/src/nsterm.m
index 0729c96..7972fa4 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -1166,7 +1166,6 @@ ns_update_end (struct frame *f)
     {
 #endif
       [NSGraphicsContext setCurrentContext:nil];
-      [view setNeedsDisplay:YES];
 #if MAC_OS_X_VERSION_MIN_REQUIRED < 101400
     }
   else
@@ -3056,7 +3055,7 @@ ns_clear_under_internal_border (struct frame *f)
       if (!face)
         return;
 
-      ns_focus (f, &frame_rect, 1);
+      ns_focus (f, NULL, 1);
       [ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f) set];
       for (int i = 0; i < 4 ; i++)
         {
@@ -4987,8 +4986,8 @@ ns_set_vertical_scroll_bar (struct window *window,
           [bar removeFromSuperview];
           wset_vertical_scroll_bar (window, Qnil);
           [bar release];
+          ns_clear_frame_area (f, left, top, width, height);
         }
-      ns_clear_frame_area (f, left, top, width, height);
       unblock_input ();
       return;
     }
@@ -5010,7 +5009,7 @@ ns_set_vertical_scroll_bar (struct window *window,
       r.size.width = oldRect.size.width;
       if (FRAME_LIVE_P (f) && !NSEqualRects (oldRect, r))
         {
-          if (oldRect.origin.x != r.origin.x)
+          if (! NSEqualRects (oldRect, r))
               ns_clear_frame_area (f, left, top, width, height);
           [bar setFrame: r];
         }
@@ -5088,8 +5087,7 @@ ns_set_horizontal_scroll_bar (struct window *window,
       oldRect = [bar frame];
       if (FRAME_LIVE_P (f) && !NSEqualRects (oldRect, r))
         {
-          if (oldRect.origin.y != r.origin.y)
-            ns_clear_frame_area (f, left, top, width, height);
+          ns_clear_frame_area (f, left, top, width, height);
           [bar setFrame: r];
           update_p = YES;
         }
diff --git a/src/process.c b/src/process.c
index 9926993..b2d94d8 100644
--- a/src/process.c
+++ b/src/process.c
@@ -5328,19 +5328,9 @@ wait_reading_process_output (intmax_t time_limit, int 
nsecs, int read_kbd,
          do
            {
              unsigned old_timers_run = timers_run;
-             struct buffer *old_buffer = current_buffer;
-             Lisp_Object old_window = selected_window;
 
              timer_delay = timer_check ();
 
-             /* If a timer has run, this might have changed buffers
-                an alike.  Make read_key_sequence aware of that.  */
-             if (timers_run != old_timers_run
-                 && (old_buffer != current_buffer
-                     || !EQ (old_window, selected_window))
-                 && waiting_for_user_input_p == -1)
-               record_asynch_buffer_change ();
-
              if (timers_run != old_timers_run && do_display)
                /* We must retry, since a timer may have requeued itself
                   and that could alter the time_delay.  */
@@ -5698,9 +5688,6 @@ wait_reading_process_output (intmax_t time_limit, int 
nsecs, int read_kbd,
 
       if (read_kbd != 0)
        {
-         unsigned old_timers_run = timers_run;
-         struct buffer *old_buffer = current_buffer;
-         Lisp_Object old_window = selected_window;
          bool leave = false;
 
          if (detect_input_pending_run_timers (do_display))
@@ -5710,14 +5697,6 @@ wait_reading_process_output (intmax_t time_limit, int 
nsecs, int read_kbd,
                leave = true;
            }
 
-         /* If a timer has run, this might have changed buffers
-            an alike.  Make read_key_sequence aware of that.  */
-         if (timers_run != old_timers_run
-             && waiting_for_user_input_p == -1
-             && (old_buffer != current_buffer
-             || !EQ (old_window, selected_window)))
-           record_asynch_buffer_change ();
-
          if (leave)
            break;
        }
@@ -6217,18 +6196,6 @@ read_and_dispose_of_process_output (struct Lisp_Process 
*p, char *chars,
   /* Restore waiting_for_user_input_p as it was
      when we were called, in case the filter clobbered it.  */
   waiting_for_user_input_p = waiting;
-
-#if 0 /* Call record_asynch_buffer_change unconditionally,
-        because we might have changed minor modes or other things
-        that affect key bindings.  */
-  if (! EQ (Fcurrent_buffer (), obuffer)
-      || ! EQ (current_buffer->keymap, okeymap))
-#endif
-    /* But do it only if the caller is actually going to read events.
-       Otherwise there's no need to make him wake up, and it could
-       cause trouble (for example it would make sit_for return).  */
-    if (waiting_for_user_input_p == -1)
-      record_asynch_buffer_change ();
 }
 
 DEFUN ("internal-default-process-filter", Finternal_default_process_filter,
@@ -7394,16 +7361,6 @@ exec_sentinel (Lisp_Object proc, Lisp_Object reason)
      when we were called, in case the filter clobbered it.  */
   waiting_for_user_input_p = waiting;
 
-#if 0
-  if (! EQ (Fcurrent_buffer (), obuffer)
-      || ! EQ (current_buffer->keymap, okeymap))
-#endif
-    /* But do it only if the caller is actually going to read events.
-       Otherwise there's no need to make him wake up, and it could
-       cause trouble (for example it would make sit_for return).  */
-    if (waiting_for_user_input_p == -1)
-      record_asynch_buffer_change ();
-
   unbind_to (count, Qnil);
 }
 
diff --git a/src/regex-emacs.c b/src/regex-emacs.c
index 971a5f6..904ca0c 100644
--- a/src/regex-emacs.c
+++ b/src/regex-emacs.c
@@ -3575,9 +3575,11 @@ skip_noops (re_char *p, re_char *pend)
    opcode.  When the function finishes, *PP will be advanced past that opcode.
    C is character to test (possibly after translations) and CORIG is original
    character (i.e. without any translations).  UNIBYTE denotes whether c is
-   unibyte or multibyte character. */
+   unibyte or multibyte character.
+   CANON_TABLE is the canonicalisation table for case folding or Qnil.  */
 static bool
-execute_charset (re_char **pp, int c, int corig, bool unibyte)
+execute_charset (re_char **pp, int c, int corig, bool unibyte,
+                 Lisp_Object canon_table)
 {
   eassume (0 <= c && 0 <= corig);
   re_char *p = *pp, *rtp = NULL;
@@ -3617,11 +3619,9 @@ execute_charset (re_char **pp, int c, int corig, bool 
unibyte)
           (class_bits & BIT_BLANK && ISBLANK (c)) ||
          (class_bits & BIT_WORD  && ISWORD  (c)) ||
          ((class_bits & BIT_UPPER) &&
-          (ISUPPER (c) || (corig != c &&
-                           c == downcase (corig) && ISLOWER (c)))) ||
+          (ISUPPER (corig) || (!NILP (canon_table) && ISLOWER (corig)))) ||
          ((class_bits & BIT_LOWER) &&
-          (ISLOWER (c) || (corig != c &&
-                           c == upcase (corig) && ISUPPER(c)))) ||
+          (ISLOWER (corig) || (!NILP (canon_table) && ISUPPER (corig)))) ||
          (class_bits & BIT_PUNCT && ISPUNCT (c)) ||
          (class_bits & BIT_GRAPH && ISGRAPH (c)) ||
          (class_bits & BIT_PRINT && ISPRINT (c)))
@@ -3696,7 +3696,8 @@ mutually_exclusive_p (struct re_pattern_buffer *bufp, 
re_char *p1,
        else if ((re_opcode_t) *p1 == charset
                 || (re_opcode_t) *p1 == charset_not)
          {
-           if (!execute_charset (&p1, c, c, !multibyte || ASCII_CHAR_P (c)))
+           if (!execute_charset (&p1, c, c, !multibyte || ASCII_CHAR_P (c),
+                                  Qnil))
              {
                DEBUG_PRINT ("   No match => fast loop.\n");
                return true;
@@ -4367,7 +4368,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp,
              }
 
            p -= 1;
-           if (!execute_charset (&p, c, corig, unibyte_char))
+           if (!execute_charset (&p, c, corig, unibyte_char, translate))
              goto fail;
 
            d += len;
diff --git a/src/termhooks.h b/src/termhooks.h
index c28c3fb..276b068 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -160,7 +160,6 @@ enum event_kind
   SELECTION_REQUEST_EVENT,     /* Another X client wants a selection from us.
                                   See `struct selection_input_event'.  */
   SELECTION_CLEAR_EVENT,       /* Another X client cleared our selection.  */
-  BUFFER_SWITCH_EVENT,         /* A process filter has switched buffers.  */
   DELETE_WINDOW_EVENT,         /* An X client said "delete this window".  */
 #ifdef HAVE_NTGUI
   END_SESSION_EVENT,           /* The user is logging out or shutting down.  */
diff --git a/src/thread.h b/src/thread.h
index a09929f..9697e49 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -140,7 +140,6 @@ struct thread_state
      for user-input when that process-filter was called.
      waiting_for_input cannot be used as that is by definition 0 when
      lisp code is being evalled.
-     This is also used in record_asynch_buffer_change.
      For that purpose, this must be 0
      when not inside wait_reading_process_output.  */
   int m_waiting_for_user_input_p;
diff --git a/src/w32gui.h b/src/w32gui.h
index dfec1f0..fc81311 100644
--- a/src/w32gui.h
+++ b/src/w32gui.h
@@ -46,6 +46,7 @@ extern int w32_load_image (struct frame *f, struct image *img,
                            Lisp_Object spec_file, Lisp_Object spec_data);
 extern bool w32_can_use_native_image_api (Lisp_Object);
 extern void w32_gdiplus_shutdown (void);
+extern size_t w32_image_size (struct image *);
 
 #define FACE_DEFAULT (~0)
 
diff --git a/src/w32term.c b/src/w32term.c
index 23cb380..a038e45 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -1991,6 +1991,17 @@ w32_draw_image_foreground (struct glyph_string *s)
   RestoreDC (s->hdc ,-1);
 }
 
+size_t
+w32_image_size (struct image *img)
+{
+  BITMAP bm_info;
+  size_t rv = 0;
+
+  if (GetObject (img->pixmap, sizeof (BITMAP), &bm_info))
+    rv = bm_info.bmWidth * bm_info.bmHeight * bm_info.bmBitsPixel / 8;
+  return rv;
+}
+
 
 /* Draw a relief around the image glyph string S.  */
 
@@ -4847,10 +4858,6 @@ w32_read_socket (struct terminal *terminal,
                      inev.kind = DEICONIFY_EVENT;
                      XSETFRAME (inev.frame_or_window, f);
                    }
-                 else if (!NILP (Vframe_list) && !NILP (XCDR (Vframe_list)))
-                   /* Force a redisplay sooner or later to update the
-                      frame titles in case this is the second frame.  */
-                   record_asynch_buffer_change ();
                }
              else
                {
@@ -5468,12 +5475,6 @@ w32_read_socket (struct terminal *terminal,
                        inev.kind = DEICONIFY_EVENT;
                        XSETFRAME (inev.frame_or_window, f);
                      }
-                   else if (! NILP (Vframe_list)
-                            && ! NILP (XCDR (Vframe_list)))
-                     /* Force a redisplay sooner or later
-                        to update the frame titles
-                        in case this is the second frame.  */
-                     record_asynch_buffer_change ();
 
                  /* Windows can send us a SIZE_MAXIMIZED message even
                     when fullscreen is fullboth.  The following is a
@@ -5521,12 +5522,6 @@ w32_read_socket (struct terminal *terminal,
                        inev.kind = DEICONIFY_EVENT;
                        XSETFRAME (inev.frame_or_window, f);
                      }
-                   else if (! NILP (Vframe_list)
-                            && ! NILP (XCDR (Vframe_list)))
-                     /* Force a redisplay sooner or later
-                        to update the frame titles
-                        in case this is the second frame.  */
-                     record_asynch_buffer_change ();
                  }
 
                  if (EQ (get_frame_param (f, Qfullscreen), Qmaximized))
@@ -5818,9 +5813,6 @@ w32_read_socket (struct terminal *terminal,
                    SET_FRAME_GARBAGED (f);
                    DebPrint (("obscured frame %p (%s) found to be visible\n",
                               f, SDATA (f->name)));
-
-                   /* Force a redisplay sooner or later.  */
-                   record_asynch_buffer_change ();
                  }
              }
          }
diff --git a/src/window.c b/src/window.c
index 6cd3122..8e75e46 100644
--- a/src/window.c
+++ b/src/window.c
@@ -5669,7 +5669,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, 
bool whole, bool noerror)
   if (whole)
     {
       ptrdiff_t start_pos = IT_CHARPOS (it);
-      int dy = frame_line_height;
+      int flh = frame_line_height;
       int ht = window_box_height (w);
       int nscls = sanitize_next_screen_context_lines ();
       /* In the below we divide the window box height by the frame's
@@ -5677,14 +5677,37 @@ window_scroll_pixel_based (Lisp_Object window, int n, 
bool whole, bool noerror)
         box is not an integral multiple of the line height.  This is
         important to ensure we get back to the same position when
         scrolling up, then down.  */
-      dy = n * max (dy, (ht / dy - nscls) * dy);
+      int dy = n * max (flh, (ht / flh - nscls) * flh);
+      int goal_y;
+      void *it_data;
 
       /* Note that move_it_vertically always moves the iterator to the
          start of a line.  So, if the last line doesn't have a newline,
         we would end up at the start of the line ending at ZV.  */
       if (dy <= 0)
        {
+         goal_y = it.current_y - dy;
          move_it_vertically_backward (&it, -dy);
+         /* Extra precision for people who want us to preserve the
+            screen position of the cursor: effectively round DY to the
+            nearest screen line, instead of rounding to zero; the latter
+            causes point to move by one line after C-v followed by M-v,
+            if the buffer has lines of different height.  */
+         if (!NILP (Vscroll_preserve_screen_position)
+             && it.current_y - goal_y > 0.5 * flh)
+           {
+             it_data = bidi_shelve_cache ();
+             struct it it2 = it;
+
+             move_it_by_lines (&it, -1);
+             if (it.current_y < goal_y - 0.5 * flh)
+               {
+                 it = it2;
+                 bidi_unshelve_cache (it_data, false);
+               }
+             else
+               bidi_unshelve_cache (it_data, true);
+           }
          /* Ensure we actually do move, e.g. in case we are currently
             looking at an image that is taller that the window height.  */
          while (start_pos == IT_CHARPOS (it)
@@ -5693,8 +5716,25 @@ window_scroll_pixel_based (Lisp_Object window, int n, 
bool whole, bool noerror)
        }
       else if (dy > 0)
        {
-         move_it_to (&it, ZV, -1, it.current_y + dy, -1,
-                     MOVE_TO_POS | MOVE_TO_Y);
+         goal_y = it.current_y + dy;
+         move_it_to (&it, ZV, -1, goal_y, -1, MOVE_TO_POS | MOVE_TO_Y);
+         /* See the comment above, for the reasons of this
+            extra-precision.  */
+         if (!NILP (Vscroll_preserve_screen_position)
+             && goal_y - it.current_y  > 0.5 * flh)
+           {
+             it_data = bidi_shelve_cache ();
+             struct it it2 = it;
+
+             move_it_by_lines (&it, 1);
+             if (it.current_y > goal_y + 0.5 * flh)
+               {
+                 it = it2;
+                 bidi_unshelve_cache (it_data, false);
+               }
+             else
+               bidi_unshelve_cache (it_data, true);
+           }
          /* Ensure we actually do move, e.g. in case we are currently
             looking at an image that is taller that the window height.  */
          while (start_pos == IT_CHARPOS (it)
@@ -8206,11 +8246,17 @@ is displayed in the `mode-line' face.  */);
   DEFVAR_LISP ("scroll-preserve-screen-position",
               Vscroll_preserve_screen_position,
               doc: /* Controls if scroll commands move point to keep its 
screen position unchanged.
+
 A value of nil means point does not keep its screen position except
 at the scroll margin or window boundary respectively.
+
 A value of t means point keeps its screen position if the scroll
 command moved it vertically out of the window, e.g. when scrolling
-by full screens.
+by full screens.  If point is within `next-screen-context-lines' lines
+from the edges of the window, point will typically not keep its screen
+position when doing commands like `scroll-up-command'/`scroll-down-command'
+and the like.
+
 Any other value means point always keeps its screen position.
 Scroll commands should have the `scroll-command' property
 on their symbols to be controlled by this variable.  */);
diff --git a/src/xdisp.c b/src/xdisp.c
index 431d811..a8c66f0 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -1925,12 +1925,12 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int 
*x, int *y,
                  /* If it3_moved stays false after the 'while' loop
                     below, that means we already were at a newline
                     before the loop (e.g., the display string begins
-                    with a newline), so we don't need to (and cannot)
-                    inspect the glyphs of it3.glyph_row, because
-                    PRODUCE_GLYPHS will not produce anything for a
-                    newline, and thus it3.glyph_row stays at its
-                    stale content it got at top of the window.  */
+                    with a newline), so we don't need to return to
+                    the last position before the display string,
+                    because PRODUCE_GLYPHS will not produce anything
+                    for a newline.  */
                  bool it3_moved = false;
+                 int top_x_before_string = it3.current_x;
                  /* Finally, advance the iterator until we hit the
                     first display element whose character position is
                     CHARPOS, or until the first newline from the
@@ -1938,6 +1938,8 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int 
*x, int *y,
                     display line.  */
                  while (get_next_display_element (&it3))
                    {
+                     if (!EQ (it3.object, string))
+                       top_x_before_string = it3.current_x;
                      PRODUCE_GLYPHS (&it3);
                      if (IT_CHARPOS (it3) == charpos
                          || ITERATOR_AT_END_OF_LINE_P (&it3))
@@ -1952,32 +1954,26 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int 
*x, int *y,
                  if (!it3.line_number_produced_p)
                    {
                      if (it3.lnum_pixel_width > 0)
-                       top_x += it3.lnum_pixel_width;
+                       {
+                         top_x += it3.lnum_pixel_width;
+                         top_x_before_string += it3.lnum_pixel_width;
+                       }
                      else if (it.line_number_produced_p)
-                       top_x += it.lnum_pixel_width;
+                       {
+                         top_x += it.lnum_pixel_width;
+                         top_x_before_string += it3.lnum_pixel_width;
+                       }
                    }
                  /* Normally, we would exit the above loop because we
                     found the display element whose character
                     position is CHARPOS.  For the contingency that we
                     didn't, and stopped at the first newline from the
-                    display string, move back over the glyphs
-                    produced from the string, until we find the
-                    rightmost glyph not from the string.  */
+                    display string, reset top_x to the coordinate of
+                    the rightmost glyph not from the string.  */
                  if (it3_moved
                      && newline_in_string
                      && IT_CHARPOS (it3) != charpos && EQ (it3.object, string))
-                   {
-                     struct glyph *g = it3.glyph_row->glyphs[TEXT_AREA]
-                                       + it3.glyph_row->used[TEXT_AREA];
-
-                     while (EQ ((g - 1)->object, string))
-                       {
-                         --g;
-                         top_x -= g->pixel_width;
-                       }
-                     eassert (g < it3.glyph_row->glyphs[TEXT_AREA]
-                                   + it3.glyph_row->used[TEXT_AREA]);
-                   }
+                   top_x = top_x_before_string;
                }
            }
 
@@ -11755,9 +11751,10 @@ resize_mini_window (struct window *w, bool exact_p)
     return false;
 
   /* By default, start display at the beginning.  */
-  set_marker_both (w->start, w->contents,
-                  BUF_BEGV (XBUFFER (w->contents)),
-                  BUF_BEGV_BYTE (XBUFFER (w->contents)));
+  if (redisplay_adhoc_scroll_in_resize_mini_windows)
+    set_marker_both (w->start, w->contents,
+                    BUF_BEGV (XBUFFER (w->contents)),
+                    BUF_BEGV_BYTE (XBUFFER (w->contents)));
 
   /* Nil means don't try to resize.  */
   if ((NILP (Vresize_mini_windows)
@@ -11816,27 +11813,32 @@ resize_mini_window (struct window *w, bool exact_p)
       if (height > max_height)
        {
          height = (max_height / unit) * unit;
-         init_iterator (&it, w, ZV, ZV_BYTE, NULL, DEFAULT_FACE_ID);
-         move_it_vertically_backward (&it, height - unit);
-         /* The following move is usually a no-op when the stuff
-            displayed in the mini-window comes entirely from buffer
-            text, but it is needed when some of it comes from overlay
-            strings, especially when there's an after-string at ZV.
-            This happens with some completion packages, like
-            icomplete, ido-vertical, etc.  With those packages, if we
-            don't force w->start to be at the beginning of a screen
-            line, important parts of the stuff in the mini-window,
-            such as user prompt, will be hidden from view.  */
-         move_it_by_lines (&it, 0);
-         start = it.current.pos;
-         /* Prevent redisplay_window from recentering, and thus from
-            overriding the window-start point we computed here.  */
-         w->start_at_line_beg = false;
+         if (redisplay_adhoc_scroll_in_resize_mini_windows)
+           {
+             init_iterator (&it, w, ZV, ZV_BYTE, NULL, DEFAULT_FACE_ID);
+             move_it_vertically_backward (&it, height - unit);
+              /* The following move is usually a no-op when the stuff
+                 displayed in the mini-window comes entirely from buffer
+                 text, but it is needed when some of it comes from overlay
+                 strings, especially when there's an after-string at ZV.
+                 This happens with some completion packages, like
+                 icomplete, ido-vertical, etc.  With those packages, if we
+                 don't force w->start to be at the beginning of a screen
+                 line, important parts of the stuff in the mini-window,
+                 such as user prompt, will be hidden from view.  */
+              move_it_by_lines (&it, 0);
+              start = it.current.pos;
+              /* Prevent redisplay_window from recentering, and thus from
+                 overriding the window-start point we computed here.  */
+              w->start_at_line_beg = false;
+              SET_MARKER_FROM_TEXT_POS (w->start, start);
+            }
        }
       else
-       SET_TEXT_POS (start, BEGV, BEGV_BYTE);
-
-      SET_MARKER_FROM_TEXT_POS (w->start, start);
+       {
+         SET_TEXT_POS (start, BEGV, BEGV_BYTE);
+          SET_MARKER_FROM_TEXT_POS (w->start, start);
+        }
 
       if (EQ (Vresize_mini_windows, Qgrow_only))
        {
@@ -35521,6 +35523,14 @@ The initial frame is not displayed anywhere, so 
skipping it is
 best except in special circumstances such as running redisplay tests
 in batch mode.   */);
   redisplay_skip_initial_frame = true;
+
+  DEFVAR_BOOL ("redisplay-adhoc-scroll-in-resize-mini-windows",
+               redisplay_adhoc_scroll_in_resize_mini_windows,
+    doc: /* If nil always use normal scrolling in minibuffer windows.
+Otherwise, use custom-tailored code after resizing minibuffer windows to try
+and display the most important part of the minibuffer.   */);
+  /* See bug#43519 for some discussion around this.  */
+  redisplay_adhoc_scroll_in_resize_mini_windows = true;
 }
 
 
diff --git a/src/xterm.c b/src/xterm.c
index 0d2452d..3de0d2e 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -8383,10 +8383,6 @@ handle_one_xevent (struct x_display_info *dpyinfo,
               inev.ie.kind = DEICONIFY_EVENT;
               XSETFRAME (inev.ie.frame_or_window, f);
             }
-          else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list)))
-            /* Force a redisplay sooner or later to update the
-              frame titles in case this is the second frame.  */
-            record_asynch_buffer_change ();
         }
       goto OTHER;
 
diff --git a/test/README b/test/README
index d0da89d..3365f18 100644
--- a/test/README
+++ b/test/README
@@ -113,7 +113,8 @@ $EMACS_HYDRA_CI indicates the hydra environment, and 
$EMACS_EMBA_CI
 indicates the emba environment, respectively.
 
 
-(Also, see etc/compilation.txt for compilation mode font lock tests.)
+(Also, see etc/compilation.txt for compilation mode font lock tests
+and etc/grep.txt for grep mode font lock tests.)
 
 
 This file is part of GNU Emacs.
diff --git a/test/lisp/abbrev-tests.el b/test/lisp/abbrev-tests.el
index aaf1d4a..288ea1a 100644
--- a/test/lisp/abbrev-tests.el
+++ b/test/lisp/abbrev-tests.el
@@ -69,8 +69,9 @@
     (define-abbrev ert-test-abbrevs "sys" "system abbrev" nil :system t)
     (should (equal (mapcar #'symbol-name (abbrev--table-symbols 
'ert-test-abbrevs))
                    '("a-e-t")))
-    (should (equal (mapcar #'symbol-name (abbrev--table-symbols 
'ert-test-abbrevs t))
-                   '("a-e-t" "sys")))))
+    (let ((syms (abbrev--table-symbols 'ert-test-abbrevs t)))
+      (should (equal (sort (mapcar #'symbol-name syms) #'string<)
+                     '("a-e-t" "sys"))))))
 
 (ert-deftest abbrev-table-get-put-test ()
   (let ((table (make-abbrev-table)))
diff --git a/test/lisp/allout-tests.el b/test/lisp/allout-tests.el
index f7cd6db..c979d08 100644
--- a/test/lisp/allout-tests.el
+++ b/test/lisp/allout-tests.el
@@ -74,7 +74,7 @@
   "Ensure that prior local value is resumed."
   (with-temp-buffer
     (allout-tests-obliterate-variable 'allout-tests-locally-true)
-    (set (make-local-variable 'allout-tests-locally-true) t)
+    (setq-local allout-tests-locally-true t)
     (cl-assert (not (default-boundp 'allout-tests-locally-true))
                nil (concat "Test setup mistake -- variable supposed to"
                            " not have global binding, but it does."))
@@ -98,7 +98,7 @@
     (allout-tests-obliterate-variable 'allout-tests-globally-true)
     (setq allout-tests-globally-true t)
     (allout-tests-obliterate-variable 'allout-tests-locally-true)
-    (set (make-local-variable 'allout-tests-locally-true) t)
+    (setq-local allout-tests-locally-true t)
     (allout-add-resumptions '(allout-tests-globally-unbound t)
                             '(allout-tests-globally-true nil)
                             '(allout-tests-locally-true nil))
@@ -135,7 +135,7 @@
     (allout-tests-obliterate-variable 'allout-tests-globally-true)
     (setq allout-tests-globally-true t)
     (allout-tests-obliterate-variable 'allout-tests-locally-true)
-    (set (make-local-variable 'allout-tests-locally-true) t)
+    (setq-local allout-tests-locally-true t)
     (allout-add-resumptions '(allout-tests-globally-unbound t)
                             '(allout-tests-globally-true nil)
                             '(allout-tests-locally-true nil))
diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el 
b/test/lisp/emacs-lisp/bytecomp-tests.el
index 8fa4d27..c2a3e3b 100644
--- a/test/lisp/emacs-lisp/bytecomp-tests.el
+++ b/test/lisp/emacs-lisp/bytecomp-tests.el
@@ -947,6 +947,75 @@ literals (Bug#20852)."
    '((suspicious set-buffer))
    "Warning: Use .with-current-buffer. rather than"))
 
+(ert-deftest bytecomp-tests--not-writable-directory ()
+  "Test that byte compilation works if the output directory isn't
+writable (Bug#44631)."
+  (let ((directory (make-temp-file "bytecomp-tests-" :directory)))
+    (unwind-protect
+        (let* ((input-file (expand-file-name "test.el" directory))
+               (output-file (expand-file-name "test.elc" directory))
+               (byte-compile-dest-file-function
+                (lambda (_) output-file))
+               (byte-compile-error-on-warn t))
+          (write-region "" nil input-file nil nil nil 'excl)
+          (write-region "" nil output-file nil nil nil 'excl)
+          (set-file-modes input-file #o400)
+          (set-file-modes output-file #o200)
+          (set-file-modes directory #o500)
+          (should (byte-compile-file input-file))
+          (should (file-regular-p output-file))
+          (should (cl-plusp (file-attribute-size
+                             (file-attributes output-file)))))
+      (with-demoted-errors "Error cleaning up directory: %s"
+        (set-file-modes directory #o700)
+        (delete-directory directory :recursive)))))
+
+(ert-deftest bytecomp-tests--dest-mountpoint ()
+  "Test that byte compilation works if the destination file is a
+mountpoint (Bug#44631)."
+  (let ((bwrap (executable-find "bwrap"))
+        (emacs (expand-file-name invocation-name invocation-directory)))
+    (skip-unless bwrap)
+    (skip-unless (file-executable-p bwrap))
+    (skip-unless (not (file-remote-p bwrap)))
+    (skip-unless (file-executable-p emacs))
+    (skip-unless (not (file-remote-p emacs)))
+    (let ((directory (make-temp-file "bytecomp-tests-" :directory)))
+      (unwind-protect
+          (let* ((input-file (expand-file-name "test.el" directory))
+                 (output-file (expand-file-name "test.elc" directory))
+                 (unquoted-file (file-name-unquote output-file))
+                 (byte-compile-dest-file-function
+                  (lambda (_) output-file))
+                 (byte-compile-error-on-warn t))
+            (should-not (file-remote-p input-file))
+            (should-not (file-remote-p output-file))
+            (write-region "" nil input-file nil nil nil 'excl)
+            (write-region "" nil output-file nil nil nil 'excl)
+            (set-file-modes input-file #o400)
+            (set-file-modes output-file #o200)
+            (set-file-modes directory #o500)
+            (with-temp-buffer
+              (let ((status (call-process
+                             bwrap nil t nil
+                             "--ro-bind" "/" "/"
+                             "--bind" unquoted-file unquoted-file
+                             emacs "--quick" "--batch" "--load=bytecomp"
+                             (format "--eval=%S"
+                                     `(setq byte-compile-dest-file-function
+                                            (lambda (_) ,output-file)
+                                            byte-compile-error-on-warn t))
+                             "--funcall=batch-byte-compile" input-file)))
+                (unless (eql status 0)
+                  (ert-fail `((status . ,status)
+                              (output . ,(buffer-string)))))))
+            (should (file-regular-p output-file))
+            (should (cl-plusp (file-attribute-size
+                               (file-attributes output-file)))))
+        (with-demoted-errors "Error cleaning up directory: %s"
+          (set-file-modes directory #o700)
+          (delete-directory directory :recursive))))))
+
 ;; Local Variables:
 ;; no-byte-compile: t
 ;; End:
diff --git a/test/lisp/emacs-lisp/edebug-tests.el 
b/test/lisp/emacs-lisp/edebug-tests.el
index 8aae26a..2c340c4 100644
--- a/test/lisp/emacs-lisp/edebug-tests.el
+++ b/test/lisp/emacs-lisp/edebug-tests.el
@@ -97,7 +97,10 @@ back to the top level.")
 
               ;; sit-on interferes with keyboard macros.
               (edebug-sit-on-break nil)
-              (edebug-continue-kbd-macro t))
+              (edebug-continue-kbd-macro t)
+
+              ;; don't print backtraces, otherwise error messages don't match
+              (backtrace-on-error-noninteractive nil))
      ,@body))
 
 (defmacro edebug-tests-with-normal-env (&rest body)
diff --git a/test/lisp/emacs-lisp/ert-tests.el 
b/test/lisp/emacs-lisp/ert-tests.el
index 1f54c8d..a0c56be 100644
--- a/test/lisp/emacs-lisp/ert-tests.el
+++ b/test/lisp/emacs-lisp/ert-tests.el
@@ -806,6 +806,16 @@ This macro is used to test if macroexpansion in `should' 
works."
   :expected-result :failed  ;; FIXME!  Bug#11218
   (should-not (with-demoted-errors (error "Foo"))))
 
+(ert-deftest ert-test-fail-inside-should ()
+  "Check that `ert-fail' inside `should' works correctly."
+  (let ((result (ert-run-test
+                 (make-ert-test
+                  :name 'test-1
+                  :body (lambda () (should (integerp (ert-fail "Boo"))))))))
+    (should (ert-test-failed-p result))
+    (should (equal (ert-test-failed-condition result)
+                   '(ert-test-failed ("Boo"))))))
+
 
 (provide 'ert-tests)
 
diff --git a/test/lisp/emacs-lisp/faceup-resources/faceup-test-mode.el 
b/test/lisp/emacs-lisp/faceup-resources/faceup-test-mode.el
index c77f2dc..6e9d50f 100644
--- a/test/lisp/emacs-lisp/faceup-resources/faceup-test-mode.el
+++ b/test/lisp/emacs-lisp/faceup-resources/faceup-test-mode.el
@@ -67,8 +67,8 @@ If `prog-mode' is defined, inherit from it."
 
 (faceup-test-define-prog-mode faceup-test-mode "faceup-test"
   "Dummy major mode for testing `faceup', a test system for font-lock."
-  (set (make-local-variable 'syntax-propertize-function)
-       #'faceup-test-syntax-propertize)
+  (setq-local syntax-propertize-function
+              #'faceup-test-syntax-propertize)
   (setq font-lock-defaults '(faceup-test-font-lock-keywords nil)))
 
 (provide 'faceup-test-mode)
diff --git a/test/lisp/emacs-lisp/gv-tests.el b/test/lisp/emacs-lisp/gv-tests.el
index 29e4273..8fc6b51 100644
--- a/test/lisp/emacs-lisp/gv-tests.el
+++ b/test/lisp/emacs-lisp/gv-tests.el
@@ -83,7 +83,10 @@
     (with-temp-buffer
       (call-process (concat invocation-directory invocation-name)
                     nil '(t t) nil
-                    "-Q" "-batch" "--eval" (prin1-to-string 
`(byte-compile-file ,el))
+                    "-Q" "-batch"
+                    "--eval" (prin1-to-string
+                              `(let ((backtrace-on-error-noninteractive nil))
+                                 (byte-compile-file ,el)))
                     "-l" elc)
       (should (equal (buffer-string)
                      "Symbol's function definition is void: \\(setf\\ 
gv-test-foo\\)\n")))))
@@ -133,8 +136,10 @@
                     "-Q" "-batch" "--eval" (prin1-to-string 
`(byte-compile-file ,el))
                     "-l" elc
                     "--eval"
-                    (prin1-to-string '(progn (setf (gv-test-foo gv-test-pair) 
99)
-                                             (message "%d" (car 
gv-test-pair)))))
+                    (prin1-to-string
+                     '(let ((backtrace-on-error-noninteractive nil))
+                        (setf (gv-test-foo gv-test-pair) 99)
+                        (message "%d" (car gv-test-pair)))))
       (should (string-match
                "\\`Symbol.s function definition is void: \\\\(setf\\\\ 
gv-test-foo\\\\)\n\\'"
                (buffer-string))))))
diff --git a/test/lisp/emacs-lisp/memory-report-tests.el 
b/test/lisp/emacs-lisp/memory-report-tests.el
new file mode 100644
index 0000000..b67ec6c
--- /dev/null
+++ b/test/lisp/emacs-lisp/memory-report-tests.el
@@ -0,0 +1,57 @@
+;;; memory-report-tests.el --- tests for memory-report.el -*- lexical-binding: 
t -*-
+
+;; Copyright (C) 2020 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
+
+(require 'ert)
+(require 'memory-report)
+
+(defun setup-memory-report-tests ()
+  ;; Set the sizes on things based on a 64-bit architecture.  (We're
+  ;; hard-coding this to be able to write simple tests that'll work on
+  ;; all architectures.)
+  (memory-report--set-size
+   '((conses 16 499173 99889)
+     (symbols 48 22244 3)
+     (strings 32 92719 4559)
+     (string-bytes 1 40402011)
+     (vectors 16 31919)
+     (vector-slots 8 385148 149240)
+     (floats 8 434 4519)
+     (intervals 56 24499 997)
+     (buffers 984 33))))
+
+(ert-deftest memory-report-sizes ()
+  (setup-memory-report-tests)
+  (should (equal (memory-report-object-size (cons nil nil)) 16))
+  (should (equal (memory-report-object-size (cons 1 2)) 16))
+
+  (should (equal (memory-report-object-size (list 1 2)) 32))
+  (should (equal (memory-report-object-size (list 1)) 16))
+
+  (should (equal (memory-report-object-size (list 'foo)) 16))
+
+  (should (equal (memory-report-object-size (vector 1 2 3 4)) 80))
+
+  (should (equal (memory-report-object-size "") 32))
+  (should (equal (memory-report-object-size "a") 33))
+  (should (equal (memory-report-object-size (propertize "a" 'face 'foo))
+                 81)))
+
+(provide 'memory-report-tests)
+
+;;; memory-report-tests.el ends here
diff --git a/test/lisp/epg-tests.el b/test/lisp/epg-tests.el
index c9c92f5..87d19e8 100644
--- a/test/lisp/epg-tests.el
+++ b/test/lisp/epg-tests.el
@@ -96,8 +96,7 @@
                  context
                   (ert-resource-file "seckey.asc")))
           (with-temp-buffer
-            (make-local-variable 'epg-tests-context)
-            (setq epg-tests-context context)
+             (setq-local epg-tests-context context)
             ,@body))
        (when (file-directory-p epg-tests-home-directory)
         (delete-directory epg-tests-home-directory t)))))
diff --git a/test/lisp/filenotify-tests.el b/test/lisp/filenotify-tests.el
index 268c318..25017dd 100644
--- a/test/lisp/filenotify-tests.el
+++ b/test/lisp/filenotify-tests.el
@@ -108,11 +108,8 @@ There are different timeouts for local and remote file 
notification libraries."
     ;; gio/gpollfilemonitor.c declares POLL_TIME_SECS 5.  So we must
     ;; wait at least this time in the GPollFileMonitor case.  A
     ;; similar timeout seems to be needed in the GFamFileMonitor case,
-    ;; at least on Cygwin.
-    ((and (string-equal (file-notify--test-library) "gfilenotify")
-          (memq (file-notify--test-monitor)
-                '(GFamFileMonitor GPollFileMonitor)))
-     7)
+    ;; at least on cygwin.
+    ((memq (file-notify--test-monitor) '(GFamFileMonitor GPollFileMonitor)) 7)
     ((string-equal (file-notify--test-library) "gvfs-monitor-dir.exe") 1)
     ((file-remote-p temporary-file-directory) 0.1)
     (t 0.01))))
@@ -264,13 +261,19 @@ This returns only for the local case and gfilenotify; 
otherwise it is nil.
   ;; We cache the result, because after `file-notify-rm-watch',
   ;; `gfile-monitor-name' does not return a proper result anymore.
   ;; But we still need this information.
-  (unless (file-remote-p temporary-file-directory)
-    (or (cdr (assq file-notify--test-desc file-notify--test-monitors))
-        (when (functionp 'gfile-monitor-name)
-          (add-to-list 'file-notify--test-monitors
-                       (cons file-notify--test-desc
-                             (gfile-monitor-name file-notify--test-desc)))
-          (cdr (assq file-notify--test-desc file-notify--test-monitors))))))
+  ;; So far, we know the monitors GFamFileMonitor, GFenFileMonitor,
+  ;; GInotifyFileMonitor, GKqueueFileMonitor and GPollFileMonitor.
+  (or (cdr (assq file-notify--test-desc file-notify--test-monitors))
+      (progn
+       (add-to-list
+        'file-notify--test-monitors
+        (cons file-notify--test-desc
+              (if (file-remote-p temporary-file-directory)
+                  (tramp-get-connection-property
+                   file-notify--test-desc "gio-file-monitor" nil)
+                (and (functionp 'gfile-monitor-name)
+                     (gfile-monitor-name file-notify--test-desc)))))
+       (cdr (assq file-notify--test-desc file-notify--test-monitors)))))
 
 (defmacro file-notify--deftest-remote (test docstring &optional unstable)
   "Define ert `TEST-remote' for remote files.
@@ -457,7 +460,7 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'."
 
   (unwind-protect
       ;; Check, that removing watch descriptors out of order do not
-      ;; harm.  This fails on Cygwin because of timing issues unless a
+      ;; harm.  This fails on cygwin because of timing issues unless a
       ;; long `sit-for' is added before the call to
       ;; `file-notify--test-read-event'.
       (unless (eq system-type 'cygwin)
@@ -631,13 +634,15 @@ delivered."
             (cond
              ;; gvfs-monitor-dir on cygwin does not detect the
              ;; `created' event reliably.
-            ((string-equal
-              (file-notify--test-library) "gvfs-monitor-dir.exe")
+            ((string-equal (file-notify--test-library) "gvfs-monitor-dir.exe")
              '((deleted stopped)
                (created deleted stopped)))
              ;; cygwin does not raise a `changed' event.
              ((eq system-type 'cygwin)
               '(created deleted stopped))
+            ;; GKqueueFileMonitor does not report the `changed' event.
+            ((equal (file-notify--test-monitor) 'GKqueueFileMonitor)
+             '(created deleted stopped))
              (t '(created changed deleted stopped)))
           (write-region
            "another text" nil file-notify--test-tmpfile nil 'no-message)
@@ -668,6 +673,9 @@ delivered."
             ((string-equal (file-notify--test-library) "gvfs-monitor-dir.exe")
              '((deleted stopped)
                (changed deleted stopped)))
+            ;; GKqueueFileMonitor does not report the `changed' event.
+            ((equal (file-notify--test-monitor) 'GKqueueFileMonitor)
+             '(deleted stopped))
             ;; There could be one or two `changed' events.
             (t '((changed deleted stopped)
                  (changed changed deleted stopped))))
@@ -718,6 +726,9 @@ delivered."
              '(created deleted stopped))
             ((string-equal (file-notify--test-library) "kqueue")
              '(created changed deleted stopped))
+            ;; GKqueueFileMonitor does not report the `changed' event.
+            ((equal (file-notify--test-monitor) 'GKqueueFileMonitor)
+             '(created deleted deleted stopped))
             (t '(created changed deleted deleted stopped)))
          (write-region
           "any text" nil file-notify--test-tmpfile nil 'no-message)
@@ -767,6 +778,9 @@ delivered."
              ;; directory are not detected.
              ((getenv "EMACS_EMBA_CI")
               '(created changed created changed deleted deleted))
+            ;; GKqueueFileMonitor does not report the `changed' event.
+            ((equal (file-notify--test-monitor) 'GKqueueFileMonitor)
+             '(created created deleted deleted deleted stopped))
             (t '(created changed created changed
                  deleted deleted deleted stopped)))
          (write-region
@@ -823,6 +837,9 @@ delivered."
              '(created created deleted deleted stopped))
             ((string-equal (file-notify--test-library) "kqueue")
              '(created changed renamed deleted stopped))
+            ;; GKqueueFileMonitor does not report the `changed' event.
+            ((equal (file-notify--test-monitor) 'GKqueueFileMonitor)
+             '(created renamed deleted deleted stopped))
             (t '(created changed renamed deleted deleted stopped)))
          (write-region
           "any text" nil file-notify--test-tmpfile nil 'no-message)
@@ -859,6 +876,8 @@ delivered."
             ((string-equal (file-notify--test-library) "w32notify")
              '((changed changed)
                (changed changed changed changed)))
+            ;; GKqueueFileMonitor does not report the `attribute-changed' 
event.
+            ((equal (file-notify--test-monitor) 'GKqueueFileMonitor) nil)
             ;; For kqueue and in the remote case, `write-region'
             ;; raises also an `attribute-changed' event.
             ((or (string-equal (file-notify--test-library) "kqueue")
@@ -925,6 +944,10 @@ delivered."
             ;; timeouts.
             (setq file-notify--test-desc auto-revert-notify-watch-descriptor)
 
+           ;; GKqueueFileMonitor does not report the `changed' event.
+           (skip-unless
+            (not (equal (file-notify--test-monitor) 'GKqueueFileMonitor)))
+
            ;; Check, that file notification has been used.
            (should auto-revert-mode)
            (should auto-revert-use-notify)
@@ -956,7 +979,7 @@ delivered."
 
            ;; Modify file.  We wait for two seconds, in order to
            ;; have another timestamp.  One second seems to be too
-            ;; short.  And Cygwin sporadically requires more than two.
+            ;; short.  And cygwin sporadically requires more than two.
             (ert-with-message-capture captured-messages
               (let ((inhibit-message t))
                 (sleep-for (if (eq system-type 'cygwin) 3 2))
@@ -1028,6 +1051,9 @@ delivered."
             ((string-equal (file-notify--test-library) "gvfs-monitor-dir.exe")
              '((deleted stopped)
                (changed deleted stopped)))
+            ;; GKqueueFileMonitor does not report the `changed' event.
+            ((equal (file-notify--test-monitor) 'GKqueueFileMonitor)
+             '(deleted stopped))
             ;; There could be one or two `changed' events.
             (t '((changed deleted stopped)
                  (changed changed deleted stopped))))
@@ -1077,6 +1103,9 @@ delivered."
                '(created deleted stopped))
               ((string-equal (file-notify--test-library) "kqueue")
                '(created changed deleted stopped))
+              ;; GKqueueFileMonitor does not report the `changed' event.
+              ((equal (file-notify--test-monitor) 'GKqueueFileMonitor)
+               '(created deleted deleted stopped))
               (t '(created changed deleted deleted stopped)))
            (write-region
             "any text" nil file-notify--test-tmpfile nil 'no-message)
@@ -1254,9 +1283,12 @@ delivered."
                '(change) #'file-notify--test-event-handler)))
         (should (file-notify-valid-p file-notify--test-desc))
         (file-notify--test-with-actions
-            ;; There could be one or two `changed' events.
-            '((changed)
-              (changed changed))
+           (cond
+            ;; GKqueueFileMonitor does not report the `changed' event.
+            ((equal (file-notify--test-monitor) 'GKqueueFileMonitor) nil)
+             ;; There could be one or two `changed' events.
+            (t '((changed)
+                 (changed changed))))
           ;; There shouldn't be any problem, because the file is kept.
           (with-temp-buffer
             (let ((buffer-file-name file-notify--test-tmpfile)
@@ -1294,6 +1326,9 @@ delivered."
              ;; On cygwin we only get the `changed' event.
              ((eq system-type 'cygwin)
               '(changed))
+            ;; GKqueueFileMonitor does not report the `changed' event.
+            ((equal (file-notify--test-monitor) 'GKqueueFileMonitor)
+             '(renamed created))
              (t '(renamed created changed)))
           ;; The file is renamed when creating a backup.  It shall
           ;; still be watched.
@@ -1391,7 +1426,12 @@ the file watch."
                 (make-list (/ n 2) 'changed)
                 ;; Just the directory monitor.
                 (make-list (/ n 2) 'created)
-                (make-list (/ n 2) 'changed)))
+                (make-list (/ n 2) 'changed))
+              (append
+                '(:random)
+               ;; Just the directory monitor.  GKqueueFileMonitor
+               ;; does not report the `changed' event.
+                (make-list (/ n 2) 'created)))
             (dotimes (i n)
               (file-notify--test-read-event)
               (if (zerop (mod i 2))
diff --git a/test/lisp/net/rcirc-tests.el b/test/lisp/net/rcirc-tests.el
index 285926a..cbd1c2b 100644
--- a/test/lisp/net/rcirc-tests.el
+++ b/test/lisp/net/rcirc-tests.el
@@ -51,4 +51,16 @@
     "MODE #cchan +kl :a:b"
     nil "MODE" '("#cchan" "+kl" "a:b")))
 
+(ert-deftest rcirc-rename-nicks ()
+  (should (equal (rcirc--make-new-nick "foo" 16)
+                 "foo`"))
+  (should (equal (rcirc--make-new-nick "123456789012345" 16)
+                 "123456789012345`"))
+  (should (equal (rcirc--make-new-nick "1234567890123456" 16)
+                 "123456789012345`"))
+  (should (equal (rcirc--make-new-nick "123456789012345`" 16)
+                 "12345678901234``"))
+  (should (equal (rcirc--make-new-nick "123456789012````" 16)
+                 "12345678901`````")))
+
 ;;; rcirc-tests.el ends here
diff --git a/test/lisp/vc/vc-tests.el b/test/lisp/vc/vc-tests.el
index 7b88b8d..a2936cc 100644
--- a/test/lisp/vc/vc-tests.el
+++ b/test/lisp/vc/vc-tests.el
@@ -439,8 +439,9 @@ This checks also `vc-backend' and `vc-responsible-backend'."
            ;; nil: Git Mtn
            ;; "0": Bzr CVS Hg SRC SVN
            ;; "1.1": RCS SCCS
+            ;; "-1": Hg versions before 5 (probably)
             (message "vc-working-revision4 %s" (vc-working-revision tmp-name))
-            (should (member (vc-working-revision tmp-name) '(nil "0" "1.1")))
+            (should (member (vc-working-revision tmp-name) '(nil "0" "1.1" 
"-1")))
 
             ;; TODO: Call `vc-checkin', and check the resulting
             ;; working revision.  None of the return values should be
diff --git a/test/manual/indent/perl.perl b/test/manual/indent/perl.perl
index 853aec4..6ec0430 100755
--- a/test/manual/indent/perl.perl
+++ b/test/manual/indent/perl.perl
@@ -81,3 +81,17 @@ return 'W' if               #/^Not Available on Mobile/m;    
#W=Web only
 # A "y|abc|def|" shouldn't interfere when inside a string!
 $toto = " x \" string\"";
 $toto = " y \" string\"";       # This is not the `y' operator!
+
+
+# Tricky cases from Harald Jörg <haj@posteo.de>
+$_ = "abcabc\n";
+s:abc:def:g;  # FIXME: the initial s is fontified like a label, and indented
+
+s'def'ghi'g;  # The middle ' should not end the quoting.
+s"ghi"ijk"g;  # The middle ' should not end the quoting.
+
+s#ijk#lmn#g;  # This is a regular expression sustitution.
+
+s #lmn#opq#g; # FIXME: this should be a comment starting with "#lmn"
+  /lmn/rst/g; # and this is the actual regular expression
+print;        # prints "rstrst\n"
diff --git a/test/src/casefiddle-tests.el b/test/src/casefiddle-tests.el
index 7abb79e..3eba4cf 100644
--- a/test/src/casefiddle-tests.el
+++ b/test/src/casefiddle-tests.el
@@ -247,7 +247,8 @@
   ;;             input upcase downcase [titlecase]
   (dolist (test '((?a ?A ?a) (?A ?A ?a)
                   (?ł ?Ł ?ł) (?Ł ?Ł ?ł)
-                  (?ß ?ß ?ß) (?ẞ ?ẞ ?ß)
+                  ;; We char-upcase ß to ẞ; see bug #11309.
+                  (?ß ?ẞ ?ß) (?ẞ ?ẞ ?ß)
                   (?ⅷ ?Ⅷ ?ⅷ) (?Ⅷ ?Ⅷ ?ⅷ)
                   (?DŽ ?DŽ ?dž ?Dž) (?Dž ?DŽ ?dž ?Dž) (?dž ?DŽ ?dž ?Dž)))
     (let ((ch (car test))
diff --git a/test/src/data-tests.el b/test/src/data-tests.el
index 1312683..c5fc3ea 100644
--- a/test/src/data-tests.el
+++ b/test/src/data-tests.el
@@ -324,7 +324,7 @@ comparing the subr with a much slower lisp implementation."
 
 (defvar binding-test-some-local 'some)
 (with-current-buffer binding-test-buffer-A
-  (set (make-local-variable 'binding-test-some-local) 'local))
+  (setq-local binding-test-some-local 'local))
 
 (ert-deftest binding-test-manual ()
   "A test case from the elisp manual."
diff --git a/test/src/emacs-module-resources/mod-test.c 
b/test/src/emacs-module-resources/mod-test.c
index f855e9b..30ad352 100644
--- a/test/src/emacs-module-resources/mod-test.c
+++ b/test/src/emacs-module-resources/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 <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -699,6 +700,34 @@ Fmod_test_funcall (emacs_env *env, ptrdiff_t nargs, 
emacs_value *args,
   return env->funcall (env, args[0], nargs - 1, args + 1);
 }
 
+static emacs_value
+Fmod_test_make_string (emacs_env *env, ptrdiff_t nargs,
+                       emacs_value *args, void *data)
+{
+  assert (nargs == 2);
+  intmax_t length_arg = env->extract_integer (env, args[0]);
+  if (env->non_local_exit_check (env) != emacs_funcall_exit_return)
+    return args[0];
+  if (length_arg < 0 || SIZE_MAX < length_arg)
+    {
+      signal_error (env, "Invalid string length");
+      return args[0];
+    }
+  size_t length = (size_t) length_arg;
+  bool multibyte = env->is_not_nil (env, args[1]);
+  char *buffer = length == 0 ? NULL : malloc (length);
+  if (buffer == NULL && length != 0)
+    {
+      memory_full (env);
+      return args[0];
+    }
+  memset (buffer, 'a', length);
+  emacs_value ret = multibyte ? env->make_string (env, buffer, length)
+                              : env->make_unibyte_string (env, buffer, length);
+  free (buffer);
+  return ret;
+}
+
 /* Lisp utilities for easier readability (simple wrappers).  */
 
 /* Provide FEATURE to Emacs.  */
@@ -790,6 +819,7 @@ emacs_module_init (struct emacs_runtime *ert)
   DEFUN ("mod-test-async-pipe", Fmod_test_async_pipe, 1, 1, NULL, NULL);
   DEFUN ("mod-test-funcall", Fmod_test_funcall, 1, emacs_variadic_function,
          NULL, NULL);
+  DEFUN ("mod-test-make-string", Fmod_test_make_string, 2, 2, NULL, NULL);
 
 #undef DEFUN
 
diff --git a/test/src/emacs-module-tests.el b/test/src/emacs-module-tests.el
index 99d4caf..bf26ffb 100644
--- a/test/src/emacs-module-tests.el
+++ b/test/src/emacs-module-tests.el
@@ -30,6 +30,7 @@
 (require 'ert)
 (require 'ert-x)
 (require 'help-fns)
+(require 'subr-x)
 
 (defconst mod-test-emacs
   (expand-file-name invocation-name invocation-directory)
@@ -556,4 +557,23 @@ See Bug#36226."
     (thread-join thread-1)
     (thread-join thread-2)))
 
+(ert-deftest mod-test-make-string/empty ()
+  (dolist (multibyte '(nil t))
+    (ert-info ((format "Multibyte: %s" multibyte))
+      (let ((got (mod-test-make-string 0 multibyte)))
+        (should (stringp got))
+        (should (string-empty-p got))
+        (should (eq (multibyte-string-p got) multibyte))))))
+
+(ert-deftest mod-test-make-string/nonempty ()
+  (dolist (multibyte '(nil t))
+    (ert-info ((format "Multibyte: %s" multibyte))
+      (let ((first (mod-test-make-string 1 multibyte))
+            (second (mod-test-make-string 1 multibyte)))
+        (should (stringp first))
+        (should (eql (length first) 1))
+        (should (eq (multibyte-string-p first) multibyte))
+        (should (string-equal first second))
+        (should-not (eq first second))))))
+
 ;;; emacs-module-tests.el ends here
diff --git a/test/src/eval-tests.el b/test/src/eval-tests.el
index 074f5be..297db81 100644
--- a/test/src/eval-tests.el
+++ b/test/src/eval-tests.el
@@ -27,6 +27,7 @@
 
 (require 'ert)
 (eval-when-compile (require 'cl-lib))
+(require 'subr-x)
 
 (ert-deftest eval-tests--bug24673 ()
   "Check that Bug#24673 has been fixed."
@@ -176,4 +177,53 @@ in Common Lisp).  Instead, make sure substitution in 
backquote
 expressions works for identifiers starting with period."
   (should (equal (let ((.x 'identity)) (eval `(,.x 'ok))) 'ok)))
 
+(ert-deftest eval-tests/backtrace-in-batch-mode ()
+  (let ((emacs (expand-file-name invocation-name invocation-directory)))
+    (skip-unless (file-executable-p emacs))
+    (with-temp-buffer
+      (let ((status (call-process emacs nil t nil
+                                  "--quick" "--batch"
+                                  (concat "--eval="
+                                          (prin1-to-string
+                                           '(progn
+                                              (defun foo () (error "Boo"))
+                                              (foo)))))))
+        (should (natnump status))
+        (should-not (eql status 0)))
+      (goto-char (point-min))
+      (ert-info ((concat "Process output:\n" (buffer-string)))
+        (search-forward "  foo()")
+        (search-forward "  normal-top-level()")))))
+
+(ert-deftest eval-tests/backtrace-in-batch-mode/inhibit ()
+  (let ((emacs (expand-file-name invocation-name invocation-directory)))
+    (skip-unless (file-executable-p emacs))
+    (with-temp-buffer
+      (let ((status (call-process
+                     emacs nil t nil
+                     "--quick" "--batch"
+                     (concat "--eval="
+                             (prin1-to-string
+                              '(progn
+                                 (defun foo () (error "Boo"))
+                                 (let ((backtrace-on-error-noninteractive nil))
+                                   (foo))))))))
+        (should (natnump status))
+        (should-not (eql status 0)))
+      (should (equal (string-trim (buffer-string)) "Boo")))))
+
+(ert-deftest eval-tests/backtrace-in-batch-mode/demoted-errors ()
+  (let ((emacs (expand-file-name invocation-name invocation-directory)))
+    (skip-unless (file-executable-p emacs))
+    (with-temp-buffer
+      (should (eql  0 (call-process emacs nil t nil
+                                    "--quick" "--batch"
+                                    (concat "--eval="
+                                            (prin1-to-string
+                                             '(with-demoted-errors "Error: %S"
+                                                (error "Boo")))))))
+      (goto-char (point-min))
+      (should (equal (string-trim (buffer-string))
+                     "Error: (error \"Boo\")")))))
+
 ;;; eval-tests.el ends here
diff --git a/test/src/fns-tests.el b/test/src/fns-tests.el
index 86b8d65..eaa569e 100644
--- a/test/src/fns-tests.el
+++ b/test/src/fns-tests.el
@@ -983,3 +983,19 @@
   (should (equal (string-search (string-to-multibyte "o\303\270") 
"foo\303\270")
                  2))
   (should (equal (string-search "\303\270" "foo\303\270") 3)))
+
+(ert-deftest object-intervals ()
+  (should (equal (object-intervals (propertize "foo" 'bar 'zot))
+                 '((0 3 (bar zot)))))
+  (should (equal (object-intervals (concat (propertize "foo" 'bar 'zot)
+                                           (propertize "foo" 'gazonk 
"gazonk")))
+                 '((0 3 (bar zot)) (3 6 (gazonk "gazonk")))))
+  (should (equal
+           (with-temp-buffer
+             (insert "foobar")
+             (put-text-property 1 3 'foo 1)
+             (put-text-property 3 6 'bar 2)
+             (put-text-property 2 5 'zot 3)
+             (object-intervals (current-buffer)))
+           '((0 1 (foo 1)) (1 2 (zot 3 foo 1)) (2 4 (zot 3 bar 2))
+             (4 5 (bar 2)) (5 6 nil)))))
diff --git a/test/src/regex-emacs-tests.el b/test/src/regex-emacs-tests.el
index f9372e3..34d4067 100644
--- a/test/src/regex-emacs-tests.el
+++ b/test/src/regex-emacs-tests.el
@@ -803,4 +803,68 @@ This evaluates the TESTS test cases from glibc."
   (should-not (string-match "å" "\xe5"))
   (should-not (string-match "[å]" "\xe5")))
 
+(ert-deftest regexp-case-fold ()
+  "Test case-sensitive and case-insensitive matching."
+  (let ((case-fold-search nil))
+    (should (equal (string-match "aB" "ABaB") 2))
+    (should (equal (string-match "åÄ" "ÅäåäÅÄåÄ") 6))
+    (should (equal (string-match "λΛ" "lΛλλΛ") 3))
+    (should (equal (string-match "шШ" "zШшшШ") 3))
+    (should (equal (string-match "[[:alpha:]]+" ".3aBåÄßλΛшШ中﷽") 2))
+    (should (equal (match-end 0) 12))
+    (should (equal (string-match "[[:alnum:]]+" ".3aBåÄßλΛшШ中﷽") 1))
+    (should (equal (match-end 0) 12))
+    (should (equal (string-match "[[:upper:]]+" ".3aåλшBÄΛШ中﷽") 6))
+    (should (equal (match-end 0) 10))
+    (should (equal (string-match "[[:lower:]]+" ".3BÄΛШaåλш中﷽") 6))
+    (should (equal (match-end 0) 10)))
+  (let ((case-fold-search t))
+    (should (equal (string-match "aB" "ABaB") 0))
+    (should (equal (string-match "åÄ" "ÅäåäÅÄåÄ") 0))
+    (should (equal (string-match "λΛ" "lΛλλΛ") 1))
+    (should (equal (string-match "шШ" "zШшшШ") 1))
+    (should (equal (string-match "[[:alpha:]]+" ".3aBåÄßλΛшШ中﷽") 2))
+    (should (equal (match-end 0) 12))
+    (should (equal (string-match "[[:alnum:]]+" ".3aBåÄßλΛшШ中﷽") 1))
+    (should (equal (match-end 0) 12))
+    (should (equal (string-match "[[:upper:]]+" ".3aåλшBÄΛШ中﷽") 2))
+    (should (equal (match-end 0) 10))
+    (should (equal (string-match "[[:lower:]]+" ".3BÄΛШaåλш中﷽") 2))
+    (should (equal (match-end 0) 10))))
+
+(ert-deftest regexp-eszett ()
+  "Test matching of ß and ẞ."
+  ;; Sanity checks.
+  (should (equal (upcase "ß") "SS"))
+  (should (equal (downcase "ß") "ß"))
+  (should (equal (capitalize "ß") "Ss"))  ; undeutsch...
+  (should (equal (upcase "ẞ") "ẞ"))
+  (should (equal (downcase "ẞ") "ß"))
+  (should (equal (capitalize "ẞ") "ẞ"))
+  ;; ß is a lower-case letter (Ll); ẞ is an upper-case letter (Lu).
+  (let ((case-fold-search nil))
+    (should (equal (string-match "ß" "ß") 0))
+    (should (equal (string-match "ß" "ẞ") nil))
+    (should (equal (string-match "ẞ" "ß") nil))
+    (should (equal (string-match "ẞ" "ẞ") 0))
+    (should (equal (string-match "[[:alpha:]]" "ß") 0))
+    ;; bug#11309
+    (should (equal (string-match "[[:lower:]]" "ß") 0))
+    (should (equal (string-match "[[:upper:]]" "ß") nil))
+    (should (equal (string-match "[[:alpha:]]" "ẞ") 0))
+    (should (equal (string-match "[[:lower:]]" "ẞ") nil))
+    (should (equal (string-match "[[:upper:]]" "ẞ") 0)))
+  (let ((case-fold-search t))
+    (should (equal (string-match "ß" "ß") 0))
+    (should (equal (string-match "ß" "ẞ") 0))
+    (should (equal (string-match "ẞ" "ß") 0))
+    (should (equal (string-match "ẞ" "ẞ") 0))
+    (should (equal (string-match "[[:alpha:]]" "ß") 0))
+    ;; bug#11309
+    (should (equal (string-match "[[:lower:]]" "ß") 0))
+    (should (equal (string-match "[[:upper:]]" "ß") 0))
+    (should (equal (string-match "[[:alpha:]]" "ẞ") 0))
+    (should (equal (string-match "[[:lower:]]" "ẞ") 0))
+    (should (equal (string-match "[[:upper:]]" "ẞ") 0))))
+
 ;;; regex-emacs-tests.el ends here



reply via email to

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