emacs-diffs
[Top][All Lists]
Advanced

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

feature/native-comp 0474fda 1/6: Merge remote-tracking branch 'savannah/


From: Andrea Corallo
Subject: feature/native-comp 0474fda 1/6: Merge remote-tracking branch 'savannah/master' into HEAD
Date: Sat, 12 Dec 2020 10:47:05 -0500 (EST)

branch: feature/native-comp
commit 0474fda62d79cb7eb250f34f19773c87f283c665
Merge: be907b0 4afef61
Author: Andrea Corallo <akrl@sdf.org>
Commit: Andrea Corallo <akrl@sdf.org>

    Merge remote-tracking branch 'savannah/master' into HEAD
---
 .gitlab-ci.yml                                     |   2 +-
 admin/nt/dist-build/build-dep-zips.py              |   1 -
 doc/emacs/maintaining.texi                         |  10 +
 doc/emacs/misc.texi                                |  25 +-
 doc/lispref/backups.texi                           |   6 +-
 doc/lispref/display.texi                           |  44 ++-
 doc/lispref/internals.texi                         |  13 +
 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/gnus.texi                                 |  31 ++-
 etc/NEWS                                           |  97 ++++++-
 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/calendar/calendar.el                          |   2 +-
 lisp/calendar/diary-lib.el                         |  23 +-
 lisp/chistory.el                                   |   2 +-
 lisp/comint.el                                     |  32 ++-
 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                                      |  12 +-
 lisp/doc-view.el                                   |   2 +-
 lisp/ebuff-menu.el                                 |   7 +-
 lisp/edmacro.el                                    |   6 +-
 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                   | 301 +++++++++++++++++++++
 lisp/emacs-lisp/pcase.el                           |   3 +-
 lisp/emacs-lisp/thunk.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-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                                |   8 +-
 lisp/gnus/nnml.el                                  |   4 +-
 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/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                               |  34 ++-
 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/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                       |   7 +-
 lisp/progmodes/etags.el                            |  77 +++---
 lisp/progmodes/fortran.el                          |  43 +--
 lisp/progmodes/gdb-mi.el                           |  39 ++-
 lisp/progmodes/grep.el                             |  35 ++-
 lisp/progmodes/gud.el                              |   8 +-
 lisp/progmodes/hideif.el                           |  16 +-
 lisp/progmodes/inf-lisp.el                         |   9 +-
 lisp/progmodes/meta-mode.el                        |  50 ++--
 lisp/progmodes/project.el                          |  12 +-
 lisp/progmodes/ps-mode.el                          |  26 +-
 lisp/progmodes/python.el                           | 152 +++++------
 lisp/progmodes/sql.el                              |  63 ++---
 lisp/progmodes/tcl.el                              |  64 +++--
 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                                     |  54 ++--
 lisp/skeleton.el                                   |  13 +-
 lisp/speedbar.el                                   |  21 +-
 lisp/startup.el                                    |   4 +-
 lisp/strokes.el                                    |  18 +-
 lisp/subr.el                                       |  65 +++--
 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/vc/ediff-ptch.el                              |   3 +
 lisp/vc/vc-git.el                                  |   2 +-
 lisp/vc/vc-hg.el                                   |  11 +-
 lisp/vc/vc.el                                      |  16 +-
 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.c                                        |  13 +-
 src/eval.c                                         |  11 +-
 src/fileio.c                                       |   7 +-
 src/fns.c                                          |  78 +++++-
 src/frame.c                                        |  12 +-
 src/image.c                                        | 124 +++++++--
 src/lisp.h                                         |  33 +--
 src/nsterm.m                                       |  10 +-
 src/regex-emacs.c                                  |  17 +-
 src/w32gui.h                                       |   1 +
 src/w32term.c                                      |  11 +
 src/window.c                                       |  56 +++-
 src/xdisp.c                                        |  40 ++-
 test/README                                        |   3 +-
 test/lisp/abbrev-tests.el                          |   5 +-
 test/lisp/allout-tests.el                          |   6 +-
 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/src/casefiddle-tests.el                       |   3 +-
 test/src/data-tests.el                             |   2 +-
 test/src/eval-tests.el                             |  17 ++
 test/src/fns-tests.el                              |  16 ++
 test/src/regex-emacs-tests.el                      |  64 +++++
 207 files changed, 2783 insertions(+), 1752 deletions(-)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index e5ebd6a..bc099a7 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-native-bootstrap-speed0:
   # Test a full native bootstrap
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/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..fb24544 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
 
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/gnus.texi b/doc/misc/gnus.texi
index 4aa07ce..cfd3ced 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 <
diff --git a/etc/NEWS b/etc/NEWS
index 6444e21..9bf067f 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -192,8 +192,10 @@ 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.
+** 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
@@ -273,6 +275,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
 
 +++
@@ -285,6 +292,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.
@@ -492,6 +511,19 @@ tags to be considered as well.
 ** Gnus
 
 +++
+*** 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
@@ -1084,6 +1116,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
@@ -1199,6 +1247,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
 
 ---
@@ -1357,8 +1410,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,
@@ -1457,13 +1543,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/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/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..baf99da 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -2419,6 +2419,8 @@ 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)
+  (unless (file-writable-p default-directory)
+    (user-error "Directory %s isn't writeable" default-directory))
   (if (derived-mode-p 'dired-mode)
       (wdired-change-to-wdired-mode)
     (read-only-mode 'toggle)))
@@ -2499,6 +2501,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 +2517,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 +2553,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 +2580,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/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..c88d9f2
--- /dev/null
+++ b/lisp/emacs-lisp/memory-report.el
@@ -0,0 +1,301 @@
+;;; 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" (image-cache-size))))
+
+(provide 'memory-report)
+
+;;; memory-report.el ends here
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/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 a201827..bb37bc6 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.
@@ -2424,9 +2424,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)
@@ -3525,7 +3523,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)))
 
@@ -4497,9 +4495,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))
@@ -6128,6 +6124,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'
@@ -6224,7 +6223,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-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 3c91c3e..0a20a99 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 c8b700e..61693a0 100644
--- a/lisp/gnus/nnimap.el
+++ b/lisp/gnus/nnimap.el
@@ -376,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)))
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/help-fns.el b/lisp/help-fns.el
index d5b8df9..0ed8342 100644
--- a/lisp/help-fns.el
+++ b/lisp/help-fns.el
@@ -1139,8 +1139,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/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 137f085..98537a1 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -3834,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)
@@ -5030,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
@@ -5139,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
@@ -5753,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/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 13bba7f..913f0c1 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'.")
 
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/fortran.el b/lisp/progmodes/fortran.el
index 3a0274c..1142c32 100644
--- a/lisp/progmodes/fortran.el
+++ b/lisp/progmodes/fortran.el
@@ -1218,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 279a70b..134c2fc 100644
--- a/lisp/progmodes/gud.el
+++ b/lisp/progmodes/gud.el
@@ -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.
@@ -2566,7 +2566,11 @@ 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)
   (setq-local gud-last-frame nil)
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/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/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/project.el b/lisp/progmodes/project.el
index 449eadc..98ad414 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -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/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/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/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 2fd9455..cd55d66 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
@@ -1328,6 +1334,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)))
@@ -1360,8 +1368,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
@@ -1372,9 +1382,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)
@@ -1676,9 +1688,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 3c4f756..6059c23 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
@@ -7202,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
@@ -7431,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
@@ -8825,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))
@@ -9288,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)
@@ -9307,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 f9de7fa..77fd1dd 100644
--- a/lisp/startup.el
+++ b/lisp/startup.el
@@ -641,7 +641,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 "~/")))))
@@ -2007,7 +2007,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 9f78471..8f27cee 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -2750,20 +2750,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)
 
@@ -2807,6 +2809,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)))
@@ -2861,28 +2865,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)
 
@@ -2960,6 +2967,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))))
@@ -5905,4 +5914,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/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/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..b3b0583 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
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 fea3986..544b20d 100644
--- a/src/data.c
+++ b/src/data.c
@@ -1700,8 +1700,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.c b/src/emacs.c
index afcdb66..afdfcad 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -2398,10 +2398,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.  */
@@ -2927,6 +2930,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 fb747c5..2b31b91 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1799,7 +1799,8 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object 
data, bool keyboard_quit)
      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)
+      && (NILP (clause) || EQ (h->tag_or_ch, Qerror)) && noninteractive
+      && backtrace_on_error_noninteractive)
     {
       ptrdiff_t count = SPECPDL_INDEX ();
       specbind (Vdebugger, Qdebug);
@@ -4344,6 +4345,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..f770929 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -4525,18 +4525,40 @@ 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)
+  if (len < 16)
     {
-      c = *p++;
-      hash = sxhash_combine (hash, c);
+      char const *p = ptr;
+      char const *end = p + len;
+      EMACS_UINT hash = len;
+
+      while (p < end)
+        {
+          unsigned char c = *p++;
+          hash = sxhash_combine (hash, c);
+        }
+
+      return hash;
     }
+  else
+    {
+      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 = max (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)
+        {
+          EMACS_UINT c = *p;
+          p += step;
+          hash = sxhash_combine (hash, c);
+        }
 
-  return hash;
+      return hash;
+    }
 }
 
 /* Return a hash for string PTR which has length LEN.  The hash
@@ -5418,7 +5440,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 +5574,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 +5649,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 17ec455..164c05c 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -3577,7 +3577,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);
@@ -3600,7 +3602,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);
@@ -3616,7 +3620,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 5eb4132..6b85ab7 100644
--- a/src/image.c
+++ b/src/image.c
@@ -1592,17 +1592,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 *
@@ -1630,7 +1619,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;
@@ -1644,12 +1633,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
@@ -1802,6 +1792,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,
@@ -9453,6 +9492,7 @@ enum svg_keyword_index
   SVG_TYPE,
   SVG_DATA,
   SVG_FILE,
+  SVG_BASE_URI,
   SVG_ASCENT,
   SVG_MARGIN,
   SVG_RELIEF,
@@ -9472,6 +9512,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},
@@ -9544,6 +9585,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 *,
@@ -9600,6 +9644,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);
@@ -9655,6 +9700,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
@@ -9688,6 +9734,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  */
 
@@ -9698,10 +9745,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;
@@ -9721,15 +9769,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))
@@ -9737,10 +9786,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;
@@ -9748,11 +9797,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)
@@ -9826,6 +9872,9 @@ 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);
+  rsvg_handle_set_dpi_x_y (rsvg_handle, FRAME_DISPLAY_INFO (f)->resx,
+                           FRAME_DISPLAY_INFO (f)->resy);
+
   if (base_file)
     g_object_unref (base_file);
   g_object_unref (input_stream);
@@ -9837,7 +9886,11 @@ svg_load_image (struct frame *f, struct image *img, char 
*contents,
   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)
@@ -9860,6 +9913,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,
@@ -9869,19 +9923,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)
@@ -9990,6 +10044,10 @@ 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);
+
+  rsvg_handle_set_dpi_x_y (rsvg_handle, FRAME_DISPLAY_INFO (f)->resx,
+                           FRAME_DISPLAY_INFO (f)->resy);
+
   if (base_file)
     g_object_unref (base_file);
   g_object_unref (input_stream);
@@ -10001,7 +10059,11 @@ svg_load_image (struct frame *f, struct image *img, 
char *contents,
   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)
@@ -10684,6 +10746,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.  */
@@ -10713,6 +10776,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/lisp.h b/src/lisp.h
index a5a90cc..5900b8d 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -1900,16 +1900,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
   {
@@ -1929,11 +1930,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;
@@ -1942,8 +1943,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)];
@@ -2018,7 +2019,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)
 {
@@ -2028,7 +2029,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/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/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..dc5cd1f 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.  */
 
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 ed1d476..689b87d 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;
                }
            }
 
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/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/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/eval-tests.el b/test/src/eval-tests.el
index 4125573..297db81 100644
--- a/test/src/eval-tests.el
+++ b/test/src/eval-tests.el
@@ -195,6 +195,23 @@ expressions works for identifiers starting with period."
         (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))
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]