emacs-diffs
[Top][All Lists]
Advanced

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

[Emacs-diffs] master 5ee5895 2/2: Merge commit '890440a44cd5f4f09742f521


From: Stephen Leake
Subject: [Emacs-diffs] master 5ee5895 2/2: Merge commit '890440a44cd5f4f09742f521c7783785d114fffc'
Date: Sun, 14 Apr 2019 12:25:05 -0400 (EDT)

branch: master
commit 5ee5895f9b7b829783bc0f217095748076cc77e9
Merge: ca449fb 890440a
Author: Stephen Leake <address@hidden>
Commit: Stephen Leake <address@hidden>

    Merge commit '890440a44cd5f4f09742f521c7783785d114fffc'
---
 CONTRIBUTE                            |   6 +
 ChangeLog.3                           | 147 ++++++++++-
 build-aux/config.sub                  |   4 +-
 doc/lispref/minibuf.texi              |   3 +-
 doc/lispref/text.texi                 | 127 ++++++----
 doc/misc/nxml-mode.texi               |   2 +-
 doc/misc/texinfo.tex                  | 448 ++++++++++++++++++++++------------
 doc/misc/tramp.texi                   |  25 +-
 etc/AUTHORS                           |  24 +-
 etc/HISTORY                           |   2 +
 etc/NEWS                              |  12 +
 etc/NEWS.1-17                         |   4 +-
 lib/_Noreturn.h                       |  16 ++
 lib/gnulib.mk.in                      |   1 +
 lisp/align.el                         |   2 +-
 lisp/cedet/srecode/srt-mode.el        |   2 +-
 lisp/emacs-lisp/byte-opt.el           |   3 +-
 lisp/emacs-lisp/copyright.el          |   2 +-
 lisp/erc/erc-backend.el               |   2 +-
 lisp/erc/erc-desktop-notifications.el |  22 +-
 lisp/erc/erc-goodies.el               |   2 +-
 lisp/gnus/gnus-group.el               | 119 ++++-----
 lisp/help-fns.el                      | 414 ++++++++++++++++++-------------
 lisp/mail/mail-extr.el                |   2 +-
 lisp/net/tramp-adb.el                 |   2 +-
 lisp/net/tramp-sh.el                  |  10 +-
 lisp/org/org-table.el                 |   4 +-
 lisp/progmodes/cc-engine.el           |  45 +++-
 lisp/progmodes/cc-langs.el            |  13 +
 lisp/progmodes/idlwave.el             |   4 +-
 lisp/progmodes/verilog-mode.el        |   8 +-
 lisp/progmodes/xref.el                |  19 +-
 lisp/simple.el                        |  19 +-
 lisp/subr.el                          |   5 +
 lisp/url/url-http.el                  |   9 -
 lisp/url/url-misc.el                  |   2 +-
 lisp/url/url-util.el                  |   2 -
 lisp/vc/diff-mode.el                  |  42 ++--
 lisp/vc/log-edit.el                   |   4 +-
 src/emacs.c                           |   9 +-
 src/json.c                            | 116 +++++++--
 src/minibuf.c                         |   3 +-
 src/xfns.c                            |   2 +-
 src/xterm.c                           |   9 +-
 test/lisp/filenotify-tests.el         |   3 +-
 test/lisp/net/tramp-tests.el          |   2 +-
 test/lisp/progmodes/python-tests.el   |   2 +-
 test/lisp/subr-tests.el               |  18 --
 test/src/fns-tests.el                 |  18 ++
 test/src/json-tests.el                |   8 +
 50 files changed, 1180 insertions(+), 589 deletions(-)

diff --git a/CONTRIBUTE b/CONTRIBUTE
index e8bb95d..a5433e3 100644
--- a/CONTRIBUTE
+++ b/CONTRIBUTE
@@ -54,6 +54,12 @@ packages the patch's commit message and changes.  To send 
just one
 such patch without additional remarks, you can use a command like
 'git send-email address@hidden 0001-DESCRIPTION.patch'.
 
+Once the cumulative amount of your submissions exceeds about 15 lines
+of non-trivial changes, we will need you to assign to the FSF the
+copyright for your contributions.  Ask on address@hidden, and we
+will send you the necessary form together with the instructions to
+fill and email it, in order to start this legal paperwork.
+
 ** Issue tracker (a.k.a. "bug tracker")
 
 The Emacs issue tracker at https://debbugs.gnu.org lets you view bug
diff --git a/ChangeLog.3 b/ChangeLog.3
index 235c8bb..e7f4d86 100644
--- a/ChangeLog.3
+++ b/ChangeLog.3
@@ -1,3 +1,148 @@
+2019-04-11  Eli Zaretskii  <address@hidden>
+
+       Improve documentation of 'read-command'
+
+       * src/minibuf.c (Fread_command): Document the return value
+       when DEFAULT-VALUE is nil and the user enters nothing.
+       * doc/lispref/minibuf.texi (High-Level Completion): Document
+       the printed representation of a symbol whose name is empty.
+       (Bug#3522)
+
+2019-04-11  Eli Zaretskii  <address@hidden>
+
+       Fix an outdated URL in a comment
+
+       * src/emacs.c: Fix reference to Cocoa CoreFoundation Release
+       Notes.  (Bug#35225)
+
+2019-04-11  Basil L. Contovounesios  <address@hidden>
+
+       Backport: Fix comment-empty-lines docstring (bug#35152)
+
+       * lisp/newcomment.el (comment-empty-lines): Consistently use US
+       commas in docstring.  Fix indentation of and typo in custom :type.
+
+       (cherry picked from commit 690c678fb6c1fb5b2f828f9bb90782bd0b01c399)
+
+2019-04-11  Alex Branham  <address@hidden>
+
+       Backport: Update documentation for indent-relative functions
+
+       * lisp/indent.el (indent-relative): Document what happens when there
+         is no previous nonblank line.
+       * doc/lispref/text.texi (Relative Indent): Document
+         indent-relative-first-indent-point instead of obsolete
+         indent-relative-maybe. Fix documentation of which argument from
+         'indent-relative' is used.
+
+       Bug#34858
+
+       (cherry picked from commit 10cd65878c741d2a22a1f2c36c54fcad4e516f72)
+
+2019-04-11  Noam Postavsky  <address@hidden>
+
+       Update nxml-mode.texi: completion now gives xmlns="-!-"
+
+       * doc/misc/nxml-mode.texi (Completion): As of 2016-01-16 "* lisp/nxml:
+       Use standard completion; it also works for company-mode", completing
+       an attribute when there is only one candidate inserts both quotes.
+       Update the example accordingly.
+
+2019-04-10  Eric Abrahamsen  <address@hidden>
+
+       Note that choose-completion-string-functions funcs take four args
+
+       * lisp/simple.el (choose-completion-string-functions): Functions in
+         this list actually need to accept four arguments, though the fourth
+         should be ignored.
+
+2019-04-10  Gemini Lasswell  <address@hidden>
+
+       Address name conflicts in EIEIO documentation (bug#31660)
+
+       * doc/misc/eieio.texi (Quick Start): Rename the class used in the
+       example from 'record' to 'person'.
+       (Building Classes): Advise user to check for name conflicts before
+       naming a class.  Add a missing apostrophe.
+       (Making New Objects): Correct grammar.  Rename the class used in the
+       example from 'record' to 'my-class'.
+
+2019-04-09  Mattias Engdegård  <address@hidden>
+
+       Clarify the TESTFN argument to `alist-get'
+
+       * lisp/subr.el (alist-get):
+       Rephrase the initial text to clarify the meaning of the TESTFN argument.
+       It's an equality predicate, not a look-up function (Bug#35206).
+
+       (cherry picked from commit c81465580fe262f28ce47502c00f4afcbe3b8f8d)
+
+2019-04-08  Eli Zaretskii  <address@hidden>
+
+       * src/editfns.c (Fnarrow_to_region): Doc fix.  (Bug#35163)
+
+2019-04-06  Eli Zaretskii  <address@hidden>
+
+       Fix doc strings of 'vc-version-diff' and 'vc-version-ediff'
+
+       * lisp/vc/vc.el (vc-version-diff, vc-version-ediff): Describe
+       arguments in the doc strings.  (Bug#35019)
+
+2019-04-06  Eli Zaretskii  <address@hidden>
+
+       Improve documentation of set-window-start
+
+       * doc/lispref/windows.texi (Window Start and End):
+       * src/window.c (Fset_window_start): Document that reliable
+       setting of a window start position requires to adjust point to
+       be visible.  (Bug#34038)
+
+2019-04-06  Eli Zaretskii  <address@hidden>
+
+       Improve documentation of window parameters
+
+       * doc/lispref/windows.texi (Cyclic Window Ordering): Describe
+       the effect of the 'other-window' window parameter.
+       (Window Parameters): Improve the descriptions of window
+       parameters.  Move the detailed description of the
+       'quit-restore' window parameter from here...
+       (Quitting Windows): ...to here.  (Bug#35063)
+
+2019-04-06  Eli Zaretskii  <address@hidden>
+
+       Improve commentary in frame.el
+
+       * lisp/frame.el: Improve commentary for display-* functions.
+       (Bug#35058)
+
+2019-04-06  Mauro Aranda  <address@hidden>
+
+       Fix typo in a doc string
+
+       * lisp/autorevert.el (global-auto-revert-mode): Fix a typo.
+       (Bug#35165)
+
+2019-03-20  Paul Eggert  <address@hidden>
+
+       Say which regexp ranges should be avoided
+
+       * doc/lispref/searching.texi (Regexp Special): Say that
+       regular expressions like "[a-m-z]" and "[[:alpha:]-~]" should
+       be avoided, for the same reason that regular expressions like
+       "+" and "*" should be avoided: POSIX says their behavior is
+       undefined, and they are confusing anyway.  Also, explain
+       better what happens when the bound of a range is a raw 8-bit
+       byte; the old explanation appears to have been obsolete
+       anyway.  Finally, say that ranges like "[\u00FF-\xFF]" that
+       mix non-ASCII characters and raw 8-bit bytes should be
+       avoided, since it’s not clear what they should mean.
+
+2019-03-20  Nicolas Petton  <address@hidden>
+
+       * etc/AUTHORS: Update.
+
+       * ; ChangeLog.3 update
+
 2019-03-20  Eli Zaretskii  <address@hidden>
 
        Improve indexing of the user manual
@@ -64946,7 +65091,7 @@
 
 This file records repository revisions from
 commit 9d56a21e6a696ad19ac65c4b405aeca44785884a (exclusive) to
-commit 0f523deec1c1e9e2a5a3474f912aa2183d3fe33d (inclusive).
+commit 85829363f728c410e33ffdc3839202977b2115cc (inclusive).
 See ChangeLog.1 for earlier changes.
 
 ;; Local Variables:
diff --git a/build-aux/config.sub b/build-aux/config.sub
index 3b4c762..a44fd8a 100755
--- a/build-aux/config.sub
+++ b/build-aux/config.sub
@@ -822,7 +822,9 @@ case $basic_machine in
                cpu=m68k
                vendor=next
                case $os in
-                   nextstep* )
+                   openstep*)
+                       ;;
+                   nextstep*)
                        ;;
                    ns2*)
                      os=nextstep2
diff --git a/doc/lispref/minibuf.texi b/doc/lispref/minibuf.texi
index 6c37fa9..cfea336 100644
--- a/doc/lispref/minibuf.texi
+++ b/doc/lispref/minibuf.texi
@@ -1333,7 +1333,8 @@ is a string, @code{read-command} interns it before 
returning it.
 If it is a list, @code{read-command} interns the first element of this list.
 If @var{default} is @code{nil}, that means no default has been
 specified; then if the user enters null input, the return value is
address@hidden(intern "")}, that is, a symbol whose name is an empty string.
address@hidden(intern "")}, that is, a symbol whose name is an empty string,
+and whose printed representation is @code{##} (@pxref{Symbol Type}).
 
 @example
 (read-command "Command name? ")
diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi
index 1ef836b..500df1f 100644
--- a/doc/lispref/text.texi
+++ b/doc/lispref/text.texi
@@ -5156,8 +5156,11 @@ as in @code{json-parse-string}.
 
 @defun json-parse-string string &rest args
 This function parses the JSON value in @var{string}, which must be a
-Lisp string.  The argument @var{args} is a list of keyword/argument
-pairs.  The following keywords are accepted:
+Lisp string.  If @var{string} doesn't contain a valid JSON object,
+this function signals the @code{json-parse-error} error.
+
+The argument @var{args} is a list of keyword/argument pairs.  The
+following keywords are accepted:
 
 @table @code
 @item :object-type
@@ -5167,6 +5170,11 @@ key-value mappings of a JSON object.  It can be either
 keys; @code{alist} to use alists with symbols as keys; or @code{plist}
 to use plists with keyword symbols as keys.
 
address@hidden :array-type
+The value decides which Lisp object to use for representing a JSON
+array.  It can be either @code{array}, the default, to use Lisp
+arrays; or @code{list} to use lists.
+
 @item :null-object
 The value decides which Lisp object to use to represent the JSON
 keyword @code{null}.  It defaults to the symbol @code{:null}.
@@ -5181,19 +5189,20 @@ keyword @code{false}.  It defaults to the symbol 
@code{:false}.
 @defun json-parse-buffer &rest args
 This function reads the next JSON value from the current buffer,
 starting at point.  It moves point to the position immediately after
-the value if a value could be read and converted to Lisp; otherwise it
-doesn't move point.  The arguments @var{args} are interpreted as in
address@hidden
+the value if contains a valid JSON object; otherwise it signals the
address@hidden error and doesn't move point.  The arguments
address@hidden are interpreted as in @code{json-parse-string}.
 @end defun
 
 @node JSONRPC
 @section JSONRPC communication
 @cindex JSON remote procedure call protocol
address@hidden JSONRPC
 
 The @code{jsonrpc} library implements the @acronym{JSONRPC}
 specification, version 2.0, as it is described in
 @uref{http://www.jsonrpc.org/}.  As the name suggests, JSONRPC is a
-generic @code{Remote Procedure Call} protocol designed around
+generic @dfn{Remote Procedure Call} protocol designed around
 @acronym{JSON} objects, which you can convert to and from Lisp objects
 (@pxref{Parsing JSON}).
 
@@ -5212,81 +5221,96 @@ transport agnostic in that the concepts can be used 
within the same
 process, over sockets, over http, or in many various message passing
 environments."
 
address@hidden jsonrpc-connection
 To model this agnosticism, the @code{jsonrpc} library uses objects of
-a @code{jsonrpc-connection} class, which represent a connection the
+a @code{jsonrpc-connection} class, which represent a connection to a
 remote JSON endpoint (for details on Emacs's object system,
 @pxref{Top,EIEIO,,eieio,EIEIO}).  In modern object-oriented parlance,
-this class is ``abstract'', i.e. the actual class of a useful
-connection object used is always a subclass of it.  Nevertheless, we
-can define two distinct API's around the @code{jsonrpc-connection}
-class:
+this class is ``abstract'', i.e.@: the actual class of a useful
+connection object is always a subclass of @code{jsonrpc-connection}.
+Nevertheless, we can define two distinct APIs around the
address@hidden class:
 
address@hidden JSONRPC application interfaces
 @enumerate
 
 @item A user interface for building JSONRPC applications
 
address@hidden :request-dispatcher
address@hidden :notification-dispatcher
address@hidden jsonrpc-notify
address@hidden jsonrpc-request
address@hidden jsonrpc-async-request
 In this scenario, the JSONRPC application selects a concrete subclass
 of @code{jsonrpc-connection}, and proceeds to create objects of that
 subclass using @code{make-instance}.  To initiate a contact to the
 remote endpoint, the JSONRPC application passes this object to the
-functions @code{jsonrpc-notify'}, @code{jsonrpc-request} and
+functions @code{jsonrpc-notify}, @code{jsonrpc-request}, and/or
 @code{jsonrpc-async-request}.  For handling remotely initiated
 contacts, which generally come in asynchronously, the instantiation
 should include @code{:request-dispatcher} and
 @code{:notification-dispatcher} initargs, which are both functions of
 3 arguments: the connection object; a symbol naming the JSONRPC method
-invoked remotely; and a JSONRPC "params" object.
+invoked remotely; and a JSONRPC @code{params} object.
 
address@hidden jsonrpc-error
 The function passed as @code{:request-dispatcher} is responsible for
 handling the remote endpoint's requests, which expect a reply from the
 local endpoint (in this case, the program you're building).  Inside
-that function, you may either return locally (normally) or non-locally
-(error).  A local return value must be a Lisp object serializable as
-JSON (@pxref{Parsing JSON}).  This determines a success response, and
-the object is forwarded to the server as the JSONRPC "result" object.
-A non-local return, achieved by calling the function
address@hidden, causes an error response to be sent to the
-server.  The details of the accompanying JSONRPC "error" are filled
-out with whatever was passed to @code{jsonrpc-error}.  A non-local
-return triggered by an unexpected error of any other type also causes
-an error response to be sent (unless you have set
address@hidden, in which case this should land you in the
-debugger, @pxref{Error Debugging}).
+that function, you may either return locally (a normal return) or
+non-locally (an error return).  A local return value must be a Lisp
+object that can be serialized as JSON (@pxref{Parsing JSON}).  This
+determines a success response, and the object is forwarded to the
+server as the JSONRPC @code{result} object.  A non-local return,
+achieved by calling the function @code{jsonrpc-error}, causes an error
+response to be sent to the server.  The details of the accompanying
+JSONRPC @code{error} are filled out with whatever was passed to
address@hidden  A non-local return triggered by an unexpected
+error of any other type also causes an error response to be sent
+(unless you have set @code{debug-on-error}, in which case this calls
+the Lisp debugger, @pxref{Error Debugging}).
 
 @item A inheritance interface for building JSONRPC transport implementations
 
 In this scenario, @code{jsonrpc-connection} is subclassed to implement
 a different underlying transport strategy (for details on how to
-subclass, @pxref{Inheritance,Inheritance,,eieio}).  Users of the
+subclass, see @ref{Inheritance,Inheritance,,eieio}.).  Users of the
 application-building interface can then instantiate objects of this
 concrete class (using the @code{make-instance} function) and connect
 to JSONRPC endpoints using that strategy.
 
 This API has mandatory and optional parts.
 
address@hidden jsonrpc-connection-send
 To allow its users to initiate JSONRPC contacts (notifications or
-requests) or reply to endpoint requests, the method
address@hidden must be implemented for the subclass.
+requests) or reply to endpoint requests, the subclass must have an
+implementation of the @code{jsonrpc-connection-send} method.
 
address@hidden jsonrpc-connection-receive
 Likewise, for handling the three types of remote contacts (requests,
-notifications and responses to local requests) the transport
+notifications, and responses to local requests), the transport
 implementation must arrange for the function
 @code{jsonrpc-connection-receive} to be called after noticing a new
 JSONRPC message on the wire (whatever that "wire" may be).
 
address@hidden jsonrpc-shutdown
address@hidden jsonrpc-running-p
 Finally, and optionally, the @code{jsonrpc-connection} subclass should
-implement @code{jsonrpc-shutdown} and @code{jsonrpc-running-p} if
-these concepts apply to the transport.  If they do, then any system
-resources (e.g. processes, timers, etc..) used listen for messages on
-the wire should be released in @code{jsonrpc-shutdown}, i.e. they
-should only be needed while @code{jsonrpc-running-p} is non-nil.
+implement the @code{jsonrpc-shutdown} and @code{jsonrpc-running-p}
+methods if these concepts apply to the transport.  If they do, then
+any system resources (e.g.@: processes, timers, etc.) used to listen for
+messages on the wire should be released in @code{jsonrpc-shutdown},
+i.e.@: they should only be needed while @code{jsonrpc-running-p} is
+non-nil.
 
 @end enumerate
 
 @node Process-based JSONRPC connections
 @subsection Process-based JSONRPC connections
address@hidden JSONRPC process-based connections
 
-For convenience, the @code{jsonrpc} library comes built-in with a
address@hidden jsonrpc-process-connection
+For convenience, the @code{jsonrpc} library comes with a built-in
 @code{jsonrpc-process-connection} transport implementation that can
 talk to local subprocesses (using the standard input and standard
 output); or TCP hosts (using sockets); or any other remote endpoint
@@ -5301,6 +5325,7 @@ JSONRPC, see the
 @uref{https://microsoft.github.io/language-server-protocol/specification,
 Language Server Protocol}.
 
address@hidden JSONRPC connection initargs
 Along with the mandatory @code{:request-dispatcher} and
 @code{:notification-dispatcher} initargs, users of the
 @code{jsonrpc-process-connection} class should pass the following
@@ -5309,29 +5334,32 @@ initargs as keyword-value pairs to @code{make-instance}:
 @table @code
 @item :process
 Value must be a live process object or a function of no arguments
-producing one such object.  If passed a process object, that is
-expected to contain an pre-established connection; otherwise, the
+producing one such object.  If passed a process object, the object is
+expected to contain a pre-established connection; otherwise, the
 function is called immediately after the object is made.
 
 @item :on-shutdown
 Value must be a function of a single argument, the
 @code{jsonrpc-process-connection} object.  The function is called
 after the underlying process object has been deleted (either
-deliberately by @code{jsonrpc-shutdown} or unexpectedly, because of
+deliberately by @code{jsonrpc-shutdown}, or unexpectedly, because of
 some external cause).
 @end table
 
 @node JSONRPC JSON object format
address@hidden JSON object format
address@hidden JSONRPC JSON object format
address@hidden JSONRPC object format
 
-JSON objects are exchanged as Lisp plists (@pxref{Parsing JSON}):
-JSON-compatible plists are handed to the dispatcher functions and,
-likewise, JSON-compatible plists should be given to
address@hidden, @code{jsonrpc-request} and
+JSONRPC JSON objects are exchanged as Lisp plists (@pxref{Property
+Lists}): JSON-compatible plists are handed to the dispatcher functions
+and, likewise, JSON-compatible plists should be given to
address@hidden, @code{jsonrpc-request}, and
 @code{jsonrpc-async-request}.
 
-To facilitate handling plists, this library make liberal use of
address@hidden library and suggests (but doesn't force) its clients to
address@hidden jsonrpc-lambda
+To facilitate handling plists, this library makes liberal use of
address@hidden library (@pxref{Top,cl-lib,,cl,Common Lisp Extensions
+for GNU Emacs Lisp}) and suggests (but doesn't force) its clients to
 do the same.  A macro @code{jsonrpc-lambda} can be used to create a
 lambda for destructuring a JSON-object like in this example:
 
@@ -5347,7 +5375,8 @@ lambda for destructuring a JSON-object like in this 
example:
 @end example
 
 @node JSONRPC deferred requests
address@hidden Deferred requests
address@hidden Deferred JSONRPC requests
address@hidden JSONRPC deferred requests
 
 In many @acronym{RPC} situations, synchronization between the two
 communicating endpoints is a matter of correctly designing the RPC
@@ -5359,6 +5388,7 @@ is still uncertainty about the state of the remote 
endpoint.
 Furthermore, acting on these events may only sometimes demand
 synchronization, depending on the event's specific nature.
 
address@hidden :address@hidden, JSONRPC keyword}
 The @code{:deferred} keyword argument to @code{jsonrpc-request} and
 @code{jsonrpc-async-request} is designed to let the caller indicate
 that the specific request needs synchronization and its actual
@@ -5369,9 +5399,10 @@ isn't sent immediately, @code{jsonrpc} will make renewed 
efforts to
 send it at certain key times during communication, such as when
 receiving or sending other messages to the endpoint.
 
address@hidden jsonrpc-connection-ready-p
 Before any attempt to send the request, the application-specific
-conditions are checked.  Since the @code{jsonrpc} library can't known
-what these conditions are, the programmer may use the
+conditions are checked.  Since the @code{jsonrpc} library can't know
+what these conditions are, the program can use the
 @code{jsonrpc-connection-ready-p} generic function (@pxref{Generic
 Functions}) to specify them.  The default method for this function
 returns @code{t}, but you can add overriding methods that return
diff --git a/doc/misc/nxml-mode.texi b/doc/misc/nxml-mode.texi
index edab900..2b2c241 100644
--- a/doc/misc/nxml-mode.texi
+++ b/doc/misc/nxml-mode.texi
@@ -250,7 +250,7 @@ xml:lang                           xmlns
 If you input @kbd{xmlns}, the result will be:
 
 @example
-<html xmlns="@point{}
+<html xmlns="@point{}"
 @end example
 
 @noindent
diff --git a/doc/misc/texinfo.tex b/doc/misc/texinfo.tex
index 667292a..192284c 100644
--- a/doc/misc/texinfo.tex
+++ b/doc/misc/texinfo.tex
@@ -3,7 +3,8 @@
 % Load plain if necessary, i.e., if running under initex.
 \expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
 %
-\def\texinfoversion{2019-03-23.11}
+\def\texinfoversion{2019-03-03.15}
+
 %
 % Copyright 1985, 1986, 1988, 1990-2019 Free Software Foundation, Inc.
 %
@@ -386,8 +387,14 @@
     % take effect in \write's, yet the group defined by the \vbox ends
     % before the \shipout runs.
     %
-    \atdummies         % don't expand commands in the output.
-    \turnoffactive
+    \indexdummies         % don't expand commands in the output.
+    \normalturnoffactive  % \ in index entries must not stay \, e.g., if
+               % the page break happens to be in the middle of an example.
+               % We don't want .vr (or whatever) entries like this:
+               % \entry{{\indexbackslash }acronym}{32}{\code {\acronym}}
+               % "\acronym" won't work when it's read back in;
+               % it needs to be
+               % {\code {{\backslashcurfont }acronym}
     \shipout\vbox{%
       % Do this early so pdf references go to the beginning of the page.
       \ifpdfmakepagedest \pdfdest name{\the\pageno} xyz\fi
@@ -448,10 +455,11 @@
   }%
 }
 
-% First remove any @comment, then any @c comment.  Pass the result on to 
-% \argcheckspaces.
+% First remove any @comment, then any @c comment.  Also remove a @texinfoc
+% comment (see \scanmacro for details).  Pass the result on to \argcheckspaces.
 \def\argremovecomment#1\comment#2\ArgTerm{\argremovec #1\c\ArgTerm}
-\def\argremovec#1\c#2\ArgTerm{\argcheckspaces#1\^^M\ArgTerm}
+\def\argremovec#1\c#2\ArgTerm{\argremovetexinfoc #1\texinfoc\ArgTerm}
+\def\argremovetexinfoc#1\texinfoc#2\ArgTerm{\argcheckspaces#1\^^M\ArgTerm}
 
 % Each occurrence of `\^^M' or `<space>\^^M' is replaced by a single space.
 %
@@ -1123,16 +1131,6 @@ where each line of input produces a line of output.}
   \fi
 \fi
 
-\newif\ifpdforxetex
-\pdforxetexfalse
-\ifpdf
-  \pdforxetextrue
-\fi
-\ifx\XeTeXrevision\thisisundefined\else
-  \pdforxetextrue
-\fi
-
-
 % PDF uses PostScript string constants for the names of xref targets,
 % for display in the outlines, and in other places.  Thus, we have to
 % double any backslashes.  Otherwise, a name like "\node" will be
@@ -2846,7 +2844,7 @@ end
 
 % @t, explicit typewriter.
 \def\t#1{%
-  {\tt \plainfrenchspacing #1}%
+  {\tt \rawbackslash \plainfrenchspacing #1}%
   \null
 }
 
@@ -2873,6 +2871,7 @@ end
     % Turn off hyphenation.
     \nohyphenation
     %
+    \rawbackslash
     \plainfrenchspacing
     #1%
   }%
@@ -3113,7 +3112,7 @@ end
 % So now @email is just like @uref, unless we are pdf.
 %
 %\def\email#1{\angleleft{\tt #1}\angleright}
-\ifpdforxetex
+\ifpdf
   \def\email#1{\doemail#1,,\finish}
   \def\doemail#1,#2,#3\finish{\begingroup
     \unsepspaces
@@ -3123,7 +3122,18 @@ end
     \endlink
   \endgroup}
 \else
-  \let\email=\uref
+  \ifx\XeTeXrevision\thisisundefined
+    \let\email=\uref
+  \else
+    \def\email#1{\doemail#1,,\finish}
+    \def\doemail#1,#2,#3\finish{\begingroup
+      \unsepspaces
+      \pdfurl{mailto:#1}%
+      \setbox0 = \hbox{\ignorespaces #2}%
+      \ifdim\wd0>0pt\unhbox0\else\code{#1}\fi
+      \endlink
+    \endgroup}
+  \fi
 \fi
 
 % @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always),
@@ -4657,6 +4667,19 @@ end
   }
 }
 
+% We have this subroutine so that we can handle at least some @value's
+% properly in indexes (we call \makevalueexpandable in \indexdummies).
+% The command has to be fully expandable (if the variable is set), since
+% the result winds up in the index file.  This means that if the
+% variable's value contains other Texinfo commands, it's almost certain
+% it will fail (although perhaps we could fix that with sufficient work
+% to do a one-level expansion on the result, instead of complete).
+% 
+% Unfortunately, this has the consequence that when _ is in the *value*
+% of an @set, it does not print properly in the roman fonts (get the cmr
+% dot accent at position 126 instead).  No fix comes to mind, and it's
+% been this way since 2003 or earlier, so just ignore it.
+% 
 \def\expandablevalue#1{%
   \expandafter\ifx\csname SET#1\endcsname\relax
     {[No value for ``#1'']}%
@@ -4685,7 +4708,7 @@ end
 % if possible, otherwise sort late.
 \def\indexnofontsvalue#1{%
   \expandafter\ifx\csname SET#1\endcsname\relax
-    ZZZZZZZ%
+    ZZZZZZZ
   \else
     \csname SET#1\endcsname
   \fi
@@ -4835,8 +4858,23 @@ end
 \def\docodeindexxxx #1{\doind{\indexname}{\code{#1}}}
 
 
-% Used for the aux, toc and index files to prevent expansion of Texinfo 
-% commands.
+% Used when writing an index entry out to an index file to prevent
+% expansion of Texinfo commands that can appear in an index entry.
+%
+\def\indexdummies{%
+  \escapechar = `\\     % use backslash in output files.
+  address@hidden
+  \definedummyletter\ %
+  %
+  % For texindex which always views { and } as separators.
+  \def\{{\lbracechar{}}%
+  \def\}{\rbracechar{}}%
+  %
+  % Do the redefinitions.
+  \definedummies
+}
+
+% Used for the aux and toc files, where @ is the escape character.
 %
 \def\atdummies{%
   address@hidden
@@ -4866,7 +4904,8 @@ end
 \def\definedummyletter#1{\def#1{\string#1}}%
 \let\definedummyaccent\definedummyletter
 
-% Called from \atdummies to prevent the expansion of commands.
+% Called from \indexdummies and \atdummies, to effectively prevent
+% the expansion of commands.
 %
 \def\definedummies{%
   %
@@ -5031,9 +5070,11 @@ end
   \commondummyword\xref
 }
 
+% This does nothing, but for a time it was recommended to use
+% \usebracesinindexestrue to be able to use braces in index entries.
+
 \let\indexlbrace\relax
 \let\indexrbrace\relax
-\let\indexatchar\relax
 
 address@hidden
 \catcode`\\=13
@@ -5067,8 +5108,10 @@ end
   }
 
   \gdef\indexnonalnumreappear{%
+    \useindexbackslash
     \let-\normaldash
     \let<\normalless
+    address@hidden@}%
   }
 }
 
@@ -5179,6 +5222,8 @@ end
 
 
 
+\let\SETmarginindex=\relax % put index entries in margin (undocumented)?
+
 % #1 is the index name, #2 is the entry text.
 \def\doind#1#2{%
   \iflinks
@@ -5210,6 +5255,13 @@ end
 \fi}
 \def\indexisfl{fl}
 
+% Output \ as {\indexbackslash}, because \ is an escape character in
+% the index files.
+\let\indexbackslash=\relax
address@hidden \catcode`\\=\active
+  @address@hidden@address@hidden
+}
+
 % Definition for writing index entry sort key.
 {
 \catcode`\-=13
@@ -5221,25 +5273,14 @@ end
   \xdef\indexsortkey{#1}\endgroup}
 }
 
-\def\indexwriteseealso#1{
-  address@hidden
-}
-
-% The default definitions
-\def\sortas#1{}%
-\def\seealso#1{\i{\putwordSeeAlso}\ #1}% for sorted index file only
-\def\putwordSeeAlso{see also}
-
 % Given index entry text like "aaa @subentry bbb @sortas{ZZZ}":
 %   * Set \bracedtext to "{aaa}{bbb}"
 %   * Set \fullindexsortkey to "aaa @subentry ZZZ"
-%   * If @seealso occurs, set \pagenumbertext
 %
 \def\splitindexentry#1{%
   \gdef\fullindexsortkey{}%
   \xdef\bracedtext{}%
   \def\sep{}%
-  \def\seealso##1{}%
   \expandafter\doindexsegment#1\subentry\finish\subentry
 }
 
@@ -5251,6 +5292,7 @@ end
     %
     % Fully expand the segment, throwing away any @sortas directives, and 
     % trim spaces.
+    \def\sortas##1{}%
     \edef\trimmed{\segment}%
     \edef\trimmed{\expandafter\eatspaces\expandafter{\trimmed}}%
     %
@@ -5260,20 +5302,16 @@ end
     % font commands turned off.
     \bgroup
       \let\sortas\indexwritesortas
-      \let\seealso\indexwriteseealso
       \indexnofonts
       % The braces around the commands are recognized by texindex.
       \def\lbracechar{{\indexlbrace}}%
       \def\rbracechar{{\indexrbrace}}%
       \let\{=\lbracechar
       \let\}=\rbracechar
-      address@hidden
-      address@hidden
       %
       \let\indexsortkey\empty
-      \global\let\pagenumbertext\empty
       % Execute the segment and throw away the typeset output.  This executes
-      % any @sortas or @seealso commands in this segment.
+      % any @sortas commands in this segment.
       \setbox\dummybox = \hbox{\segment}%
       \ifx\indexsortkey\empty{%
         \indexnonalnumdisappear
@@ -5294,20 +5332,21 @@ end
   \fi
 }
 \def\isfinish{\finish}%
-\newbox\dummybox % used above
 
 \let\subentry\relax
 
 % Write the entry in \toks0 to the index file.
 %
 \def\doindwrite{%
-  \maybemarginindex
-  %
-  \atdummies
+  % Put the index entry in the margin if desired.
+  \ifx\SETmarginindex\relax\else
+    \insert\margin{\hbox{\vrule height8pt depth3pt width0pt \the\toks0}}%
+  \fi
   %
-  % For texindex which always views { and } as separators.
-  \def\{{\lbracechar{}}%
-  \def\}{\rbracechar{}}%
+  % Remember, we are within a group.
+  \indexdummies % Must do this here, since \bf, etc expand at this stage
+  \useindexbackslash % \indexbackslash isn't defined now so it will be output 
+                     % as is; and it will print as backslash.
   %
   % Split the entry into primary entry and any subentries, and get the index 
   % sort key.
@@ -5321,21 +5360,11 @@ end
   %
   \edef\temp{%
     \write\writeto{%
-      \string\entry{\fullindexsortkey}%
-        {\ifx\pagenumbertext\empty\noexpand\folio\else\pagenumbertext\fi}%
-        \bracedtext}%
+      \string\entry{\fullindexsortkey}{\noexpand\folio}\bracedtext}%
   }%
   \temp
 }
-
-% Put the index entry in the margin if desired (undocumented).
-\def\maybemarginindex{%
-  \ifx\SETmarginindex\relax\else
-    \insert\margin{\hbox{\vrule height8pt depth3pt width0pt \relax\indextext}}%
-  \fi
-}
-\let\SETmarginindex=\relax
-
+\newbox\dummybox % used above
 
 % Take care of unwanted page breaks/skips around a whatsit:
 %
@@ -5423,14 +5452,9 @@ end
 %  \entry {topic}{pagelist}
 %     for a topic that is used without subtopics
 %  \primary {topic}
-%  \entry {topic}{}
 %     for the beginning of a topic that is used with subtopics
 %  \secondary {subtopic}{pagelist}
 %     for each subtopic.
-%  \secondary {subtopic}{}
-%     for a subtopic with sub-subtopics
-%  \tertiary {subtopic}{subsubtopic}{pagelist}
-%     for each sub-subtopic.
 
 % Define the user-accessible indexing commands
 % @findex, @vindex, @kindex, @cindex.
@@ -5455,10 +5479,14 @@ end
   \plainfrenchspacing
   \everypar = {}% don't want the \kern\-parindent from indentation suppression.
   %
+  % See if the index file exists and is nonempty.
+  % Change catcode of @ here so that if the index file contains
+  % \initial address@hidden
+  % as its first line, TeX doesn't complain about mismatched braces
+  % (because it thinks @} is a control sequence).
+  \catcode`\@ = 12
   % See comment in \requireopenindexfile.
   \def\indexname{#1}\ifx\indexname\indexisfl\def\indexname{f1}\fi
-  %
-  % See if the index file exists and is nonempty.
   \openin 1 \jobname.\indexname s
   \ifeof 1
     % \enddoublecolumns gets confused if there is no text in the index,
@@ -5468,6 +5496,8 @@ end
     \putwordIndexNonexistent
     \typeout{No file \jobname.\indexname s.}%
   \else
+    \catcode`\\ = 0
+    %
     % If the index file exists but is empty, then \openin leaves \ifeof
     % false.  We have to make TeX try to read something from the file, so
     % it can discover if there is anything in it.
@@ -5475,27 +5505,47 @@ end
     \ifeof 1
       \putwordIndexIsEmpty
     \else
-      \expandafter\printindexzz\thisline\relax\relax\finish%
+      % Index files are almost Texinfo source, but we use \ as the escape
+      % character.  It would be better to use @, but that's too big a change
+      % to make right now.
+      \def\indexbackslash{\ttbackslash}%
+      \let\indexlbrace\{   % Likewise, set these sequences for braces
+      \let\indexrbrace\}   % used in the sort key.
+      \begindoublecolumns
+      \let\dotheinsertentrybox\dotheinsertentryboxwithpenalty
+      %
+      % Read input from the index file line by line.
+      \loopdo
+        \ifeof1 \else
+          \read 1 to \nextline
+        \fi
+        %
+        \indexinputprocessing
+        \thisline
+        %
+        \ifeof1\else
+        \let\thisline\nextline
+      \repeat
+      %%
+      \enddoublecolumns
     \fi
   \fi
   \closein 1
 \endgroup}
+\def\loopdo#1\repeat{\def\body{#1}\loopdoxxx}
+\def\loopdoxxx{\let\next=\relax\body\let\next=\loopdoxxx\fi\next}
 
-% If the index file starts with a backslash, forgo reading the index
-% file altogether.  If somebody upgrades texinfo.tex they may still have
-% old index files using \ as the escape character.  Reading this would
-% at best lead to typesetting garbage, at worst a TeX syntax error.
-\def\printindexzz#1#2\finish{%
-  % NB this won't work if the index file starts with a group...
-  \uccode`\~=`\\ \uppercase{\if\noexpand~}\noexpand#1
-    \message{skipping sorted index file}%
-    (Skipped sorted index file in obsolete format)
+\def\indexinputprocessing{%
+  \ifeof1
+    \let\firsttoken\relax
   \else
-    \begindoublecolumns
-    \input \jobname.\indexname s
-    \enddoublecolumns
+    \edef\act{\gdef\noexpand\firsttoken{\getfirsttoken\nextline}}%
+    \act
   \fi
 }
+\def\getfirsttoken#1{\expandafter\getfirsttokenx#1\endfirsttoken}
+\long\def\getfirsttokenx#1#2\endfirsttoken{\noexpand#1}
+
 
 % These macros are used by the sorted index file itself.
 % Change them to control the appearance of the index.
@@ -5504,18 +5554,12 @@ end
 \catcode`\|=13 \catcode`\<=13 \catcode`\>=13 \catcode`\+=13 \catcode`\"=13
 \catcode`\$=3
 \gdef\initialglyphs{%
-  % special control sequences used in the index sort key
-  \let\indexlbrace\{%
-  \let\indexrbrace\}%
-  address@hidden
-  %
   % Some changes for non-alphabetic characters.  Using the glyphs from the
   % math fonts looks more consistent than the typewriter font used elsewhere
   % for these characters.
-  \uccode`\~=`\\ \uppercase{\def~{\math{\backslash}}}
+  \def\indexbackslash{\math{\backslash}}%
+  \let\\=\indexbackslash
   %
-  % In case @\ is used for backslash
-  \uppercase{\let\\=~}
   % Can't get bold backslash so don't use bold forward slash
   \catcode`\/=13
   \def/{{\secrmnotbold \normalslash}}%
@@ -5575,6 +5619,12 @@ end
 \def\entry{%
   \begingroup
     %
+    % For pdfTeX and XeTeX.
+    % The redefinition of \domark stops marks being added in \pdflink to 
+    % preserve coloured links across page boundaries.  Otherwise the marks
+    % would get in the way of \lastbox in \insertentrybox.
+    \let\domark\relax
+    %
     % Start a new paragraph if necessary, so our assignments below can't
     % affect previous text.
     \par
@@ -5607,31 +5657,35 @@ end
 \gdef\finishentry#1{%
     \egroup % end box A
     \dimen@ = \wd\boxA % Length of text of entry
-    \global\setbox\boxA=\hbox\bgroup
-      \unhbox\boxA
-      % #1 is the page number.
+    \global\setbox\boxA=\hbox\bgroup\unhbox\boxA
+    % #1 is the page number.
+    %
+    % Get the width of the page numbers, and only use
+    % leaders if they are present.
+    \global\setbox\boxB = \hbox{#1}%
+    \ifdim\wd\boxB = 0pt
+      \null\nobreak\hfill\ %
+    \else
+      %
+      \null\nobreak\indexdotfill % Have leaders before the page number.
       %
-      % Get the width of the page numbers, and only use
-      % leaders if they are present.
-      \global\setbox\boxB = \hbox{#1}%
-      \ifdim\wd\boxB = 0pt
-        \null\nobreak\hfill\ %
+      \ifpdf
+        \pdfgettoks#1.%
+        \hskip\skip\thinshrinkable\the\toksA
       \else
-        %
-        \null\nobreak\indexdotfill % Have leaders before the page number.
-        %
-        \ifpdforxetex
+        \ifx\XeTeXrevision\thisisundefined
+          \hskip\skip\thinshrinkable #1%
+        \else
           \pdfgettoks#1.%
           \hskip\skip\thinshrinkable\the\toksA
-        \else
-          \hskip\skip\thinshrinkable #1%
         \fi
       \fi
+    \fi
     \egroup % end \boxA
     \ifdim\wd\boxB = 0pt
-      \noindent\unhbox\boxA\par
-      \nobreak
-    \else\bgroup
+      \global\setbox\entrybox=\vbox{\unhbox\boxA}%
+    \else
+    \global\setbox\entrybox=\vbox\bgroup
       % We want the text of the entries to be aligned to the left, and the
       % page numbers to be aligned to the right.
       %
@@ -5697,11 +5751,55 @@ end
     \egroup % The \vbox
     \fi
   \endgroup
+  \dotheinsertentrybox
 }}
 
 \newskip\thinshrinkable
 \skip\thinshrinkable=.15em minus .15em
 
+\newbox\entrybox
+\def\insertentrybox{%
+  \ourunvbox\entrybox
+}
+
+% default definition
+\let\dotheinsertentrybox\insertentrybox
+
+% Use \lastbox to take apart vbox box by box, and add each sub-box
+% to the current vertical list.
+\def\ourunvbox#1{%
+\bgroup % for local binding of \delayedbox
+  % Remove the last box from box #1
+  \global\setbox#1=\vbox{%
+    \unvbox#1%
+    \unskip % remove any glue
+    \unpenalty
+    \global\setbox\interbox=\lastbox
+  }%
+  \setbox\delayedbox=\box\interbox
+  \ifdim\ht#1=0pt\else
+    \ourunvbox#1 % Repeat on what's left of the box
+    \nobreak
+  \fi
+  \box\delayedbox
+\egroup
+}
+\newbox\delayedbox
+\newbox\interbox
+
+% Used from \printindex.  \firsttoken should be the first token
+% after the \entry.  If it's not another \entry, we are at the last
+% line of a group of index entries, so insert a penalty to discourage
+% widowed index entries.
+\def\dotheinsertentryboxwithpenalty{%
+  \ifx\firsttoken\isentry
+  \else
+    \penalty 9000
+  \fi
+  \insertentrybox
+}
+\def\isentry{\entry}%
+
 % Like plain.tex's \dotfill, except uses up at least 1 em.
 % The filll stretch here overpowers both the fil and fill stretch to push
 % the page number to the right.
@@ -5711,15 +5809,24 @@ end
 
 \def\primary #1{\line{#1\hfil}}
 
-\def\secondary{\indententry{0.5cm}}
-\def\tertiary{\indententry{1cm}}
-
-\def\indententry#1#2#3{%
-  \bgroup
-  \leftskip=#1
-  \entry{#2}{#3}%
-  \egroup
-}
+\newskip\secondaryindent \secondaryindent=0.5cm
+\def\secondary#1#2{{%
+  \parfillskip=0in
+  \parskip=0in
+  \hangindent=1in
+  \hangafter=1
+  \noindent\hskip\secondaryindent\hbox{#1}\indexdotfill
+  \ifpdf
+    \pdfgettoks#2.\ \the\toksA % The page number ends the paragraph.
+  \else
+    \ifx\XeTeXrevision\thisisundefined
+      #2
+    \else
+      \pdfgettoks#2.\ \the\toksA % The page number ends the paragraph.
+    \fi
+  \fi
+  \par
+}}
 
 % Define two-column mode, which we use to typeset indexes.
 % Adapted from the TeXbook, page 416, which is to say,
@@ -5737,6 +5844,17 @@ end
   \output = {%
     \savetopmark
     %
+    % Here is a possibility not foreseen in manmac: if we accumulate a
+    % whole lot of material, we might end up calling this \output
+    % routine twice in a row (see the doublecol-lose test, which is
+    % essentially a couple of indexes with @setchapternewpage off).  In
+    % that case we just ship out what is in \partialpage with the normal
+    % output routine.  Generally, \partialpage will be empty when this
+    % runs and this will be a no-op.  See the indexspread.tex test case.
+    \ifvoid\partialpage \else
+      \onepageout{\pagecontents\partialpage}%
+    \fi
+    %
     \global\setbox\partialpage = \vbox{%
       % Unvbox the main output page.
       \unvbox\PAGE
@@ -6016,9 +6134,11 @@ end
 
 % @raisesections: treat @section as chapter, @subsection as section, etc.
 \def\raisesections{\global\advance\secbase by -1}
+\let\up=\raisesections % original BFox name
 
 % @lowersections: treat @chapter as section, @section as subsection, etc.
 \def\lowersections{\global\advance\secbase by 1}
+\let\down=\lowersections % original BFox name
 
 % we only have subsub.
 \chardef\maxseclevel = 3
@@ -6670,8 +6790,13 @@ end
   % 1 and 2 (the page numbers aren't printed), and so are the first
   % two pages of the document.  Thus, we'd have two destinations named
   % `1', and two named `2'.
-  \ifpdforxetex
+  \ifpdf
     \global\pdfmakepagedesttrue
+  \else
+    \ifx\XeTeXrevision\thisisundefined
+    \else
+      \global\pdfmakepagedesttrue
+    \fi
   \fi
 }
 
@@ -7034,7 +7159,11 @@ end
 
 % @cartouche ... @end cartouche: draw rectangle w/rounded corners around
 % environment contents.
-
+\font\circle=lcircle10
+\newdimen\circthick
+\newdimen\cartouter\newdimen\cartinner
+\newskip\normbskip\newskip\normpskip\newskip\normlskip
+\circthick=\fontdimen8\circle
 %
 \def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth
 \def\ctr{{\hskip 6pt\circle\char'010}}
@@ -7049,18 +7178,7 @@ end
 %
 \newskip\lskip\newskip\rskip
 
-% only require the font if @cartouche is actually used
-\def\cartouchefontdefs{%
-  \font\circle=lcircle10\relax
-  \circthick=\fontdimen8\circle
-}
-\newdimen\circthick
-\newdimen\cartouter\newdimen\cartinner
-\newskip\normbskip\newskip\normpskip\newskip\normlskip
-
-
 \envdef\cartouche{%
-  \cartouchefontdefs
   \ifhmode\par\fi  % can't be in the midst of a paragraph.
   \startsavinginserts
   \lskip=\leftskip \rskip=\rightskip
@@ -7932,18 +8050,36 @@ end
   }
 \fi
 
+% alias because \c means cedilla in @tex or @math
+\let\texinfoc=\c
+
+\newcount\savedcatcodeone
+\newcount\savedcatcodetwo
+
 % Used at the time of macro expansion.
 % Argument is macro body with arguments substituted
 \def\scanmacro#1{%
   \newlinechar`\^^M
   \def\xeatspaces{\eatspaces}%
   %
+  % Temporarily undo catcode changes of \printindex.  Set catcode of @ to
+  % 0 so that @-commands in macro expansions aren't printed literally when 
+  % formatting an index file, where \ is used as the escape character.
+  \savedcatcodeone=\catcode`\@
+  \savedcatcodetwo=\catcode`\\
+  address@hidden
+  \catcode`\\=\active
+  %
   % Process the macro body under the current catcode regime.
-  address@hidden
+  address@hidden
   %
-  % The \comment is to remove the \newlinechar added by \scantokens, and
-  % can be noticed by \parsearg.  Note \c isn't used because this means 
cedilla 
-  % in math mode.
+  address@hidden
+  \catcode`\\=\savedcatcodetwo
+  %
+  % The \texinfoc is to remove the \newlinechar added by \scantokens, and
+  % can be noticed by \parsearg.
+  %   We avoid surrounding the call to \scantokens with \bgroup and \egroup
+  % to allow macros to open or close groups themselves.
 }
 
 % Used for copying and captions
@@ -8044,14 +8180,12 @@ end
 \def\macroargctxt{%
   \scanctxt
   \catcode`\ =\active
-  address@hidden
   \catcode`\^^M=\other
   \catcode`\\=\active
 }
 
 \def\macrolineargctxt{% used for whole-line arguments without braces
   \scanctxt
-  address@hidden
   \catcode`\{=\other
   \catcode`\}=\other
 }
@@ -8615,21 +8749,9 @@ end
 % also remove a trailing comma, in case of something like this:
 % @node Help-Cross,  ,  , Cross-refs
 \def\donode#1 ,#2\finishnodeparse{\dodonode #1,\finishnodeparse}
-\def\dodonode#1,#2\finishnodeparse{\gdef\lastnode{#1}\omittopnode}
-
-% Used so that the @top node doesn't have to be wrapped in an @ifnottex
-% conditional.
-% \doignore goes to more effort to skip nested conditionals but we don't need 
-% that here.
-\def\omittopnode{%
-   \ifx\lastnode\wordTop
-   \expandafter\ignorenode\fi
-}
-\def\wordTop{Top}
-
-% Divert output to a box that is not output until the next @node command.
-\def\ignorenode{\setbox\dummybox\vbox\bgroup\def\node{\egroup\node}}
+\def\dodonode#1,#2\finishnodeparse{\gdef\lastnode{#1}}
 
+\let\nwnode=\node
 \let\lastnode=\empty
 
 % Write a cross-reference definition for the current node.  #1 is the
@@ -9104,6 +9226,19 @@ end
   \catcode`\^^]=\other
   \catcode`\^^^=\other
   \catcode`\^^_=\other
+  % It was suggested to set the catcode of ^ to 7, which would allow ^^e4 etc.
+  % in xref tags, i.e., node names.  But since ^^e4 notation isn't
+  % supported in the main text, it doesn't seem desirable.  Furthermore,
+  % that is not enough: for node names that actually contain a ^
+  % character, we would end up writing a line like this: 'xrdef {'hat
+  % b-title}{'hat b} and \xrdef does a \csname...\endcsname on the first
+  % argument, and \hat is not an expandable control sequence.  It could
+  % all be worked out, but why?  Either we support ^^ or we don't.
+  %
+  % The other change necessary for this was to define \auxhat:
+  % \def\auxhat{\def^{'hat }}% extra space so ok if followed by letter
+  % and then to call \auxhat in \setq.
+  %
   \catcode`\^=\other
   %
   % Special characters.  Should be turned off anyway, but...
@@ -9121,7 +9256,14 @@ end
   \catcode`\%=\other
   \catcode`+=\other % avoid \+ for paranoia even though we've turned it off
   %
-  \catcode`\\=\active
+  % This is to support \ in node names and titles, since the \
+  % characters end up in a \csname.  It's easier than
+  % leaving it active and making its active definition an actual \
+  % character.  What I don't understand is why it works in the *value*
+  % of the xrdef.  Seems like it should be a catcode12 \, and that
+  % should not typeset properly.  But it works, so I'm moving on for
+  % now.  --karl, 15jan04.
+  \catcode`\\=\other
   %
   % @ is our escape character in .aux files, and we need braces.
   \catcode`\{=1
@@ -11392,9 +11534,11 @@ directory should work if nowhere else does.}
 % \backslashcurfont outputs one backslash character in current font,
 % as in \char`\\.
 \global\chardef\backslashcurfont=`\\
+\global\let\rawbackslashxx=\backslashcurfont  % let existing .??s files work
 
-% \realbackslash is an actual character `\' with catcode other.
-{\catcode`\\=\other @address@hidden
+% \realbackslash is an actual character `\' with catcode other, and
+% \doublebackslash is two of them (for the pdf outlines).
+{\catcode`\\=\other @address@hidden @address@hidden
 
 % In Texinfo, backslash is an active character; it prints the backslash
 % in fixed width font.
@@ -11412,8 +11556,10 @@ directory should work if nowhere else does.}
 @address@hidden@tt @ifmmode @mathchar29020 @else @backslashcurfont @fi}}
 @address@hidden = @ttbackslash % @backslashchar{} is for user documents.
 
+% \rawbackslash defines an active \ to do \backslashcurfont.
 % \otherbackslash defines an active \ to be a literal `\' character with
-% catcode other.
+% catcode other.  We switch back and forth between these.
address@hidden@address@hidden@backslashcurfont}
 @address@hidden@address@hidden
 
 % Same as @turnoffactive except outputs \ as {\tt\char`\\} instead of
@@ -11485,7 +11631,7 @@ directory should work if nowhere else does.}
   @address@hidden @let\ = @ttbackslash @fi
   @catcode13=5 % regular end of line
   @enableemergencynewline
-  @address@hidden@comment
+  @address@hidden@texinfoc
   @address@hidden@originalparsearg
   % Also turn back on active characters that might appear in the input
   % file name, in case not using a pre-dumped format.
diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi
index e376fc7..3dfd522 100644
--- a/doc/misc/tramp.texi
+++ b/doc/misc/tramp.texi
@@ -2,9 +2,8 @@
 @setfilename ../../info/tramp.info
 @c %**start of header
 @include docstyle.texi
address@hidden In the Tramp repository, the version number is auto-frobbed from
address@hidden configure.ac, so you should edit that file and run
address@hidden "autoconf && ./configure" to change the version number.
address@hidden In the Tramp GIT, the version number is auto-frobbed from 
tramp.el,
address@hidden and the bug report address is auto-frobbed from configure.ac.
 @include trampver.texi
 @settitle @value{tramp} @value{trampver} User Manual
 @c %**end of header
@@ -52,7 +51,7 @@ editing package for Emacs.
 
 @value{tramp} stands for ``Transparent Remote (file) Access, Multiple
 Protocol''.  This package provides remote file editing, similar to
-Ange FTP.
+Ange address@hidden
 
 The difference is that Ange FTP uses FTP to transfer files between the
 local and the remote host, whereas @value{tramp} uses a combination of
@@ -968,7 +967,7 @@ after a predefined timeout.
 @cindex @option{ftp} method
 
 When @value{tramp} uses @option{ftp}, it forwards requests to whatever
-ftp program is specified by Ange FTP.  This external program must be
+ftp program is specified by Ange address@hidden  This external program must be
 capable of servicing requests from @value{tramp}.
 
 @item @option{smb}
@@ -1092,8 +1091,8 @@ numbers are not applicable to Android devices connected 
through address@hidden
 The program @command{rclone} allows to access different system
 storages in the cloud, see @url{https://rclone.org/} for a list of
 supported systems.  If the @command{rclone} program isn't found in
-your @env{PATH} environment variable, you can tell Tramp its absolute
-path via the user option @code{tramp-rclone-program}.
+your @env{PATH} environment variable, you can tell @value{tramp} its
+absolute path via the user option @code{tramp-rclone-program}.
 
 A system storage must be configured via the @command{rclone config}
 command, outside Emacs.  If you have configured a storage in
@@ -1108,7 +1107,7 @@ User names are part of the @command{rclone} 
configuration, and not
 needed in the remote file name.  If a user name is contained in the
 remote file name, it is ignored.
 
-Internally, Tramp mounts the remote system storage at location
+Internally, @value{tramp} mounts the remote system storage at location
 @file{/tmp/tramp.rclone.storage}, with @file{storage} being the name
 of the configured system storage.
 
@@ -1538,8 +1537,8 @@ Host host.other.domain
 @end group
 @end example
 
address@hidden is BSD's netcat program, which establishes HTTP tunnels. Any
-other program with such a feature could be used as well.
address@hidden is BSD's netcat program, which establishes HTTP tunnels.
+Any other program with such a feature could be used as well.
 
 In the example, opening @address@hidden,host.your.domain,}} passes
 the HTTP proxy server @samp{proxy.your.domain} on port 3128.
@@ -1615,7 +1614,7 @@ Integration for LXD containers.  A container is accessed 
via
 @cindex method @option{git}
 @cindex @option{git} method
 Browing git repositories with @code{magit}.  A versioned file is accessed via
address@hidden@trampfn{git,rev@@root-dir,/path/to/file}}. @samp{rev} is a git
address@hidden@trampfn{git,rev@@root-dir,/path/to/file}}.  @samp{rev} is a git
 revision, and @samp{root-dir} is a virtual host name for the root
 directory, specified in @code{magit-tramp-hosts-alist}.
 
@@ -2642,7 +2641,7 @@ names.  Beside the @code{default} value, @var{syntax} can 
be
 @item @code{simplified}
 @cindex simplified syntax
 
-The remote file name syntax is similar to the syntax used by Ange FTP.
+The remote file name syntax is similar to the syntax used by Ange 
address@hidden
 A remote file name has the form
 @address@hidden@@address@hidden/to/file}.  The
 @code{user@@} part is optional, and the method is determined by
@@ -4372,7 +4371,7 @@ handlers.
 @vindex non-essential
 Sometimes, it is not convenient to open a new connection to a remote
 host, including entering the password and alike.  For example, this is
-nasty for packages providing file name completion. Such a package
+nasty for packages providing file name completion.  Such a package
 could signal to @value{tramp}, that they don't want it to establish a
 new connection.  Use the variable @code{non-essential} temporarily and
 bind it to address@hidden value.
diff --git a/etc/AUTHORS b/etc/AUTHORS
index 73c5245..2f7e015 100644
--- a/etc/AUTHORS
+++ b/etc/AUTHORS
@@ -163,7 +163,7 @@ Alexandru Harsanyi: wrote soap-client.el soap-inspect.el
 and changed emacs3.py vc-hooks.el vc.el xml.el
 
 Alex Branham: changed bibtex.el dired-x.el dired.el em-rebind.el eww.el
-  imenu.el modes.texi programs.texi
+  imenu.el indent.el modes.texi programs.texi text.texi
 
 Alex Coventry: changed files.el
 
@@ -442,8 +442,8 @@ Bartosz Duszel: changed allout.el bib-mode.el cc-cmds.el 
hexl.el icon.el
 
 Basil L. Contovounesios: changed simple.el message.el sequences.texi
   bibtex.el css-mode-tests.el css-mode.el customize.texi display.texi
-  gnus-art.el json-tests.el json.el lists.texi man.el modes.texi rcirc.el
-  shr-color.el text.texi url-handlers.el
+  gnus-art.el json-tests.el json.el lists.texi man.el modes.texi
+  newcomment.el rcirc.el shr-color.el text.texi url-handlers.el
 
 Bastian Beischer: changed include.el mru-bookmark.el refs.el
   semantic/complete.el senator.el
@@ -1354,8 +1354,8 @@ Eli Zaretskii: wrote [bidirectional display in xdisp.c]
   tty-colors.el
 and changed xdisp.c msdos.c w32.c display.texi w32fns.c simple.el
   files.el fileio.c keyboard.c w32proc.c files.texi w32term.c text.texi
-  dispnew.c frames.texi emacs.c dispextern.h lisp.h process.c term.c
-  window.c and 1125 other files
+  dispnew.c emacs.c frames.texi dispextern.h lisp.h window.c process.c
+  term.c and 1125 other files
 
 Emanuele Giaquinta: changed configure.ac rxvt.el charset.c etags.c
   fontset.c frame.el gnus-faq.texi loadup.el lread.c sh-script.el
@@ -1380,7 +1380,7 @@ Eric Abrahamsen: changed eieio-base.el registry.el 
nnimap.el
   gnus-registry.el files.el files.texi windows.texi eieio-test-persist.el
   eieio.el gnus-start.el gnus-sum.el gnus.texi nnir.el buffers.texi
   checkdoc.el files-tests.el gnus-bcklg.el gnus-group.el nnmairix.el
-  org.el org.texi and 3 other files
+  org.el org.texi and 4 other files
 
 Eric Bélanger: changed image.c
 
@@ -1682,9 +1682,9 @@ Geert Kloosterman: changed which-func.el
 Gemini Lasswell: wrote edebug-tests.el kmacro-tests.el testcover-tests.el
 and changed edebug.el cl-macs.el cl-generic.el ert-x.el cl-print.el
   edebug-test-code.el edebug.texi eieio-compat.el generator.el subr.el
-  autorevert-tests.el cl-print-tests.el emacs-lisp/debug.el eval-tests.el
-  eval.c filenotify-tests.el generator-tests.el kmacro.el lread.c
-  map-tests.el map.el and 9 other files
+  autorevert-tests.el cl-print-tests.el eieio.texi emacs-lisp/debug.el
+  eval-tests.el eval.c filenotify-tests.el generator-tests.el kmacro.el
+  lread.c map-tests.el and 10 other files
 
 Geoff Gole: changed align.el ibuffer.el whitespace.el
 
@@ -3258,6 +3258,8 @@ Matt Hodges: changed textmodes/table.el faces.el 
iswitchb.el simple.el
   edebug.texi eldoc.el em-hist.el em-pred.el fixit.texi icon.el ido.el
   locate.el paragraphs.el pcomplete.el repeat.el and 3 other files
 
+Mattias Engdegård: changed subr.el
+
 Matt Lundin: changed org-agenda.el org.el org-bibtex.el org-footnote.el
   ox-publish.el org-bbdb.el org-datetree.el org-gnus.el
 
@@ -3270,7 +3272,7 @@ Matt Simmons: changed message.el
 Matt Swift: changed dired.el editfns.c lisp-mode.el mm-decode.el
   outline.el progmodes/compile.el rx.el simple.el startup.el
 
-Mauro Aranda: changed files.texi os.texi
+Mauro Aranda: changed autorevert.el files.texi os.texi
 
 Maxime Edouard Robert Froumentin: changed gnus-art.el mml.el
 
@@ -3649,7 +3651,7 @@ Noam Postavsky: changed lisp-mode.el progmodes/python.el 
xdisp.c
   cl-macs.el lisp-mode-tests.el emacs-lisp/debug.el data.c simple.el
   term.el ert.el subr.el help-fns.el bytecomp.el cl-print.el
   elisp-mode.el eval.c ffap.el modes.texi search.c sh-script.el
-  cl-preloaded.el and 248 other files
+  cl-preloaded.el and 249 other files
 
 Nobuyoshi Nakada: co-wrote ruby-mode.el
 
diff --git a/etc/HISTORY b/etc/HISTORY
index b239904..bf03692 100644
--- a/etc/HISTORY
+++ b/etc/HISTORY
@@ -216,6 +216,8 @@ GNU Emacs 25.3 (2017-09-11) emacs-25.3
 
 GNU Emacs 26.1 (2018-05-28) emacs-26.1
 
+GNU Emacs 26.2 (2019-04-12) emacs-26.2
+
 
 ----------------------------------------------------------------------
 This file is part of GNU Emacs.
diff --git a/etc/NEWS b/etc/NEWS
index f41db02..82d27d7 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -847,6 +847,9 @@ directories in the destination.
 ** Help
 
 ---
+*** Description of variables and functions give an estimated first release
+
+---
 *** Output format of 'C-h l' ('view-lossage') has changed.
 For convenience, 'view-lossage' now displays the last keystrokes
 and commands in the same format as the edit buffer of
@@ -1061,6 +1064,12 @@ followed when Emacs writes the relevant history 
variables to the disk.
 *** The variable 'shell-file-name' can be set now as connection-local
 variable for remote shells.  It still defaults to "/bin/sh".
 
+** Single shell commands
+
+---
+*** 'shell-command-width' defines the number of display columns
+available for output of asynchronous shell commands.
+
 ** Pcomplete
 
 *** The function 'pcomplete-uniquify-list' has been renamed from
@@ -1497,6 +1506,9 @@ performs (setq-local indent-line-function 
#'indent-relative).
 
 * Lisp Changes in Emacs 27.1
 
+** New 'help-fns-describe-variable-functions' hook.
+Makes it possible to add metadata information to describe-variable.
+
 ** i18n (internationalization)
 
 *** ngettext can be used now to return the right plural form
diff --git a/etc/NEWS.1-17 b/etc/NEWS.1-17
index 758ef65..1ce36fe 100644
--- a/etc/NEWS.1-17
+++ b/etc/NEWS.1-17
@@ -2339,9 +2339,9 @@ It's Beat CCA Week.
 
 ** Lisp macros now exist.
  For example, you can write
-    (defmacro cadr (arg) (list 'car (list 'cdr arg)))
+    (defmacro mycadr (arg) (list 'car (list 'cdr arg)))
  and then the expression
-    (cadr foo)
+    (mycadr foo)
  will expand into
     (car (cdr foo))
 
diff --git a/lib/_Noreturn.h b/lib/_Noreturn.h
index 7594e4b..db9b455 100644
--- a/lib/_Noreturn.h
+++ b/lib/_Noreturn.h
@@ -1,3 +1,19 @@
+/* A C macro for declaring that a function does not return.
+   Copyright (C) 2011-2019 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
 #ifndef _Noreturn
 # if (defined __cplusplus \
       && ((201103 <= __cplusplus && !(__GNUC__ == 4 && __GNUC_MINOR__ == 7)) \
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in
index 0d9a885..1450df9 100644
--- a/lib/gnulib.mk.in
+++ b/lib/gnulib.mk.in
@@ -179,6 +179,7 @@ CAIRO_LIBS = @CAIRO_LIBS@
 CC = @CC@
 CFLAGS = @CFLAGS@
 CFLAGS_SOUND = @CFLAGS_SOUND@
+CHECK_STRUCTS = @CHECK_STRUCTS@
 CLIENTRES = @CLIENTRES@
 CLIENTW = @CLIENTW@
 CM_OBJ = @CM_OBJ@
diff --git a/lisp/align.el b/lisp/align.el
index fd88d0e..443237b 100644
--- a/lisp/align.el
+++ b/lisp/align.el
@@ -411,7 +411,7 @@ The possible settings for `align-region-separate' are:
     (c-variable-declaration
      (regexp   . ,(concat "[*&0-9A-Za-z_]>?[&*]*\\(\\s-+[*&]*\\)"
                          "[A-Za-z_][0-9A-Za-z:_]*\\s-*\\(\\()\\|"
-                         "=[^=\n].*\\|(.*)\\|\\(\\[.*\\]\\)*\\)?"
+                         "=[^=\n].*\\|(.*)\\|\\(\\[.*\\]\\)*\\)"
                          "\\s-*[;,]\\|)\\s-*$\\)"))
      (group    . 1)
      (modes    . align-c++-modes)
diff --git a/lisp/cedet/srecode/srt-mode.el b/lisp/cedet/srecode/srt-mode.el
index 2ad7ffc..6bf2d51 100644
--- a/lisp/cedet/srecode/srt-mode.el
+++ b/lisp/cedet/srecode/srt-mode.el
@@ -64,7 +64,7 @@
 (defvar srecode-font-lock-keywords
   '(
     ;; Template
-    ("^\\(template\\)\\s-+\\(\\w*\\)\\(\\( \\(:\\w+\\)\\|\\)+\\)$"
+    ("^\\(template\\)\\s-+\\(\\w*\\)\\(\\( \\(:\\w+\\)\\)*\\)$"
      (1 font-lock-keyword-face)
      (2 font-lock-function-name-face)
      (3 font-lock-builtin-face ))
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index 33d4964..44cca61 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -879,7 +879,8 @@
 (put 'symbolp 'byte-optimizer 'byte-optimize-predicate)
 (put 'stringp 'byte-optimizer 'byte-optimize-predicate)
 (put 'string< 'byte-optimizer 'byte-optimize-predicate)
-(put 'string-lessp 'byte-optimizer 'byte-optimize-predicate)
+(put 'string-lessp  'byte-optimizer 'byte-optimize-predicate)
+(put 'proper-list-p 'byte-optimizer 'byte-optimize-predicate)
 
 (put 'logand 'byte-optimizer 'byte-optimize-predicate)
 (put 'logior 'byte-optimizer 'byte-optimize-predicate)
diff --git a/lisp/emacs-lisp/copyright.el b/lisp/emacs-lisp/copyright.el
index 2726bbc..be33583 100644
--- a/lisp/emacs-lisp/copyright.el
+++ b/lisp/emacs-lisp/copyright.el
@@ -52,7 +52,7 @@ This is useful for ChangeLogs."
 (defcustom copyright-regexp
  "\\(©\\|@copyright{}\\|[Cc]opyright\\s *:?\\s *\\(?:(C)\\)?\
 \\|[Cc]opyright\\s *:?\\s *©\\)\
-\\s *\\(?:[^0-9\n]*\\s *\\)?\
+\\s *[^0-9\n]*\\s *\
 \\([1-9]\\([-0-9, ';/*%#\n\t]\\|\\s<\\|\\s>\\)*[0-9]+\\)"
   "What your copyright notice looks like.
 The second \\( \\) construct must match the years."
diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el
index 2854cde..210830a 100644
--- a/lisp/erc/erc-backend.el
+++ b/lisp/erc/erc-backend.el
@@ -1285,7 +1285,7 @@ add things to `%s' instead."
     (pcase-let ((`(,nick ,login ,host)
                  (erc-parse-user (erc-response.sender parsed))))
       ;; strip the stupid combined JOIN facility (IRC 2.9)
-      (if (string-match "^\\(.*\\)?\^g.*$" chnl)
+      (if (string-match "^\\(.*\\)\^g.*$" chnl)
           (setq chnl (match-string 1 chnl)))
       (save-excursion
         (let* ((str (cond
diff --git a/lisp/erc/erc-desktop-notifications.el 
b/lisp/erc/erc-desktop-notifications.el
index 56b9392..41b7420 100644
--- a/lisp/erc/erc-desktop-notifications.el
+++ b/lisp/erc/erc-desktop-notifications.el
@@ -1,4 +1,4 @@
-;; erc-desktop-notifications.el -- Send notification on PRIVMSG or mentions
+;; erc-desktop-notifications.el -- Send notification on PRIVMSG or mentions 
-*- lexical-binding:t -*-
 
 ;; Copyright (C) 2012-2019 Free Software Foundation, Inc.
 
@@ -59,13 +59,19 @@
 This will replace the last notification sent with this function."
   (dbus-ignore-errors
     (setq erc-notifications-last-notification
-          (notifications-notify :bus erc-notifications-bus
-                               :title (xml-escape-string nick)
-                                :body (xml-escape-string msg)
-                                :replaces-id 
erc-notifications-last-notification
-                                :app-icon erc-notifications-icon))))
-
-(defun erc-notifications-PRIVMSG (proc parsed)
+          (let ((channel (current-buffer)))
+            (notifications-notify :bus erc-notifications-bus
+                                  :title (format "%s in %s"
+                                                 (xml-escape-string nick)
+                                                 channel)
+                                  :body (xml-escape-string msg)
+                                  :replaces-id 
erc-notifications-last-notification
+                                  :app-icon erc-notifications-icon
+                                  :actions '("default" "Switch to buffer")
+                                  :on-action (lambda (&rest _)
+                                               (pop-to-buffer channel)))))))
+
+(defun erc-notifications-PRIVMSG (_proc parsed)
   (let ((nick (car (erc-parse-user (erc-response.sender parsed))))
         (target (car (erc-response.command-args parsed)))
         (msg (erc-response.contents parsed)))
diff --git a/lisp/erc/erc-goodies.el b/lisp/erc/erc-goodies.el
index 117b678..884c594 100644
--- a/lisp/erc/erc-goodies.el
+++ b/lisp/erc/erc-goodies.el
@@ -548,7 +548,7 @@ channel that has weird people talking in morse to each 
other.
 
 See also `unmorse-region'."
   (goto-char (point-min))
-  (when (re-search-forward "[.-]+\\([.-]*/? *\\)+[.-]+/?" nil t)
+  (when (re-search-forward "[.-]+[./ -]*[.-]/?" nil t)
     (save-restriction
       (narrow-to-region (match-beginning 0) (match-end 0))
       ;; Turn " / " into "  "
diff --git a/lisp/gnus/gnus-group.el b/lisp/gnus/gnus-group.el
index 144496b..b1e4091 100644
--- a/lisp/gnus/gnus-group.el
+++ b/lisp/gnus/gnus-group.el
@@ -1320,7 +1320,7 @@ if it is a string, only list groups matching REGEXP."
              gnus-group-listed-groups)
       ;; List living groups, according to order in `gnus-group-list'.
       (dolist (g (cdr gnus-group-list))
-       (setq info (nth 1 (gethash g gnus-newsrc-hashtb))
+        (setq info (gnus-get-info g)
              group (gnus-info-group info)
              params (gnus-info-params info)
              unread (gnus-group-unread group))
@@ -1389,39 +1389,35 @@ if it is a string, only list groups matching REGEXP."
   ;; List zombies and killed lists somewhat faster, which was
   ;; suggested by Jack Vinson <address@hidden>.  It does
   ;; this by ignoring the group format specification altogether.
-  (let (group)
-    (if (> (length groups) gnus-group-listing-limit)
-       (while groups
-         (setq group (pop groups))
-         (when (gnus-group-prepare-logic
-                group
-                (or (not regexp)
-                    (and (stringp regexp) (string-match regexp group))
-                    (and (functionp regexp) (funcall regexp group))))
-           (add-text-properties
-            (point) (prog1 (1+ (point))
-                      (insert " " mark "     *: "
-                              (gnus-group-decoded-name group)
-                              "\n"))
-            (list 'gnus-group (gethash group gnus-active-hashtb)
-                  'gnus-unread t
-                  'gnus-level level))))
-      (while groups
-       (setq group (pop groups))
+  (if (nthcdr gnus-group-listing-limit groups)
+      (dolist (group groups)
        (when (gnus-group-prepare-logic
               group
-              (or (not regexp)
-                  (and (stringp regexp) (string-match regexp group))
-                  (and (functionp regexp) (funcall regexp group))))
-         (gnus-group-insert-group-line
-          group level nil
-          (let ((active (gnus-active group)))
-            (if active
-                (if (zerop (cdr active))
-                    0
-                  (- (1+ (cdr active)) (car active)))
-              nil))
-          (gnus-method-simplify (gnus-find-method-for-group group))))))))
+               (cond ((not regexp))
+                     ((stringp regexp) (string-match-p regexp group))
+                     ((functionp regexp) (funcall regexp group))))
+          (add-text-properties
+           (point) (prog1 (1+ (point))
+                     (insert " " mark "     *: "
+                             (gnus-group-decoded-name group)
+                             "\n"))
+           (list 'gnus-group group
+                 'gnus-unread t
+                 'gnus-level level))))
+    (dolist (group groups)
+      (when (gnus-group-prepare-logic
+             group
+             (cond ((not regexp))
+                   ((stringp regexp) (string-match-p regexp group))
+                   ((functionp regexp) (funcall regexp group))))
+        (gnus-group-insert-group-line
+         group level nil
+         (let ((active (gnus-active group)))
+           (and active
+                (if (zerop (cdr active))
+                    0
+                  (- (cdr active) (car active) -1))))
+         (gnus-method-simplify (gnus-find-method-for-group group)))))))
 
 (defun gnus-group-update-group-line ()
   "Update the current line in the group buffer."
@@ -1527,7 +1523,7 @@ if it is a string, only list groups matching REGEXP."
              (int-to-string (max 0 (- gnus-tmp-number-total number)))
            "*"))
         (gnus-tmp-subscribed
-         (cond ((<= gnus-tmp-level gnus-level-subscribed) ? )
+          (cond ((<= gnus-tmp-level gnus-level-subscribed) ?\s)
                ((<= gnus-tmp-level gnus-level-unsubscribed) ?U)
                ((= gnus-tmp-level gnus-level-zombie) ?Z)
                (t ?K)))
@@ -1546,7 +1542,7 @@ if it is a string, only list groups matching REGEXP."
         (gnus-tmp-moderated
          (if (and gnus-moderated-hashtb
                   (gethash gnus-tmp-group gnus-moderated-hashtb))
-             ?m ? ))
+              ?m ?\s))
         (gnus-tmp-moderated-string
          (if (eq gnus-tmp-moderated ?m) "(m)" ""))
          (gnus-tmp-group-icon (gnus-group-get-icon gnus-tmp-group))
@@ -1560,15 +1556,15 @@ if it is a string, only list groups matching REGEXP."
          (if (and (numberp number)
                   (zerop number)
                   (cdr (assq 'tick gnus-tmp-marked)))
-             ?* ? ))
+              ?* ?\s))
         (gnus-tmp-summary-live
          (if (and (not gnus-group-is-exiting-p)
                   (gnus-buffer-live-p (gnus-summary-buffer-name
                                        gnus-tmp-group)))
-             ?* ? ))
+              ?* ?\s))
         (gnus-tmp-process-marked
          (if (member gnus-tmp-group gnus-group-marked)
-             gnus-process-mark ? ))
+              gnus-process-mark ?\s))
         (buffer-read-only nil)
         beg end
          gnus-tmp-header)        ; passed as parameter to user-funcs.
@@ -1768,10 +1764,8 @@ already.  If INFO-UNCHANGED is non-nil, dribble buffer 
is not updated."
 (defun gnus-group-group-name ()
   "Get the name of the newsgroup on the current line."
   (let ((group (get-text-property (point-at-bol) 'gnus-group)))
-    (when group
-      (if (stringp group)
-         group
-       (symbol-name group)))))
+    (cond ((stringp group) group)
+          (group (symbol-name group)))))
 
 (defun gnus-group-group-level ()
   "Get the level of the newsgroup on the current line."
@@ -1791,7 +1785,7 @@ already.  If INFO-UNCHANGED is non-nil, dribble buffer is 
not updated."
 (defun gnus-group-new-mail (group)
   (if (nnmail-new-mail-p (gnus-group-real-name group))
       gnus-new-mail-mark
-    ? ))
+    ?\s))
 
 (defun gnus-group-level (group)
   "Return the estimated level of GROUP."
@@ -1881,7 +1875,7 @@ If FIRST-TOO, the current line is also eligible as a 
target."
        (if unmark
            (progn
              (setq gnus-group-marked (delete group gnus-group-marked))
-             (insert-char ? 1 t))
+              (insert-char ?\s 1 t))
           (setq gnus-group-marked
                 (cons group (delete group gnus-group-marked)))
           (insert-char gnus-process-mark 1 t)))
@@ -2561,10 +2555,10 @@ If TEST-MARKED, the line must be marked."
   (when group
     (let ((start (point))
          (active (and (or
-                       ;; some kind of group may be only there.
-                       (gethash group gnus-active-hashtb)
-                       ;; all groups (but with exception) are there.
-                       (gethash group gnus-newsrc-hashtb))
+                        ;; Some kind of group may be only there.
+                        (gnus-active group)
+                        ;; All groups (but with exception) are there.
+                        (gnus-group-entry group))
                       group)))
       (beginning-of-line)
       (cond
@@ -4013,15 +4007,9 @@ entail asking the server for the groups."
          (gnus-agent gnus-plugged)); If we're actually plugged, store the 
active file in the agent.
       (gnus-read-active-file)))
   ;; Find all groups and sort them.
-  (let ((groups
-        (sort
-         (hash-table-keys gnus-active-hashtb)
-         'string<))
-       (buffer-read-only nil)
-       group)
+  (let ((buffer-read-only nil))
     (erase-buffer)
-    (while groups
-      (setq group (pop groups))
+    (dolist (group (sort (hash-table-keys gnus-active-hashtb) #'string<))
       (add-text-properties
        (point) (prog1 (1+ (point))
                 (insert "       *: "
@@ -4149,20 +4137,19 @@ If DONT-SCAN is non-nil, scan non-activated groups as 
well."
   (when (not (or gnus-description-hashtb
                 (gnus-read-all-descriptions-files)))
     (error "Couldn't request descriptions file"))
-  (let ((buffer-read-only nil)
-       (groups (sort (hash-table-keys gnus-description-hashtb)))
-       b)
+  (let ((buffer-read-only nil))
     (erase-buffer)
-    (dolist (group groups)
-      (setq b (point))
-      (let ((charset (gnus-group-name-charset nil group)))
+    (dolist (group (sort (hash-table-keys gnus-description-hashtb) #'string<))
+      (let ((b (point))
+            (desc (gethash group gnus-description-hashtb))
+            (charset (gnus-group-name-charset nil group)))
        (insert (format "      *: %-20s %s\n"
                        (gnus-group-name-decode group charset)
-                       (gnus-group-name-decode group charset))))
-      (add-text-properties
-       b (1+ b) (list 'gnus-group (intern group gnus-description-hashtb)
-                     'gnus-unread t 'gnus-marked nil
-                     'gnus-level (1+ gnus-level-subscribed))))
+                        (gnus-group-name-decode desc charset)))
+        (add-text-properties
+         b (1+ b) (list 'gnus-group group
+                        'gnus-unread t 'gnus-marked nil
+                        'gnus-level (1+ gnus-level-subscribed)))))
     (goto-char (point-min))
     (gnus-group-position-point)))
 
diff --git a/lisp/help-fns.el b/lisp/help-fns.el
index 06b4ec8..50d69e7 100644
--- a/lisp/help-fns.el
+++ b/lisp/help-fns.el
@@ -40,7 +40,21 @@
   "List of functions to run in help buffer in `describe-function'.
 Those functions will be run after the header line and argument
 list was inserted, and before the documentation will be inserted.
-The functions will receive the function name as argument.")
+The functions will receive the function name as argument.
+They can assume that a newline was output just before they were called,
+and they should terminate any of their own output with a newline.
+By convention they should indent their output by 2 spaces.")
+
+(defvar help-fns-describe-variable-functions nil
+  "List of functions to run in help buffer in `describe-variable'.
+Those functions will be run after the header line and value was inserted,
+and before the documentation will be inserted.
+The functions will receive the variable name as argument.
+They can assume that a newline was output just before they were called,
+and they should terminate any of their own output with a newline.
+By convention they should indent their output by 2 spaces.
+Current buffer is the buffer in which we queried the variable,
+and the output should go to `standard-output'.")
 
 ;; Functions
 
@@ -412,7 +426,7 @@ suitable file is found, return nil."
 (defun help-fns--compiler-macro (function)
   (let ((handler (function-get function 'compiler-macro)))
     (when handler
-      (insert "\nThis function has a compiler macro")
+      (insert "  This function has a compiler macro")
       (if (symbolp handler)
           (progn
             (insert (format-message " `%s'" handler))
@@ -486,7 +500,7 @@ suitable file is found, return nil."
                           (get function
                                'derived-mode-parent))))
     (when parent-mode
-      (insert (substitute-command-keys "\nParent mode: `"))
+      (insert (substitute-command-keys "  Parent mode: `"))
       (let ((beg (point)))
         (insert (format "%s" parent-mode))
         (make-text-button beg (point)
@@ -500,15 +514,15 @@ suitable file is found, return nil."
                        (get function 'byte-obsolete-info)))
          (use (car obsolete)))
     (when obsolete
-      (insert "\nThis "
+      (insert "  This "
              (if (eq (car-safe (symbol-function function)) 'macro)
                  "macro"
                "function")
              " is obsolete")
       (when (nth 2 obsolete)
         (insert (format " since %s" (nth 2 obsolete))))
-      (insert (cond ((stringp use) (concat ";\n" use))
-                    (use (format-message ";\nuse `%s' instead." use))
+      (insert (cond ((stringp use) (concat ";\n  " use))
+                    (use (format-message ";\n  use `%s' instead." use))
                     (t "."))
               "\n"))))
 
@@ -538,17 +552,65 @@ FILE is the file where FUNCTION was probably defined."
                        (memq function
                              byte-compile-interactive-only-functions)))))
          (when interactive-only
-           (insert "\nThis function is for interactive use only"
+           (insert "  This function is for interactive use only"
                    ;; Cf byte-compile-form.
                    (cond ((stringp interactive-only)
-                          (format ";\nin Lisp code %s" interactive-only))
+                          (format ";\n  in Lisp code %s" interactive-only))
                          ((and (symbolp 'interactive-only)
                                (not (eq interactive-only t)))
-                          (format-message ";\nin Lisp code use `%s' instead."
+                          (format-message ";\n  in Lisp code use `%s' instead."
                                           interactive-only))
                          (t "."))
                    "\n")))))
 
+(add-hook 'help-fns-describe-function-functions #'help-fns--side-effects)
+(defun help-fns--side-effects (function)
+  (when (and (symbolp function)
+             (or (function-get function 'pure)
+                 (function-get function 'side-effect-free)))
+    (insert "  This function does not change global state, "
+            "including the match data.\n")))
+
+(defun help-fns--first-release (symbol)
+  "Return the likely first release that defined SYMBOL."
+  ;; Code below relies on the etc/NEWS* files.
+  ;; FIXME: Maybe we should also use the */ChangeLog* files when available.
+  ;; FIXME: Maybe we should also look for announcements of the addition
+  ;; of the *packages* in which the function is defined.
+  (let* ((name (symbol-name symbol))
+         (re (concat "\\_<" (regexp-quote name) "\\_>"))
+         (news (directory-files data-directory t "\\`NEWS.[1-9]"))
+         (first nil))
+    (with-temp-buffer
+      (dolist (f news)
+        (erase-buffer)
+        (insert-file-contents f)
+        (goto-char (point-min))
+        (search-forward "\n*")
+        (while (re-search-forward re nil t)
+          (save-excursion
+            ;; Almost all entries are of the form "* ... in Emacs NN.MM."
+            ;; but there are also a few in the form "* Emacs NN.MM is a bug
+            ;; fix release ...".
+            (if (not (re-search-backward "^\\*.* Emacs \\([0-9.]+[0-9]\\)"
+                                         nil t))
+                (message "Ref found in non-versioned section in %S"
+                         (file-name-nondirectory f))
+              (let ((version (match-string 1)))
+                (when (or (null first) (version< version first))
+                  (setq first version))))))))
+    first))
+
+(add-hook 'help-fns-describe-function-functions
+          #'help-fns--mention-first-release)
+(add-hook 'help-fns-describe-variable-functions
+          #'help-fns--mention-first-release)
+(defun help-fns--mention-first-release (object)
+  (let ((first (if (symbolp object) (help-fns--first-release object))))
+    (when first
+      (princ (format "  Probably introduced at or before Emacs version %s.\n"
+                     first)))))
+
 (defun help-fns-short-filename (filename)
   (let* ((abbrev (abbreviate-file-name filename))
          (short abbrev))
@@ -611,9 +673,9 @@ Returns a list of the form (REAL-FUNCTION DEF ALIASED 
REAL-DEF)."
                                  (memq (car-safe def) '(macro lambda closure)))
                              (stringp file-name)
                              (help-fns--autoloaded-p function file-name))
-                        (if (commandp def)
-                            "an interactive autoloaded "
-                          "an autoloaded ")
+                        (concat
+                         "an autoloaded " (if (commandp def)
+                                              "interactive "))
                       (if (commandp def) "an interactive " "a "))))
 
     ;; Print what kind of function-like object FUNCTION is.
@@ -627,14 +689,16 @@ Returns a list of the form (REAL-FUNCTION DEF ALIASED 
REAL-DEF)."
                 (aliased
                  (format-message "an alias for `%s'" real-def))
                 ((subrp def)
-                 (if (eq 'unevalled (cdr (subr-arity def)))
-                     (concat beg "special form")
-                   (concat beg "built-in function")))
+                 (concat beg (if (eq 'unevalled (cdr (subr-arity def)))
+                                 "special form"
+                                "built-in function")))
                 ((autoloadp def)
-                 (format "%s autoloaded %s"
-                         (if (commandp def) "an interactive" "an")
-                         (if (eq (nth 4 def) 'keymap) "keymap"
-                           (if (nth 4 def) "Lisp macro" "Lisp function"))))
+                 (format "an autoloaded %s"
+                          (cond
+                          ((commandp def) "interactive Lisp function")
+                          ((eq (nth 4 def) 'keymap) "keymap")
+                          ((nth 4 def) "Lisp macro")
+                           (t "Lisp function"))))
                 ((or (eq (car-safe def) 'macro)
                      ;; For advised macros, def is a lambda
                      ;; expression or a byte-code-function-p, so we
@@ -685,6 +749,10 @@ Returns a list of the form (REAL-FUNCTION DEF ALIASED 
REAL-DEF)."
            (help-xref-button 1 'help-function-def function file-name))))
       (princ "."))))
 
+(defun help-fns--ensure-empty-line ()
+  (unless (eolp) (insert "\n"))
+  (unless (eq ?\n (char-before (1- (point)))) (insert "\n")))
+
 ;;;###autoload
 (defun describe-function-1 (function)
   (let ((pt1 (with-current-buffer (help-buffer) (point))))
@@ -722,12 +790,10 @@ Returns a list of the form (REAL-FUNCTION DEF ALIASED 
REAL-DEF)."
                       real-function key-bindings-buffer)
                    ;; E.g. an alias for a not yet defined function.
                    ((invalid-function void-function) doc-raw))))
+        (help-fns--ensure-empty-line)
         (run-hook-with-args 'help-fns-describe-function-functions function)
-        (insert "\n" (or doc "Not documented.")))
-      (when (or (function-get function 'pure)
-                (function-get function 'side-effect-free))
-        (insert "\nThis function does not change global state, "
-                "including the match data."))
+        (help-fns--ensure-empty-line)
+        (insert (or doc "Not documented.")))
       ;; Avoid asking the user annoying questions if she decides
       ;; to save the help buffer, when her locale's codeset
       ;; isn't UTF-8.
@@ -830,7 +896,6 @@ it is displayed along with the global value."
        (message "You did not specify a variable")
       (save-excursion
        (let ((valvoid (not (with-current-buffer buffer (boundp variable))))
-             (permanent-local (get variable 'permanent-local))
              val val-start-pos locus)
          ;; Extract the value before setting up the output buffer,
          ;; in case `buffer' *is* the output buffer.
@@ -846,26 +911,26 @@ it is displayed along with the global value."
              (prin1 variable)
              (setq file-name (find-lisp-object-file-name variable 'defvar))
 
-             (if file-name
-                 (progn
-                   (princ (format-message
-                            " is a variable defined in `%s'.\n"
-                            (if (eq file-name 'C-source)
-                                "C source code"
-                              (file-name-nondirectory file-name))))
-                   (with-current-buffer standard-output
-                     (save-excursion
-                       (re-search-backward (substitute-command-keys
-                                             "`\\([^`']+\\)'")
-                                            nil t)
-                       (help-xref-button 1 'help-variable-def
-                                         variable file-name)))
-                   (if valvoid
-                       (princ "It is void as a variable.")
-                     (princ "Its ")))
-               (if valvoid
-                   (princ " is void as a variable.")
-                 (princ (substitute-command-keys "'s ")))))
+             (princ (if file-name
+                        (progn
+                          (princ (format-message
+                                   " is a variable defined in `%s'.\n"
+                                   (if (eq file-name 'C-source)
+                                       "C source code"
+                                     (file-name-nondirectory file-name))))
+                          (with-current-buffer standard-output
+                            (save-excursion
+                              (re-search-backward (substitute-command-keys
+                                                    "`\\([^`']+\\)'")
+                                                   nil t)
+                              (help-xref-button 1 'help-variable-def
+                                                variable file-name)))
+                          (if valvoid
+                              "It is void as a variable."
+                             "Its "))
+                       (if valvoid
+                          " is void as a variable."
+                         (substitute-command-keys "'s ")))))
            (unless valvoid
              (with-current-buffer standard-output
                (setq val-start-pos (point))
@@ -894,7 +959,7 @@ it is displayed along with the global value."
                  (let* ((sv (get variable 'standard-value))
                         (origval (and (consp sv)
                                       (condition-case nil
-                                          (eval (car sv))
+                                          (eval (car sv) t)
                                         (error :help-eval-error))))
                          from)
                    (when (and (consp sv)
@@ -969,132 +1034,17 @@ it is displayed along with the global value."
             (let* ((alias (condition-case nil
                               (indirect-variable variable)
                             (error variable)))
-                   (obsolete (get variable 'byte-obsolete-variable))
-                   (watchpoints (get-variable-watchers variable))
-                  (use (car obsolete))
-                  (safe-var (get variable 'safe-local-variable))
                    (doc (or (documentation-property
                              variable 'variable-documentation)
                             (documentation-property
-                             alias 'variable-documentation)))
-                   (extra-line nil))
+                             alias 'variable-documentation))))
 
-             ;; Mention if it's a local variable.
-             (cond
-              ((and (local-variable-if-set-p variable)
-                    (or (not (local-variable-p variable))
-                        (with-temp-buffer
-                          (local-variable-if-set-p variable))))
-                (setq extra-line t)
-                (princ "  Automatically becomes ")
-               (if permanent-local
-                   (princ "permanently "))
-               (princ "buffer-local when set.\n"))
-              ((not permanent-local))
-              ((bufferp locus)
-               (setq extra-line t)
-               (princ
-                (substitute-command-keys
-                 "  This variable's buffer-local value is permanent.\n")))
-              (t
-               (setq extra-line t)
-                (princ (substitute-command-keys
-                       "  This variable's value is permanent \
-if it is given a local binding.\n"))))
-
-             ;; Mention if it's an alias.
-              (unless (eq alias variable)
-                (setq extra-line t)
-                (princ (format-message
-                        "  This variable is an alias for `%s'.\n"
-                        alias)))
-
-              (when obsolete
-                (setq extra-line t)
-                (princ "  This variable is obsolete")
-                (if (nth 2 obsolete)
-                    (princ (format " since %s" (nth 2 obsolete))))
-               (princ (cond ((stringp use) (concat ";\n  " use))
-                            (use (format-message ";\n  use `%s' instead."
-                                                  (car obsolete)))
-                            (t ".")))
-                (terpri))
-
-              (when watchpoints
-                (setq extra-line t)
-                (princ "  Calls these functions when changed: ")
-                (princ watchpoints)
-                (terpri))
-
-             (when (member (cons variable val)
-                            (with-current-buffer buffer
-                              file-local-variables-alist))
-               (setq extra-line t)
-               (if (member (cons variable val)
-                             (with-current-buffer buffer
-                               dir-local-variables-alist))
-                   (let ((file (and (buffer-file-name buffer)
-                                      (not (file-remote-p
-                                            (buffer-file-name buffer)))
-                                      (dir-locals-find-file
-                                       (buffer-file-name buffer))))
-                          (is-directory nil))
-                     (princ (substitute-command-keys
-                             "  This variable's value is directory-local"))
-                      (when (consp file) ; result from cache
-                        ;; If the cache element has an mtime, we
-                        ;; assume it came from a file.
-                        (if (nth 2 file)
-                            ;; (car file) is a directory.
-                            (setq file (dir-locals--all-files (car file)))
-                          ;; Otherwise, assume it was set directly.
-                          (setq file (car file)
-                                is-directory t)))
-                      (if (null file)
-                          (princ ".\n")
-                        (princ ", set ")
-                        (princ (substitute-command-keys
-                                (cond
-                                 (is-directory "for the directory\n  `")
-                                 ;; Many files matched.
-                                 ((and (consp file) (cdr file))
-                                  (setq file (file-name-directory (car file)))
-                                  (format "by one of the\n  %s files in the 
directory\n  `"
-                                          dir-locals-file))
-                                 (t (setq file (car file))
-                                    "by the file\n  `"))))
-                       (with-current-buffer standard-output
-                         (insert-text-button
-                          file 'type 'help-dir-local-var-def
-                             'help-args (list variable file)))
-                       (princ (substitute-command-keys "'.\n"))))
-                 (princ (substitute-command-keys
-                         "  This variable's value is file-local.\n"))))
-
-             (when (memq variable ignored-local-variables)
-               (setq extra-line t)
-               (princ "  This variable is ignored as a file-local \
-variable.\n"))
-
-             ;; Can be both risky and safe, eg auto-fill-function.
-             (when (risky-local-variable-p variable)
-               (setq extra-line t)
-               (princ "  This variable may be risky if used as a \
-file-local variable.\n")
-               (when (assq variable safe-local-variable-values)
-                 (princ (substitute-command-keys
-                          "  However, you have added it to \
-`safe-local-variable-values'.\n"))))
-
-             (when safe-var
-                (setq extra-line t)
-               (princ "  This variable is safe as a file local variable ")
-               (princ "if its value\n  satisfies the predicate ")
-               (princ (if (byte-code-function-p safe-var)
-                          "which is a byte-compiled expression.\n"
-                        (format-message "`%s'.\n" safe-var))))
-
-              (if extra-line (terpri))
+              (with-current-buffer buffer
+                (run-hook-with-args 'help-fns-describe-variable-functions
+                                    variable))
+
+              (with-current-buffer standard-output
+                (help-fns--ensure-empty-line))
              (princ "Documentation:\n")
              (with-current-buffer standard-output
                (insert (or doc "Not documented as a variable."))))
@@ -1121,6 +1071,134 @@ file-local variable.\n")
              ;; Return the text we displayed.
              (buffer-string))))))))
 
+(add-hook 'help-fns-describe-variable-functions #'help-fns--var-safe-local)
+(defun help-fns--var-safe-local (variable)
+  (let ((safe-var (get variable 'safe-local-variable)))
+    (when safe-var
+      (princ "  This variable is safe as a file local variable ")
+      (princ "if its value\n  satisfies the predicate ")
+      (princ (if (byte-code-function-p safe-var)
+                "which is a byte-compiled expression.\n"
+              (format-message "`%s'.\n" safe-var))))))
+
+(add-hook 'help-fns-describe-variable-functions #'help-fns--var-risky)
+(defun help-fns--var-risky (variable)
+  ;; Can be both risky and safe, eg auto-fill-function.
+  (when (risky-local-variable-p variable)
+    (princ "  This variable may be risky if used as a \
+file-local variable.\n")
+    (when (assq variable safe-local-variable-values)
+      (princ (substitute-command-keys
+              "  However, you have added it to \
+`safe-local-variable-values'.\n")))))
+
+(add-hook 'help-fns-describe-variable-functions #'help-fns--var-ignored-local)
+(defun help-fns--var-ignored-local (variable)
+  (when (memq variable ignored-local-variables)
+    (princ "  This variable is ignored as a file-local \
+variable.\n")))
+
+(add-hook 'help-fns-describe-variable-functions #'help-fns--var-file-local)
+(defun help-fns--var-file-local (variable)
+  (when (boundp variable)
+    (let ((val (symbol-value variable)))
+      (when (member (cons variable val)
+                    file-local-variables-alist)
+        (if (member (cons variable val)
+                    dir-local-variables-alist)
+           (let ((file (and buffer-file-name
+                             (not (file-remote-p buffer-file-name))
+                             (dir-locals-find-file buffer-file-name)))
+                  (is-directory nil))
+             (princ (substitute-command-keys
+                     "  This variable's value is directory-local"))
+              (when (consp file)       ; result from cache
+                ;; If the cache element has an mtime, we
+                ;; assume it came from a file.
+                (if (nth 2 file)
+                    ;; (car file) is a directory.
+                    (setq file (dir-locals--all-files (car file)))
+                  ;; Otherwise, assume it was set directly.
+                  (setq file (car file)
+                        is-directory t)))
+              (if (null file)
+                  (princ ".\n")
+                (princ ", set ")
+                (princ (substitute-command-keys
+                        (cond
+                         (is-directory "for the directory\n  `")
+                         ;; Many files matched.
+                         ((and (consp file) (cdr file))
+                          (setq file (file-name-directory (car file)))
+                          (format "by one of the\n  %s files in the 
directory\n  `"
+                                  dir-locals-file))
+                         (t (setq file (car file))
+                            "by the file\n  `"))))
+               (with-current-buffer standard-output
+                 (insert-text-button
+                  file 'type 'help-dir-local-var-def
+                   'help-args (list variable file)))
+               (princ (substitute-command-keys "'.\n"))))
+          (princ (substitute-command-keys
+                 "  This variable's value is file-local.\n")))))))
+
+(add-hook 'help-fns-describe-variable-functions #'help-fns--var-watchpoints)
+(defun help-fns--var-watchpoints (variable)
+  (let ((watchpoints (get-variable-watchers variable)))
+    (when watchpoints
+      (princ "  Calls these functions when changed: ")
+      ;; FIXME: Turn function names into hyperlinks.
+      (princ watchpoints)
+      (terpri))))
+
+(add-hook 'help-fns-describe-variable-functions #'help-fns--var-obsolete)
+(defun help-fns--var-obsolete (variable)
+  (let* ((obsolete (get variable 'byte-obsolete-variable))
+        (use (car obsolete)))
+    (when obsolete
+      (princ "  This variable is obsolete")
+      (if (nth 2 obsolete)
+          (princ (format " since %s" (nth 2 obsolete))))
+      (princ (cond ((stringp use) (concat ";\n  " use))
+                  (use (format-message ";\n  use `%s' instead."
+                                        (car obsolete)))
+                  (t ".")))
+      (terpri))))
+
+(add-hook 'help-fns-describe-variable-functions #'help-fns--var-alias)
+(defun help-fns--var-alias (variable)
+  ;; Mention if it's an alias.
+  (let ((alias (condition-case nil
+                   (indirect-variable variable)
+                 (error variable))))
+    (unless (eq alias variable)
+      (princ (format-message
+              "  This variable is an alias for `%s'.\n"
+              alias)))))
+
+(add-hook 'help-fns-describe-variable-functions #'help-fns--var-bufferlocal)
+(defun help-fns--var-bufferlocal (variable)
+  (let ((permanent-local (get variable 'permanent-local))
+        (locus (variable-binding-locus variable)))
+    ;; Mention if it's a local variable.
+    (cond
+     ((and (local-variable-if-set-p variable)
+          (or (not (local-variable-p variable))
+              (with-temp-buffer
+                (local-variable-if-set-p variable))))
+      (princ "  Automatically becomes ")
+      (if permanent-local
+         (princ "permanently "))
+      (princ "buffer-local when set.\n"))
+     ((not permanent-local))
+     ((bufferp locus)
+      (princ
+       (substitute-command-keys
+        "  This variable's buffer-local value is permanent.\n")))
+     (t
+      (princ (substitute-command-keys
+             "  This variable's value is permanent \
+if it is given a local binding.\n"))))))
 
 (defvar help-xref-stack-item)
 
diff --git a/lisp/mail/mail-extr.el b/lisp/mail/mail-extr.el
index cb57d8e..a0b9688 100644
--- a/lisp/mail/mail-extr.el
+++ b/lisp/mail/mail-extr.el
@@ -383,7 +383,7 @@ by translating things like \"address@hidden" into 
\"address@hidden"."
 ;; Matches telephone extensions.
 (defconst mail-extr-telephone-extension-pattern
   (purecopy
-   "\\(\\([Ee]xt\\|\\|[Tt]ph\\|[Tt]el\\|[Xx]\\).?\\)? *\\+?[0-9][- 0-9]+"))
+   "\\(\\([Ee]xt\\|[Tt]ph\\|[Tt]el\\|[Xx]\\).?\\)? *\\+?[0-9][- 0-9]+"))
 
 ;; Matches ham radio call signs.
 ;; Help from: Mat Maessen N2NJZ <address@hidden>, Mark Feit
diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el
index db9acbf..f3aa55f 100644
--- a/lisp/net/tramp-adb.el
+++ b/lisp/net/tramp-adb.el
@@ -53,7 +53,7 @@ It is used for TCP/IP devices."
   "When this method name is used, forward all calls to Android Debug Bridge.")
 
 (defcustom tramp-adb-prompt
-  
"^\\(?:[[:digit:]]*|?\\)?\\(?:[[:alnum:]\e;address@hidden:alnum:]]*[^#\\$]*\\)?[#\\$][[:space:]]"
+  
"^[[:digit:]]*|?\\(?:[[:alnum:]\e;address@hidden:alnum:]]*[^#\\$]*\\)?[#\\$][[:space:]]"
   "Regexp used as prompt in almquist shell."
   :type 'string
   :version "24.4"
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index 7d903c5..d9751a9 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -2903,7 +2903,8 @@ the result will be a local, non-Tramp, file name."
                    ;; otherwise we might be interrupted by
                    ;; `verify-visited-file-modtime'.
                    (let ((buffer-undo-list t)
-                         (inhibit-read-only t))
+                         (inhibit-read-only t)
+                         (mark (point-max)))
                      (clear-visited-file-modtime)
                      (narrow-to-region (point-max) (point-max))
                      ;; We call `tramp-maybe-open-connection', in
@@ -2916,7 +2917,12 @@ the result will be a local, non-Tramp, file name."
                        (let ((pid (tramp-send-command-and-read v "echo $$")))
                          (process-put p 'remote-pid pid)
                          (tramp-set-connection-property p "remote-pid" pid))
-                       (delete-region (point-min) (point-max))
+                       ;; `tramp-maybe-open-connection' and
+                       ;; `tramp-send-command-and-read' could have
+                       ;; trashed the connection buffer.  Remove this.
+                       (widen)
+                       (delete-region mark (point-max))
+                       (narrow-to-region (point-max) (point-max))
                        ;; Now do it.
                        (if command
                            ;; Send the command.
diff --git a/lisp/org/org-table.el b/lisp/org/org-table.el
index b6e864f..147527d 100644
--- a/lisp/org/org-table.el
+++ b/lisp/org/org-table.el
@@ -484,8 +484,8 @@ Line numbers are counted from the beginning of the table.  
This
 variable is initialized with `org-table-analyze'.")
 
 (defconst org-table-range-regexp
-  
"@\\([-+]?I*[-+]?[0-9]*\\)?\\(\\$[-+]?[0-9]+\\)?\\(address@hidden([-+]?I*[-+]?[0-9]*\\)?\\(\\$[-+]?[0-9]+\\)?\\)?"
-  ;;   1                        2                    3          4              
          5
+  
"@\\([-+]?I*[-+]?[0-9]*\\)\\(\\$[-+]?[0-9]+\\)?\\(address@hidden([-+]?I*[-+]?[0-9]*\\)\\(\\$[-+]?[0-9]+\\)?\\)?"
+  ;;   1                       2                    3          4               
        5
   "Regular expression for matching ranges in formulas.")
 
 (defconst org-table-range-regexp2
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index 1a8c516..f0b44d2 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -10953,7 +10953,8 @@ comment at the start of cc-engine.el for more info."
                      (eq (char-after) ?\())
                 (setq braceassignp 'c++-noassign
                       in-paren 'in-paren))
-               ((looking-at c-pre-id-bracelist-key))
+               ((looking-at c-pre-id-bracelist-key)
+                (setq braceassignp nil))
                ((looking-at c-return-key))
                ((and (looking-at c-symbol-start)
                      (not (looking-at c-keywords-regexp)))
@@ -10995,6 +10996,8 @@ comment at the start of cc-engine.el for more info."
 
       (setq pos (point))
       (cond
+       ((not braceassignp)
+       nil)
        ((and after-type-id-pos
             (goto-char after-type-id-pos)
             (setq res (c-back-over-member-initializers))
@@ -11069,14 +11072,20 @@ comment at the start of cc-engine.el for more info."
                                     ))))
                           nil)
                          (t t))))))
-         (when (and (eq braceassignp 'dontknow)
-                    (/= (c-backward-token-2 1 t lim) 0))
-           (if (save-excursion
-                 (and c-has-compound-literals
-                      (eq (c-backward-token-2 1 nil lim) 0)
-                      (eq (char-after) ?\()))
-               (setq braceassignp t)
-             (setq braceassignp nil))))
+         (when (eq braceassignp 'dontknow)
+           (cond ((and
+                   (not (eq (char-after) ?,))
+                   (save-excursion
+                     (c-backward-syntactic-ws)
+                     (eq (char-before) ?})))
+                  (setq braceassignp nil))
+                 ((/= (c-backward-token-2 1 t lim) 0)
+                  (if (save-excursion
+                        (and c-has-compound-literals
+                             (eq (c-backward-token-2 1 nil lim) 0)
+                             (eq (char-after) ?\()))
+                      (setq braceassignp t)
+                    (setq braceassignp nil))))))
 
        (cond
         (braceassignp
@@ -11108,9 +11117,14 @@ comment at the start of cc-engine.el for more info."
                    (and (consp res)
                         (eq (car res) after-type-id-pos))))))
          (cons bufpos (or in-paren inexpr-brace-list)))
-        ((eq (char-after) ?\;)
-         ;; Brace lists can't contain a semicolon, so we're done.
-         ;; (setq containing-sexp nil)
+        ((or (eq (char-after) ?\;)
+             ;; Brace lists can't contain a semicolon, so we're done.
+             (save-excursion
+               (c-backward-syntactic-ws)
+               (eq (char-before) ?}))
+             ;; They also can't contain a bare }, which is probably the end
+             ;; of a function.
+             )
          nil)
         ((and (setq macro-start (point))
               (c-forward-to-cpp-define-body)
@@ -12720,6 +12734,13 @@ comment at the start of cc-engine.el for more info."
                        (if (eq (char-after) ?<)
                            (zerop (c-forward-token-2 1 t indent-point))
                          t)
+                       (progn
+                         (while
+                             (and
+                              (< (point) indent-point)
+                              (looking-at c-class-id-suffix-ws-ids-key)
+                              (zerop (c-forward-token-2 1 nil indent-point))))
+                         t)
                        (eq (char-after) ?:))))
            (goto-char placeholder)
            (c-add-syntax 'inher-cont (c-point 'boi)))
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el
index 2dff5cf..50f8b84 100644
--- a/lisp/progmodes/cc-langs.el
+++ b/lisp/progmodes/cc-langs.el
@@ -2049,6 +2049,19 @@ effect in the declaration, but are syntactically like 
whitespace."
 (c-lang-defvar c-type-decl-suffix-ws-ids-key
   (c-lang-const c-type-decl-suffix-ws-ids-key))
 
+(c-lang-defconst c-class-id-suffix-ws-ids-kwds
+  "\"Identifiers\" that when immediately following the identifier
+of a class declaration have semantic effect in the declaration,
+but are syntactically like whitespace."
+  t    nil
+  c++ '("final"))
+
+(c-lang-defconst c-class-id-suffix-ws-ids-key
+  ;; An adorned regexp matching `c-class-id-suffix-ws-ids-kwds'.
+  t (c-make-keywords-re t (c-lang-const c-class-id-suffix-ws-ids-kwds)))
+(c-lang-defvar c-class-id-suffix-ws-ids-key
+  (c-lang-const c-class-id-suffix-ws-ids-key))
+
 (c-lang-defconst c-class-decl-kwds
   "Keywords introducing declarations where the following block (if any)
 contains another declaration level that should be considered a class.
diff --git a/lisp/progmodes/idlwave.el b/lisp/progmodes/idlwave.el
index bded09d..6f56ce0 100644
--- a/lisp/progmodes/idlwave.el
+++ b/lisp/progmodes/idlwave.el
@@ -6454,10 +6454,10 @@ ARROW:  Location of the arrow"
      ((string-match "\\`[ \t]*\\(pro\\|function\\)\\>"
                    match-string)
       nil)
-     ((string-match "OBJ_NEW([ \t]*['\"]\\([a-zA-Z0-9$_]*\\)?\\'"
+     ((string-match "OBJ_NEW([ \t]*['\"][a-zA-Z0-9$_]*\\'"
                    match-string)
       (setq cw 'class))
-     ((string-match "\\<inherits\\s-+\\([a-zA-Z0-9$_]*\\)?\\'"
+     ((string-match "\\<inherits\\s-+[a-zA-Z0-9$_]*\\'"
                    match-string)
       (setq cw 'class))
      ((and func
diff --git a/lisp/progmodes/verilog-mode.el b/lisp/progmodes/verilog-mode.el
index 9226291..e75e584 100644
--- a/lisp/progmodes/verilog-mode.el
+++ b/lisp/progmodes/verilog-mode.el
@@ -2761,12 +2761,12 @@ find the errors."
 (defconst verilog-declaration-re-2-no-macro
   (concat "\\s-*" verilog-declaration-re
          "\\s-*\\(\\(" verilog-optional-signed-range-re "\\)\\|\\(" 
verilog-delay-re "\\)"
-         "\\)?"))
+         "\\)"))
 (defconst verilog-declaration-re-2-macro
   (concat "\\s-*" verilog-declaration-re
          "\\s-*\\(\\(" verilog-optional-signed-range-re "\\)\\|\\(" 
verilog-delay-re "\\)"
          "\\|\\(" verilog-macroexp-re "\\)"
-         "\\)?"))
+         "\\)"))
 (defconst verilog-declaration-re-1-macro
   (concat "^" verilog-declaration-re-2-macro))
 
@@ -10810,7 +10810,7 @@ Intended for internal use inside a 
`verilog-save-font-no-change-functions' block
                              'verilog-delete-auto-star-all)
   ;; Remove template comments ... anywhere in case was pasted after AUTOINST 
removed
   (goto-char (point-min))
-  (while (re-search-forward "\\s-*// \\(Templated\\|Implicit \\.\\*\\)\\([ 
\tLT0-9]*\\| LHS: .*\\)?$" nil t)
+  (while (re-search-forward "\\s-*// \\(Templated\\|Implicit \\.\\*\\)\\([ 
\tLT0-9]*\\| LHS: .*\\)$" nil t)
     (replace-match ""))
 
   ;; Final customize
@@ -11412,7 +11412,7 @@ If PAR-VALUES replace final strings with these 
parameter values."
     (when tpl-ass
       ;; Evaluate @"(lispcode)"
       (when (string-match "@\".*[^\\]\"" tpl-net)
-       (while (string-match "@\"\\(\\([^\\\"]*\\(\\\\.\\)*\\)*\\)\"" tpl-net)
+       (while (string-match "@\"\\(\\([^\\\"]\\|\\\\.\\)*\\)\"" tpl-net)
          (setq tpl-net
                (concat
                 (substring tpl-net 0 (match-beginning 0))
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index aed92f8..e5e5972 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -448,6 +448,18 @@ If SELECT is non-nil, select the target window."
 (defconst xref-buffer-name "*xref*"
   "The name of the buffer to show xrefs.")
 
+(defface xref-file-header '((t :inherit compilation-info))
+  "Face used to highlight file header in the xref buffer."
+  :version "27.1")
+
+(defface xref-line-number '((t :inherit compilation-line-number))
+  "Face for displaying line numbers in the xref buffer."
+  :version "27.1")
+
+(defface xref-match '((t :inherit highlight))
+  "Face used to highlight matches in the xref buffer."
+  :version "27.1")
+
 (defmacro xref--with-dedicated-window (&rest body)
   `(let* ((xref-w (get-buffer-window xref-buffer-name))
           (xref-w-dedicated (window-dedicated-p xref-w)))
@@ -737,18 +749,17 @@ GROUP is a string for decoration purposes and XREF is an
            for line-format = (and max-line-width
                                   (format "%%%dd: " max-line-width))
            do
-           (xref--insert-propertized '(face compilation-info) group "\n")
+           (xref--insert-propertized '(face xref-file-header) group "\n")
            (cl-loop for (xref . more2) on xrefs do
                     (with-slots (summary location) xref
                       (let* ((line (xref-location-line location))
                              (prefix
                               (if line
                                   (propertize (format line-format line)
-                                              'face 'compilation-line-number)
+                                              'face 'xref-line-number)
                                 "  ")))
                         (xref--insert-propertized
                          (list 'xref-item xref
-                               ;; 'face 'font-lock-keyword-face
                                'mouse-face 'highlight
                                'keymap xref--button-map
                                'help-echo
@@ -1159,7 +1170,7 @@ Such as the current syntax table and the applied syntax 
properties."
              (end-column (- (match-end 0) line-beg))
              (loc (xref-make-file-location file line beg-column))
              (summary (buffer-substring line-beg line-end)))
-        (add-face-text-property beg-column end-column 'highlight
+        (add-face-text-property beg-column end-column 'xref-match
                                 t summary)
         (push (xref-make-match summary loc (- end-column beg-column))
               matches)))
diff --git a/lisp/simple.el b/lisp/simple.el
index fb66735..160c433 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -3351,6 +3351,16 @@ is output."
   :group 'shell
   :version "26.1")
 
+(defcustom shell-command-width nil
+  "Number of display columns available for asynchronous shell command output.
+If nil, use the shell default number (usually 80 columns).
+If a positive integer, tell the shell to use that number of columns for
+command output."
+  :type '(choice (const :tag "Use system limit" nil)
+                 (integer :tag "Fixed width" :value 80))
+  :group 'shell
+  :version "27.1")
+
 (defcustom shell-command-dont-erase-buffer nil
   "If non-nil, output buffer is not erased between shell commands.
 Also, a non-nil value sets the point in the output buffer
@@ -3614,8 +3624,13 @@ impose the use of a shell (with its need to quote 
arguments)."
                (with-current-buffer buffer
                   (shell-command--save-pos-or-erase)
                  (setq default-directory directory)
-                  (setq proc
-                        (start-process-shell-command "Shell" buffer command))
+                 (let ((process-environment
+                        (if (natnump shell-command-width)
+                            (cons (format "COLUMNS=%d" shell-command-width)
+                                  process-environment)
+                          process-environment)))
+                   (setq proc
+                         (start-process-shell-command "Shell" buffer command)))
                  (setq mode-line-process '(":%s"))
                  (require 'shell) (shell-mode)
                   (set-process-sentinel proc #'shell-command-sentinel)
diff --git a/lisp/subr.el b/lisp/subr.el
index bdf9897..bf3716b 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -604,6 +604,11 @@ If N is omitted or nil, remove the last element."
           (if (> n 0) (setcdr (nthcdr (- (1- m) n) list) nil))
           list))))
 
+;; The function's definition was moved to fns.c,
+;; but it's easier to set properties here.
+(put 'proper-list-p 'pure t)
+(put 'proper-list-p 'side-effect-free 'error-free)
+
 (defun delete-dups (list)
   "Destructively remove `equal' duplicates from LIST.
 Store the result in LIST and return it.  LIST must be a proper list.
diff --git a/lisp/url/url-http.el b/lisp/url/url-http.el
index cf19520..662b666 100644
--- a/lisp/url/url-http.el
+++ b/lisp/url/url-http.el
@@ -150,15 +150,6 @@ request.")
 ;; These routines will allow us to implement persistent HTTP
 ;; connections.
 (defsubst url-http-debug (&rest args)
-  (if (eq quit-flag t)
-      (let ((proc (get-buffer-process (current-buffer))))
-       ;; The user hit C-g, honor it!  Some things can get in an
-       ;; incredibly tight loop (chunked encoding)
-       (if proc
-           (progn
-             (set-process-sentinel proc nil)
-             (set-process-filter proc nil)))
-       (error "Transfer interrupted!")))
   (apply 'url-debug 'http args))
 
 (defun url-http-mark-connection-as-busy (host port proc)
diff --git a/lisp/url/url-misc.el b/lisp/url/url-misc.el
index 4969cba..aa44ea7 100644
--- a/lisp/url/url-misc.el
+++ b/lisp/url/url-misc.el
@@ -88,7 +88,7 @@
        (encoding "8bit")
        (data nil))
     (save-excursion
-      (if (not (string-match "\\([^,]*\\)?," desc))
+      (if (not (string-match "\\([^,]*\\)," desc))
          (error "Malformed data URL: %s" desc)
        (setq mediatype (match-string 1 desc)
              data (url-unhex-string (substring desc (match-end 0))))
diff --git a/lisp/url/url-util.el b/lisp/url/url-util.el
index 72ff4f1..5b83506 100644
--- a/lisp/url/url-util.el
+++ b/lisp/url/url-util.el
@@ -61,8 +61,6 @@ If a list, it is a list of the types of messages to be 
logged."
 
 ;;;###autoload
 (defun url-debug (tag &rest args)
-  (if (eq quit-flag t)
-      (error "Interrupted!"))
   (if (or (eq url-debug t)
          (numberp url-debug)
          (and (listp url-debug) (memq tag url-debug)))
diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el
index 8940c7e..1d5a2cf 100644
--- a/lisp/vc/diff-mode.el
+++ b/lisp/vc/diff-mode.el
@@ -2411,10 +2411,11 @@ and the position in MAX."
     (diff-syntax-fontify-hunk beg end t)
     (diff-syntax-fontify-hunk beg end nil)))
 
-(defvar diff-syntax-fontify-revisions (make-hash-table :test 'equal))
-
 (eval-when-compile (require 'subr-x)) ; for string-trim-right
 
+(defvar-local diff--syntax-file-attributes nil)
+(put 'diff--syntax-file-attributes 'permanent-local t)
+
 (defun diff-syntax-fontify-hunk (beg end old)
   "Highlight source language syntax in diff hunk between BEG and END.
 When OLD is non-nil, highlight the hunk from the old source."
@@ -2444,33 +2445,38 @@ When OLD is non-nil, highlight the hunk from the old 
source."
                (when file
                  (if (not revision)
                      ;; Get properties from the current working revision
-                     (when (and (not old) (file-exists-p file)
+                     (when (and (not old) (file-readable-p file)
                                 (file-regular-p file))
                        (let ((buf (get-file-buffer (expand-file-name file))))
                          ;; Try to reuse an existing buffer
                          (if buf
                              (with-current-buffer buf
                                (diff-syntax-fontify-props nil text line-nb))
-                           ;; Get properties from the file
-                           (with-temp-buffer
-                             (insert-file-contents file)
+                           ;; Get properties from the file.
+                           (with-current-buffer (get-buffer-create
+                                                 " *diff-syntax-file*")
+                             (let ((attrs (file-attributes file)))
+                               (if (equal diff--syntax-file-attributes attrs)
+                                   ;; Same file as last-time, unmodified.
+                                   ;; Reuse buffer as-is.
+                                   (setq file nil)
+                                 (insert-file-contents file)
+                                 (setq diff--syntax-file-attributes attrs)))
                              (diff-syntax-fontify-props file text line-nb)))))
                    ;; Get properties from a cached revision
                    (let* ((buffer-name (format " *diff-syntax:%s.~%s~*"
                                                (expand-file-name file)
                                                revision))
-                          (buffer (gethash buffer-name
-                                           diff-syntax-fontify-revisions)))
-                     (unless (and buffer (buffer-live-p buffer))
-                       (let* ((vc-buffer (ignore-errors
-                                           (vc-find-revision-no-save
-                                            (expand-file-name file) revision
-                                            diff-vc-backend
-                                            (get-buffer-create buffer-name)))))
-                         (when vc-buffer
-                           (setq buffer vc-buffer)
-                           (puthash buffer-name buffer
-                                    diff-syntax-fontify-revisions))))
+                          (buffer (get-buffer buffer-name)))
+                     (if buffer
+                         ;; Don't re-initialize the buffer (which would throw
+                         ;; away the previous fontification work).
+                         (setq file nil)
+                       (setq buffer (ignore-errors
+                                      (vc-find-revision-no-save
+                                       (expand-file-name file) revision
+                                       diff-vc-backend
+                                       (get-buffer-create buffer-name)))))
                      (when buffer
                        (with-current-buffer buffer
                          (diff-syntax-fontify-props file text line-nb))))))))
diff --git a/lisp/vc/log-edit.el b/lisp/vc/log-edit.el
index 42710dd..ba5a1a3 100644
--- a/lisp/vc/log-edit.el
+++ b/lisp/vc/log-edit.el
@@ -754,7 +754,9 @@ regardless of user name or time."
             (log-edit-insert-changelog-entries (log-edit-files)))))
       (log-edit-set-common-indentation)
       ;; Add an Author: field if appropriate.
-      (when author (log-edit-add-field "Author" (car author)))
+      (when author
+        (log-edit-add-field "Author" (car author))
+        (log-edit-add-field "Summary" ""))
       ;; Add a Fixes: field if applicable.
       (when (consp log-edit-rewrite-fixes)
        (rfc822-goto-eoh)
diff --git a/src/emacs.c b/src/emacs.c
index 68835ca..6ed4b0e 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -157,9 +157,14 @@ static uprintmax_t heap_bss_diff;
 /* To run as a background daemon under Cocoa or Windows,
    we must do a fork+exec, not a simple fork.
 
-   On Cocoa, CoreFoundation lib fails in forked process:
+   On Cocoa, CoreFoundation lib fails in forked process, see Mac OS X
+   Leopard Developer Release Notes for CoreFoundation Framework:
+
    http://developer.apple.com/ReleaseNotes/
-   CoreFoundation/CoreFoundation.html)
+   CoreFoundation/CoreFoundation.html
+
+   Note: the above is no longer available on-line, but it can be found
+   via the "Wayback machine", https://web.archive.org.
 
    On Windows, a Cygwin fork child cannot access the USER subsystem.
 
diff --git a/src/json.c b/src/json.c
index 5e1439f..74e0534 100644
--- a/src/json.c
+++ b/src/json.c
@@ -337,8 +337,14 @@ enum json_object_type {
   json_object_plist
 };
 
+enum json_array_type {
+  json_array_array,
+  json_array_list
+};
+
 struct json_configuration {
   enum json_object_type object_type;
+  enum json_array_type array_type;
   Lisp_Object null_object;
   Lisp_Object false_object;
 };
@@ -521,7 +527,7 @@ static void
 json_parse_args (ptrdiff_t nargs,
                  Lisp_Object *args,
                  struct json_configuration *conf,
-                 bool configure_object_type)
+                 bool parse_object_types)
 {
   if ((nargs % 2) != 0)
     wrong_type_argument (Qplistp, Flist (nargs, args));
@@ -531,7 +537,7 @@ json_parse_args (ptrdiff_t nargs,
   for (ptrdiff_t i = nargs; i > 0; i -= 2) {
     Lisp_Object key = args[i - 2];
     Lisp_Object value = args[i - 1];
-    if (configure_object_type && EQ (key, QCobject_type))
+    if (parse_object_types && EQ (key, QCobject_type))
       {
         if (EQ (value, Qhash_table))
           conf->object_type = json_object_hashtable;
@@ -542,12 +548,22 @@ json_parse_args (ptrdiff_t nargs,
         else
           wrong_choice (list3 (Qhash_table, Qalist, Qplist), value);
       }
+    else if (parse_object_types && EQ (key, QCarray_type))
+      {
+        if (EQ (value, Qarray))
+          conf->array_type = json_array_array;
+        else if (EQ (value, Qlist))
+          conf->array_type = json_array_list;
+        else
+          wrong_choice (list2 (Qarray, Qlist), value);
+      }
     else if (EQ (key, QCnull_object))
       conf->null_object = value;
     else if (EQ (key, QCfalse_object))
       conf->false_object = value;
-    else if (configure_object_type)
-      wrong_choice (list3 (QCobject_type,
+    else if (parse_object_types)
+      wrong_choice (list4 (QCobject_type,
+                           QCarray_type,
                            QCnull_object,
                            QCfalse_object),
                     value);
@@ -604,7 +620,8 @@ usage: (json-serialize OBJECT &rest ARGS)  */)
     }
 #endif
 
-  struct json_configuration conf = {json_object_hashtable, QCnull, QCfalse};
+  struct json_configuration conf =
+    {json_object_hashtable, json_array_array, QCnull, QCfalse};
   json_parse_args (nargs - 1, args + 1, &conf, false);
 
   json_t *json = lisp_to_json_toplevel (args[0], &conf);
@@ -701,7 +718,8 @@ usage: (json-insert OBJECT &rest ARGS)  */)
     }
 #endif
 
-  struct json_configuration conf = {json_object_hashtable, QCnull, QCfalse};
+  struct json_configuration conf =
+    {json_object_hashtable, json_array_array, QCnull, QCfalse};
   json_parse_args (nargs - 1, args + 1, &conf, false);
 
   json_t *json = lisp_to_json (args[0], &conf);
@@ -817,10 +835,35 @@ json_to_lisp (json_t *json, struct json_configuration 
*conf)
         size_t size = json_array_size (json);
         if (PTRDIFF_MAX < size)
           overflow_error ();
-        Lisp_Object result = make_vector (size, Qunbound);
-        for (ptrdiff_t i = 0; i < size; ++i)
-          ASET (result, i,
-                json_to_lisp (json_array_get (json, i), conf));
+        Lisp_Object result;
+        switch (conf->array_type)
+          {
+          case json_array_array:
+            {
+              result = make_vector (size, Qunbound);
+              for (ptrdiff_t i = 0; i < size; ++i)
+                {
+                  rarely_quit (i);
+                  ASET (result, i,
+                        json_to_lisp (json_array_get (json, i), conf));
+                }
+              break;
+            }
+          case json_array_list:
+            {
+              result = Qnil;
+              for (ptrdiff_t i = size - 1; i >= 0; --i)
+                {
+                  rarely_quit (i);
+                  result = Fcons (json_to_lisp (json_array_get (json, i), 
conf),
+                                  result);
+                }
+              break;
+            }
+          default:
+            /* Can't get here.  */
+            emacs_abort ();
+          }
         --lisp_eval_depth;
         return result;
       }
@@ -905,18 +948,22 @@ json_to_lisp (json_t *json, struct json_configuration 
*conf)
 DEFUN ("json-parse-string", Fjson_parse_string, Sjson_parse_string, 1, MANY,
        NULL,
        doc: /* Parse the JSON STRING into a Lisp object.
-
 This is essentially the reverse operation of `json-serialize', which
-see.  The returned object will be a vector, hashtable, alist, or
+see.  The returned object will be a vector, list, hashtable, alist, or
 plist.  Its elements will be the JSON null value, the JSON false
 value, t, numbers, strings, or further vectors, hashtables, alists, or
 plists.  If there are duplicate keys in an object, all but the last
-one are ignored.  If STRING doesn't contain a valid JSON object, an
-error of type `json-parse-error' is signaled.  The arguments ARGS are
-a list of keyword/argument pairs:
+one are ignored.  If STRING doesn't contain a valid JSON object, this
+function signals an error of type `json-parse-error'.
+
+The arguments ARGS are a list of keyword/argument pairs:
 
 The keyword argument `:object-type' specifies which Lisp type is used
-to represent objects; it can be `hash-table', `alist' or `plist'.
+to represent objects; it can be `hash-table', `alist' or `plist'.  It
+defaults to `hash-table'.
+
+The keyword argument `:array-type' specifies which Lisp type is used
+to represent arrays; it can be `array' (the default) or `list'.
 
 The keyword argument `:null-object' specifies which object to use
 to represent a JSON null value.  It defaults to `:null'.
@@ -946,7 +993,8 @@ usage: (json-parse-string STRING &rest ARGS) */)
   Lisp_Object string = args[0];
   Lisp_Object encoded = json_encode (string);
   check_string_without_embedded_nuls (encoded);
-  struct json_configuration conf = {json_object_hashtable, QCnull, QCfalse};
+  struct json_configuration conf =
+    {json_object_hashtable, json_array_array, QCnull, QCfalse};
   json_parse_args (nargs - 1, args + 1, &conf, true);
 
   json_error_t error;
@@ -993,9 +1041,32 @@ json_read_buffer_callback (void *buffer, size_t buflen, 
void *data)
 DEFUN ("json-parse-buffer", Fjson_parse_buffer, Sjson_parse_buffer,
        0, MANY, NULL,
        doc: /* Read JSON object from current buffer starting at point.
-This is similar to `json-parse-string', which see.  Move point after
-the end of the object if parsing was successful.  On error, point is
-not moved.
+Move point after the end of the object if parsing was successful.
+On error, don't move point.
+
+The returned object will be a vector, list, hashtable, alist, or
+plist.  Its elements will be the JSON null value, the JSON false
+value, t, numbers, strings, or further vectors, lists, hashtables,
+alists, or plists.  If there are duplicate keys in an object, all
+but the last one are ignored.
+
+If the current buffer doesn't contain a valid JSON object, the
+function signals an error of type `json-parse-error'.
+
+The arguments ARGS are a list of keyword/argument pairs:
+
+The keyword argument `:object-type' specifies which Lisp type is used
+to represent objects; it can be `hash-table', `alist' or `plist'.  It
+defaults to `hash-table'.
+
+The keyword argument `:array-type' specifies which Lisp type is used
+to represent arrays; it can be `array' (the default) or `list'.
+
+The keyword argument `:null-object' specifies which object to use
+to represent a JSON null value.  It defaults to `:null'.
+
+The keyword argument `:false-object' specifies which object to use to
+represent a JSON false value.  It defaults to `:false'.
 usage: (json-parse-buffer &rest args) */)
      (ptrdiff_t nargs, Lisp_Object *args)
 {
@@ -1016,7 +1087,8 @@ usage: (json-parse-buffer &rest args) */)
     }
 #endif
 
-  struct json_configuration conf = {json_object_hashtable, QCnull, QCfalse};
+  struct json_configuration conf =
+    {json_object_hashtable, json_array_array, QCnull, QCfalse};
   json_parse_args (nargs, args, &conf, true);
 
   ptrdiff_t point = PT_BYTE;
@@ -1095,10 +1167,12 @@ syms_of_json (void)
   Fput (Qjson_parse_string, Qside_effect_free, Qt);
 
   DEFSYM (QCobject_type, ":object-type");
+  DEFSYM (QCarray_type, ":array-type");
   DEFSYM (QCnull_object, ":null-object");
   DEFSYM (QCfalse_object, ":false-object");
   DEFSYM (Qalist, "alist");
   DEFSYM (Qplist, "plist");
+  DEFSYM (Qarray, "array");
 
   defsubr (&Sjson_serialize);
   defsubr (&Sjson_insert);
diff --git a/src/minibuf.c b/src/minibuf.c
index a0025e2..10fd5e5 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -995,7 +995,8 @@ the current input method and the setting 
of`enable-multibyte-characters'.  */)
 DEFUN ("read-command", Fread_command, Sread_command, 1, 2, 0,
        doc: /* Read the name of a command and return as a symbol.
 Prompt with PROMPT.  By default, return DEFAULT-VALUE or its first element
-if it is a list.  */)
+if it is a list.  If DEFAULT-VALUE is omitted or nil, and the user enters
+null input, return a symbol whose name is an empty string.  */)
   (Lisp_Object prompt, Lisp_Object default_value)
 {
   Lisp_Object name, default_string;
diff --git a/src/xfns.c b/src/xfns.c
index 13f66f0..e521ed1 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -5030,7 +5030,7 @@ Internal use only, use `display-monitor-attributes-list' 
instead.  */)
       mi->mm_height = height_mm;
 
 #if GTK_CHECK_VERSION (3, 22, 0)
-      mi->name = xstrdup (gdk_monitor_get_model (monitor));
+      dupstring (&mi->name, (gdk_monitor_get_model (monitor)));
 #elif GTK_CHECK_VERSION (2, 14, 0)
       mi->name = gdk_screen_get_monitor_plug_name (gscreen, i);
 #endif
diff --git a/src/xterm.c b/src/xterm.c
index 5aa3e3f..def6915 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -922,16 +922,17 @@ x_set_frame_alpha (struct frame *f)
   else
     alpha = f->alpha[1];
 
+  if (alpha < 0.0)
+    return;
+
   if (FLOATP (Vframe_alpha_lower_limit))
     alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit);
   else if (FIXNUMP (Vframe_alpha_lower_limit))
     alpha_min = (XFIXNUM (Vframe_alpha_lower_limit)) / 100.0;
 
-  if (alpha < 0.0)
-    return;
-  else if (alpha > 1.0)
+  if (alpha > 1.0)
     alpha = 1.0;
-  else if (0.0 <= alpha && alpha < alpha_min && alpha_min <= 1.0)
+  else if (alpha < alpha_min && alpha_min <= 1.0)
     alpha = alpha_min;
 
   opac = alpha * OPAQUE;
diff --git a/test/lisp/filenotify-tests.el b/test/lisp/filenotify-tests.el
index 5003620..842d66d 100644
--- a/test/lisp/filenotify-tests.el
+++ b/test/lisp/filenotify-tests.el
@@ -266,9 +266,8 @@ This returns only for the local case and gfilenotify; 
otherwise it is nil.
   (declare (indent 1))
   `(ert-deftest ,(intern (concat (symbol-name test) "-remote")) ()
      ,docstring
-     :tags '(:expensive-test)
      :expected-result (or ,expected :passed)
-     (skip-unless (not ,skip))
+     :tags ,(if skip ''(:expensive-test :unstable) ''(:expensive-test))
      (let* ((temporary-file-directory
             file-notify-test-remote-temporary-file-directory)
            (ert-test (ert-get-test ',test))
diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el
index 5a9541d..cc3200b 100644
--- a/test/lisp/net/tramp-tests.el
+++ b/test/lisp/net/tramp-tests.el
@@ -4579,7 +4579,7 @@ This tests also `make-symbolic-link', `file-truename' and 
`add-name-to-file'."
              ;; skip the test then.
              (condition-case nil
                  (vc-create-repo (car vc-handled-backends))
-               (error (skip-unless nil)))
+               (error (ert-skip "`vc-create-repo' not supported")))
              ;; The structure of VC-FILESET is not documented.  Let's
              ;; hope it won't change.
              (condition-case nil
diff --git a/test/lisp/progmodes/python-tests.el 
b/test/lisp/progmodes/python-tests.el
index 999cf8d..b940f45 100644
--- a/test/lisp/progmodes/python-tests.el
+++ b/test/lisp/progmodes/python-tests.el
@@ -5350,7 +5350,7 @@ buffer with overlapping strings."
   ;; The description of the problem it's trying to catch is not clear enough
   ;; to be able to see if the underlying problem is really fixed, sadly.
   ;; E.g. I don't know what is meant by "overlap", really.
-  (skip-unless nil)
+  :tags '(:unstable)
   (python-tests-with-temp-buffer "''' '\n''' ' '\n"
     (syntax-propertize (point-max))
     ;; Create a situation where strings nominally overlap.  This
diff --git a/test/lisp/subr-tests.el b/test/lisp/subr-tests.el
index 7465aac..c458eef 100644
--- a/test/lisp/subr-tests.el
+++ b/test/lisp/subr-tests.el
@@ -318,24 +318,6 @@ cf. Bug#25477."
   (should (eq (string-to-char (symbol-name (gensym))) ?g))
   (should (eq (string-to-char (symbol-name (gensym "X"))) ?X)))
 
-(ert-deftest subr-tests--proper-list-p ()
-  "Test `proper-list-p' behavior."
-  (dotimes (length 4)
-    ;; Proper and dotted lists.
-    (let ((list (make-list length 0)))
-      (should (= (proper-list-p list) length))
-      (should (not (proper-list-p (nconc list 0)))))
-    ;; Circular lists.
-    (dotimes (n (1+ length))
-      (let ((circle (make-list (1+ length) 0)))
-        (should (not (proper-list-p (nconc circle (nthcdr n circle))))))))
-  ;; Atoms.
-  (should (not (proper-list-p 0)))
-  (should (not (proper-list-p "")))
-  (should (not (proper-list-p [])))
-  (should (not (proper-list-p (make-bool-vector 0 nil))))
-  (should (not (proper-list-p (make-symbol "a")))))
-
 (ert-deftest subr-tests--assq-delete-all ()
   "Test `assq-delete-all' behavior."
   (cl-flet ((new-list-fn
diff --git a/test/src/fns-tests.el b/test/src/fns-tests.el
index d6cc99e..6ebab42 100644
--- a/test/src/fns-tests.el
+++ b/test/src/fns-tests.el
@@ -648,4 +648,22 @@
           (should (equal (list (eq a b) n len)
                          (list t n len))))))))
 
+(ert-deftest test-proper-list-p ()
+  "Test `proper-list-p' behavior."
+  (dotimes (length 4)
+    ;; Proper and dotted lists.
+    (let ((list (make-list length 0)))
+      (should (= (proper-list-p list) length))
+      (should (not (proper-list-p (nconc list 0)))))
+    ;; Circular lists.
+    (dotimes (n (1+ length))
+      (let ((circle (make-list (1+ length) 0)))
+        (should (not (proper-list-p (nconc circle (nthcdr n circle))))))))
+  ;; Atoms.
+  (should (not (proper-list-p 0)))
+  (should (not (proper-list-p "")))
+  (should (not (proper-list-p [])))
+  (should (not (proper-list-p (make-bool-vector 0 nil))))
+  (should (not (proper-list-p (make-symbol "a")))))
+
 (provide 'fns-tests)
diff --git a/test/src/json-tests.el b/test/src/json-tests.el
index 04f91f4..542eec1 100644
--- a/test/src/json-tests.el
+++ b/test/src/json-tests.el
@@ -117,6 +117,14 @@
     (should (equal (json-parse-string input :object-type 'plist)
                    '(:abc [9 :false] :def :null)))))
 
+(ert-deftest json-parse-string/array ()
+  (skip-unless (fboundp 'json-parse-string))
+  (let ((input "[\"a\", 1, [\"b\", 2]]"))
+    (should (equal (json-parse-string input)
+                   ["a" 1 ["b" 2]]))
+    (should (equal (json-parse-string input :array-type 'list)
+                   '("a" 1 ("b" 2))))))
+
 (ert-deftest json-parse-string/string ()
   (skip-unless (fboundp 'json-parse-string))
   (should-error (json-parse-string "[\"formfeed\f\"]") :type 'json-parse-error)



reply via email to

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