emacs-diffs
[Top][All Lists]
Advanced

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

feature/native-comp 7a161dc 3/3: Merge remote-tracking branch 'savahnna/


From: Andrea Corallo
Subject: feature/native-comp 7a161dc 3/3: Merge remote-tracking branch 'savahnna/master' into HEAD
Date: Sun, 26 Jul 2020 04:06:46 -0400 (EDT)

branch: feature/native-comp
commit 7a161dc688f0eeee64e307a55efbc7d11bab3627
Merge: 79ed903 9f01ce6
Author: Andrea Corallo <akrl@sdf.org>
Commit: Andrea Corallo <akrl@sdf.org>

    Merge remote-tracking branch 'savahnna/master' into HEAD
---
 CONTRIBUTE                        |   2 +-
 doc/emacs/custom.texi             |  35 +++++----
 doc/emacs/display.texi            |   4 +-
 doc/emacs/emacs.texi              |   6 ++
 doc/emacs/maintaining.texi        | 161 ++++++++++++++++++++++++++++----------
 doc/lispref/os.texi               |   4 +
 doc/misc/epa.texi                 |   5 +-
 doc/misc/flymake.texi             |   2 +-
 etc/NEWS                          |  20 +++--
 etc/NEWS.27                       |   2 +-
 lisp/allout-widgets.el            |  81 +++++++++++--------
 lisp/bookmark.el                  |   3 +-
 lisp/calc/calc.el                 |   2 +-
 lisp/cus-edit.el                  |   7 +-
 lisp/emacs-lisp/byte-opt.el       |  10 +++
 lisp/emacs-lisp/eldoc.el          |  61 ++++++++++-----
 lisp/epa-mail.el                  |   5 +-
 lisp/gnus/gnus-start.el           |   1 +
 lisp/gnus/mm-decode.el            |  10 ++-
 lisp/ielm.el                      |   4 +-
 lisp/man.el                       |   4 +-
 lisp/net/gnutls.el                |   5 +-
 lisp/net/tramp.el                 |   8 +-
 lisp/progmodes/bug-reference.el   |  66 ++++++++++------
 lisp/progmodes/project.el         |  79 ++++++++++++++++---
 lisp/shell.el                     |   7 +-
 lisp/url/url.el                   |  19 ++++-
 lisp/vc/vc-git.el                 |   2 +-
 lisp/xwidget.el                   |   3 +
 src/emacs-module.c                | 108 ++++++++++++++++++-------
 src/emacs.c                       |   2 +
 src/w32proc.c                     |  10 +--
 test/data/emacs-module/mod-test.c |  32 ++++++++
 test/src/emacs-module-tests.el    |  29 +++++++
 34 files changed, 587 insertions(+), 212 deletions(-)

diff --git a/CONTRIBUTE b/CONTRIBUTE
index 26efbd7..4e42c7a 100644
--- a/CONTRIBUTE
+++ b/CONTRIBUTE
@@ -63,7 +63,7 @@ also possible to use a command like
 However, we prefer the 'git format-patch' method with attachment, as
 doing so delivers patches in the correct and easily-recognizable format
 more reliably, and makes the job of applying the patches easier and less
-error-prone.  It also allows to send patches whose author is someone
+error-prone.  It also allows sending patches whose author is someone
 other than the email sender.
 
 Once the cumulative amount of your submissions exceeds about 15 lines
diff --git a/doc/emacs/custom.texi b/doc/emacs/custom.texi
index 719e09e..acd7fb1 100644
--- a/doc/emacs/custom.texi
+++ b/doc/emacs/custom.texi
@@ -1630,6 +1630,10 @@ characters are actually defined by this map.
 @item
 @vindex mode-specific-map
 @code{mode-specific-map} is for characters that follow @kbd{C-c}.
+@item
+@vindex project-prefix-map
+@code{project-prefix-map} is for characters that follow @kbd{C-x p},
+used for project-related commands (@pxref{Projects}).
 @end itemize
 
 @node Local Keymaps
@@ -2252,10 +2256,13 @@ as a function from Lisp programs.
   When Emacs is started, it normally tries to load a Lisp program from
 an @dfn{initialization file}, or @dfn{init file} for short.  This
 file, if it exists, specifies how to initialize Emacs for you.
-If the file @file{~/.config/emacs/init.el} exists, it is used as the
-init file; otherwise Emacs may look at @file{~/.emacs.el},
-@file{~/.emacs}, @file{~/.emacs.d/init.el}, or other locations.
-@xref{Find Init}.
+Traditionally, file @file{~/.emacs} is used as the init file, although
+Emacs also looks at @file{~/.emacs.el}, @file{~/.emacs.d/init.el},
+@file{~/.config/emacs/init.el}, or other locations.  @xref{Find Init}.
+
+You may find it convenient to have all your Emacs configuration in one
+directory, in which case you should use @file{~/.emacs.d/init.el} or
+the XDG-compatible @file{~/.config/emacs/init.el}.
 
   You can use the command line switch @samp{-q} to prevent loading
 your init file, and @samp{-u} (or @samp{--user}) to specify a
@@ -2661,23 +2668,21 @@ library.  @xref{Hooks}.
 @subsection How Emacs Finds Your Init File
 
   Emacs normally finds your init file in a location under your home
-directory.  @xref{Init File}.  By default this location is
-@file{~/.emacs.d/init.el} where @file{~/} stands for your home directory.
-This default can be overridden as described below.
+directory.  @xref{Init File}.
 
-Emacs looks for your init file
-using the filenames @file{~/.emacs.el}, @file{~/.emacs}, or
-@file{~/.emacs.d/init.el}; you can choose to use any one of these
-names.  (Note that only the locations directly in your home directory
-have a leading dot in the location's basename.)
+  Emacs looks for your init file using the filenames @file{~/.emacs.el},
+@file{~/.emacs}, or @file{~/.emacs.d/init.el} in that order; you can
+choose to use any one of these names.  (Note that only the locations
+directly in your home directory have a leading dot in the location's
+basename.)
 
 Emacs can also look in an XDG-compatible location for @file{init.el},
 the default is the directory @file{~/.config/emacs}.  This can be
 overriden by setting @env{XDG_CONFIG_HOME} in your environment, its
 value replaces @file{~/.config} in the name of the default XDG init
-file.  However @file{~/.emacs.d} and @file{~/.emacs} are always
-preferred if they exist, which means that you must delete or rename
-them in order to use the XDG location.
+file.  However @file{~/.emacs.d}, @file{~/.emacs}, and
+@file{~/.emacs.el} are always preferred if they exist, which means
+that you must delete or rename them in order to use the XDG location.
 
 Note also that if neither the XDG location nor @file{~/.emacs.d}
 exist, then Emacs will create @file{~/.emacs.d} (and therefore use it
diff --git a/doc/emacs/display.texi b/doc/emacs/display.texi
index a2ace00..e96e43b 100644
--- a/doc/emacs/display.texi
+++ b/doc/emacs/display.texi
@@ -1584,7 +1584,9 @@ sequences}, with the @code{escape-glyph} face.  For 
instance,
 character code @code{U+0098} (octal 230) is displayed as @samp{\230}.
 If you change the buffer-local variable @code{ctl-arrow} to
 @code{nil}, the @acronym{ASCII} control characters are also displayed
-as octal escape sequences instead of caret escape sequences.
+as octal escape sequences instead of caret escape sequences.  (You can
+also request that raw bytes be shown in hex, @pxref{Display Custom,
+display-raw-bytes-as-hex}.)
 
 @vindex nobreak-char-display
 @cindex non-breaking space
diff --git a/doc/emacs/emacs.texi b/doc/emacs/emacs.texi
index 6b82aeb..5b6b7b7 100644
--- a/doc/emacs/emacs.texi
+++ b/doc/emacs/emacs.texi
@@ -857,6 +857,12 @@ Customizing VC
 * CVS Options::           Options for CVS.
 @end ifnottex
 
+Projects
+
+* Project File Commands::   Commands for handling project files.
+* Project Buffer Commands:: Commands for handling project buffers.
+* Switching Projects::      Switching between projects.
+
 Change Logs
 
 * Change Log Commands:: Commands for editing change log files.
diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi
index cc7415e..43ec2d4 100644
--- a/doc/emacs/maintaining.texi
+++ b/doc/emacs/maintaining.texi
@@ -1657,12 +1657,43 @@ the project back-end.  For example, the VC back-end 
doesn't consider
 ``ignored'' files (@pxref{VC Ignore}) to be part of the project.
 
 @menu
-* Project File Commands:: Commands for handling project files.
-* Switching Projects::    Switching between projects.
+* Project File Commands::   Commands for handling project files.
+* Project Buffer Commands:: Commands for handling project buffers.
+* Switching Projects::      Switching between projects.
 @end menu
 
 @node Project File Commands
-@subsection Project File Commands
+@subsection Project Commands That Operate on Files
+
+@table @kbd
+@item C-x p f
+Visit a file that belongs to the current project
+(@code{project-find-file}).
+@item C-x p g
+Find matches for a regexp in all files that belong to the current
+project (@code{project-find-regexp}).
+@item M-x project-search
+Interactively search for regexp matches in all files that belong to
+the current project.
+@item C-x p r
+Perform query-replace for a regexp in all files that belong to the
+current project (@code{project-query-replace-regexp}).
+@item C-x p d
+Run Dired in the current project's root directory
+(@code{project-dired}).
+@item C-x p v
+Run @code{vc-dir} in the current project's root directory
+(@code{project-vc-dir}).
+@item C-x p s
+Start an inferior shell in the current project's root directory
+(@code{project-shell}).
+@item C-x p e
+Start Eshell in the current project's root directory
+(@code{project-eshell}).
+@item C-x p c
+Run compilation in the current project's root directory
+(@code{project-compile}).
+@end table
 
   Emacs provides commands for handling project files conveniently.
 This subsection describes these commands.
@@ -1676,25 +1707,26 @@ doesn't seem to belong to a recognizable project, these 
commands
 prompt you for the project directory.
 
 @findex project-find-file
-  The command @code{project-find-file} is a convenient way of visiting
-files (@pxref{Visiting}) that belong to the current project.  Unlike
-@kbd{C-x C-f}, this command doesn't require to type the full file name
-of the file to visit, you can type only the file's base name (i.e.,
-omit the leading directories).  In addition, the completion candidates
-considered by the command include only the files belonging to the
-current project, and nothing else.  If there's a file name at point,
-this command offers that file as the default to visit.
+  The command @kbd{C-x p f} (@code{project-find-file}) is a convenient
+way of visiting files (@pxref{Visiting}) that belong to the current
+project.  Unlike @kbd{C-x C-f}, this command doesn't require to type
+the full file name of the file to visit, you can type only the file's
+base name (i.e., omit the leading directories).  In addition, the
+completion candidates considered by the command include only the files
+belonging to the current project, and nothing else.  If there's a file
+name at point, this command offers that file as the default to visit.
 
 @findex project-find-regexp
-  The command @code{project-find-regexp} is similar to @code{rgrep}
-(@pxref{Grep Searching}), but it searches only the files that belong
-to the current project.  The command prompts for the regular
-expression to search, and pops up an Xref mode buffer with the search
-results, where you can select a match using the Xref mode commands
-(@pxref{Xref Commands}).  When invoked with a prefix argument, this
-command additionally prompts for the base directory from which to
-start the search; this allows, for example, to limit the search only
-to project files under a certain subdirectory of the project root.
+  The command @kbd{C-x p g} (@code{project-find-regexp}) is similar to
+@code{rgrep} (@pxref{Grep Searching}), but it searches only the files
+that belong to the current project.  The command prompts for the
+regular expression to search, and pops up an Xref mode buffer with the
+search results, where you can select a match using the Xref mode
+commands (@pxref{Xref Commands}).  When invoked with a prefix
+argument, this command additionally prompts for the base directory
+from which to start the search; this allows, for example, to limit the
+search only to project files under a certain subdirectory of the
+project root.
 
 @findex project-search
   @kbd{M-x project-search} is an interactive variant of
@@ -1706,7 +1738,7 @@ matched file.  To find the rest of the matches, type 
@w{@kbd{M-x
 fileloop-continue @key{RET}}}.
 
 @findex project-query-replace-regexp
-  @kbd{M-x project-query-replace-regexp} is similar to
+  @kbd{C-x p r} (@code{project-query-replace-regexp}) is similar to
 @code{project-search}, but it prompts you for whether to replace each
 match it finds, like @code{query-replace} does (@pxref{Query
 Replace}), and continues to the next match after you respond.  If your
@@ -1714,40 +1746,85 @@ response causes Emacs to exit the query-replace loop, 
you can later
 continue with @w{@kbd{M-x fileloop-continue @key{RET}}}.
 
 @findex project-dired
-  The command @code{project-dired} opens a Dired buffer
-(@pxref{Dired}) listing the files in the current project's root
+  The command @kbd{C-x p d} (@code{project-dired}) opens a Dired
+buffer (@pxref{Dired}) listing the files in the current project's root
 directory.
 
 @findex project-vc-dir
-  The command @code{project-vc-dir} opens a VC Directory buffer
-(@pxref{VC Directory Mode}) listing the version control statuses of
-the files in a directory tree under the current project's
-root directory.
+  The command @kbd{C-x p v} (@code{project-vc-dir}) opens a VC
+Directory buffer (@pxref{VC Directory Mode}) listing the version
+control statuses of the files in a directory tree under the current
+project's root directory.
 
 @findex project-shell
-  The command @code{project-shell} starts a shell session
-(@pxref{Shell}) in a new buffer with the current project's root as the
-working directory.
+  The command @kbd{C-x p s} (@code{project-shell}) starts a shell
+session (@pxref{Shell}) in a new buffer with the current project's
+root as the working directory.
 
 @findex project-eshell
-  The command @code{project-eshell} starts an Eshell session in a new
-buffer with the current project's root as the working directory.
-@xref{Top,Eshell,Eshell, eshell, Eshell: The Emacs Shell}.
+  The command @kbd{C-x p e} (@code{project-eshell}) starts an Eshell
+session in a new buffer with the current project's root as the working
+directory.  @xref{Top,Eshell,Eshell, eshell, Eshell: The Emacs Shell}.
+
+@findex project-compile
+  The command @kbd{C-x p c} (@code{project-compile}) runs compilation
+(@pxref{Compilation}) in the current project's root directory.
+
+@node Project Buffer Commands
+@subsection Project Commands That Operate on Buffers
+
+@table @kbd
+@item C-x p b
+Switch to another buffer belonging to the current project
+(@code{project-switch-to-buffer}).
+@item C-x p k
+Kill all live buffers that belong to the current project
+(@code{project-kill-buffers}).
+@end table
+
+@findex project-switch-to-buffer
+  Working on a project could potentially involve having many buffers
+visiting files that belong to the project, and also buffers that
+belong to the project, but don't visit any files (like the
+@file{*compilation*} buffer created by @code{project-compile}).  The
+command @kbd{C-x p b} (@code{project-switch-to-buffer}) helps you
+switch between buffers that belong to the current project by prompting
+for a buffer to switch and considering only the current project's
+buffers as candidates for completion.
+
+@findex project-kill-buffers
+@vindex project-kill-buffers-ignores
+  When you finish working on the project, you may wish to kill all the
+buffers that belong to the project, to keep your Emacs session
+smaller.  The command @kbd{C-x p k} (@code{project-kill-buffers})
+accomplishes that: it kills all the buffers that belong to the current
+project, except if @code{project-kill-buffers-ignores} tells
+otherwise.
 
 @node Switching Projects
 @subsection Switching Projects
 
+@table @kbd
+@item C-x p p
+Run an Emacs command for another project (@code{project-switch-project}).
+@end table
+
+@findex project-switch-project
+@vindex project-switch-commands
   Commands that operate on project files (@pxref{Project File
 Commands}) will conveniently prompt you for a project directory when
-no project is current.  When you are inside a project but you want to
-operate on a different project, the command
-@code{project-switch-project} can be used.
-
-  This command prompts you to choose a directory among known project
-roots, and then displays the menu of available commands to operate on
-the chosen project.  The variable @code{project-switch-commands}
-controls which commands are available in the menu, and by which keys
-they are invoked.
+no project is current.  When you are inside some project, but you want
+to operate on a different project, use the @kbd{C-x p p} command
+(@code{project-switch-project}).  This command prompts you to choose a
+directory among known project roots, and then displays the menu of
+available commands to operate on the project you choose.  The variable
+@code{project-switch-commands} controls which commands are available
+in the menu, and which key invokes each command.
+
+@vindex project-list-file
+  The variable @code{project-list-file} names the file in which Emacs
+records the list of known projects.  It defaults to the file
+@file{projects} in @code{user-emacs-directory} (@pxref{Find Init}).
 
 @node Change Log
 @section Change Logs
diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi
index 9189452..942bda1 100644
--- a/doc/lispref/os.texi
+++ b/doc/lispref/os.texi
@@ -707,6 +707,10 @@ the Emacs process.  (This is useful primarily in batch 
operation; see
 If @var{exit-data} is a string, its contents are stuffed into the
 terminal input buffer so that the shell (or whatever program next reads
 input) can read them.
+
+If @var{exit-data} is neither an integer nor a string, or is omitted,
+that means to use the (system-specific) exit status which indicates
+successful program termination.
 @end deffn
 
 @cindex SIGTERM
diff --git a/doc/misc/epa.texi b/doc/misc/epa.texi
index 49b6b53..fa1833a 100644
--- a/doc/misc/epa.texi
+++ b/doc/misc/epa.texi
@@ -337,7 +337,8 @@ Verify OpenPGP cleartext signed messages in the current 
buffer.
 @kindex C-c C-e C-s
 @kindex C-c C-e s
 @findex epa-mail-sign
-Compose a signed message from the current buffer.
+Compose a signed message from the current buffer, using your default
+key.  With a prefix argument, select the key to use interactively.
 
 @item C-c C-e C-e and C-c C-e e
 @kindex C-c C-e C-e
@@ -352,6 +353,8 @@ key in the recipient list, use @samp{encrypt-to} option in
 addresses using the @code{epa-mail-aliases} list.  You can also
 use that option to ignore specific recipients for encryption purposes.
 
+With prefix argument, asks you to select the recipients interactively,
+whether to sign, and which key(s) to sign with.
 @end table
 
 @node Encrypting/decrypting gpg files,  , Mail-mode integration, Commands
diff --git a/doc/misc/flymake.texi b/doc/misc/flymake.texi
index 89d2265..19dcb19 100644
--- a/doc/misc/flymake.texi
+++ b/doc/misc/flymake.texi
@@ -684,7 +684,7 @@ Binding,,, elisp, The Emacs Lisp Reference Manual}) to be 
active.
                                                         msg)
                        into diags
                        finally (funcall report-fn diags)))
-                  (flymake-log :warning "Cancelling obsolete check %s"
+                  (flymake-log :warning "Canceling obsolete check %s"
                                proc))
               ;; Cleanup the temporary buffer used to hold the
               ;; check's output.
diff --git a/etc/NEWS b/etc/NEWS
index 7c6c9fe..650b958 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -502,21 +502,31 @@ information, see the related entry about 'shr-browse-url' 
above.
 
 *** New user option 'project-vc-merge-submodules'.
 
-*** Previously used project directories are now suggested by
-all commands that prompt for a project directory.
+*** Project commands now have their own history.
+Previously used project directories are now suggested by all commands
+that prompt for a project directory.
+
++++
+*** New prefix keymap 'project-prefix-map'.
+Key sequences that invoke project-related commands start with the
+prefix 'C-x p'.  Type "C-x p C-h" to show the full list.
 
 +++
 *** New commands 'project-dired', 'project-vc-dir', 'project-shell',
 'project-eshell'.  These commands run Dired/VC-Dir and Shell/Eshell in
 a project's root directory, respectively.
 
-*** New command 'project-compile', which runs compilation.
++++
+*** New command 'project-compile'.
+This command runs compilation in the current project's root
+directory.
 
 +++
 *** New command 'project-switch-project'.
 This command lets you "switch" to another project and run a project
 command chosen from a dispatch menu.
 
++++
 *** New user option 'project-list-file'.
 
 ** json.el
@@ -566,8 +576,8 @@ appropriate values for those two variables.  There are 
three guessing
 mechanisms so far: based on version control information of the current
 buffer's file, based on newsgroup/mail-folder name and several news
 and mail message headers in Gnus buffers, and based on IRC channel and
-server in rcirc buffers.  All mechanisms are extensible with custom
-rules, see the variables 'bug-reference-setup-from-vc-alist',
+network in rcirc and ERC buffers.  All mechanisms are extensible with
+custom rules, see the variables 'bug-reference-setup-from-vc-alist',
 'bug-reference-setup-from-mail-alist', and
 'bug-reference-setup-from-irc-alist'.
 
diff --git a/etc/NEWS.27 b/etc/NEWS.27
index 10a6e39..2c8fa9d 100644
--- a/etc/NEWS.27
+++ b/etc/NEWS.27
@@ -270,7 +270,7 @@ doing before changing the value.
 +++
 ** Native GnuTLS connections can now use client certificates.
 Previously, this support was only available when using the external
-'gnutls-cli' command.  Call 'open-network-stream' with
+'gnutls-cli' or 'starttls' command.  Call 'open-network-stream' with
 ':client-certificate t' to trigger looking up of per-server
 certificates via 'auth-source'.
 
diff --git a/lisp/allout-widgets.el b/lisp/allout-widgets.el
index fbdddca..2a8dced 100644
--- a/lisp/allout-widgets.el
+++ b/lisp/allout-widgets.el
@@ -415,15 +415,17 @@ not altered with an escape sequence.")
 ;;;_   , Widget element formatting
 ;;;_    = allout-item-icon-keymap
 (defvar allout-item-icon-keymap
-  (let ((km (make-sparse-keymap)))
+  (let ((km (make-sparse-keymap))
+        (as-parent (if (current-local-map)
+                       (make-composed-keymap (current-local-map)
+                                             (current-global-map))
+                     (current-global-map))))
+    ;; The keymap parent is reset on the each local var when mode starts.
+    (set-keymap-parent km as-parent)
     (dolist (digit '("0" "1" "2" "3"
                      "4" "5" "6" "7" "8" "9"))
       (define-key km digit 'digit-argument))
     (define-key km "-" 'negative-argument)
-;;    (define-key km [(return)] 'allout-tree-expand-command)
-;;    (define-key km [(meta return)] 'allout-toggle-torso-command)
-;;    (define-key km [(down-mouse-1)] 'allout-item-button-click)
-;;    (define-key km [(down-mouse-2)] 'allout-toggle-torso-event-command)
     ;; Override underlying mouse-1 and mouse-2 bindings in icon territory:
     (define-key km [(mouse-1)] (lambda () (interactive) nil))
     (define-key km [(mouse-2)] (lambda () (interactive) nil))
@@ -433,17 +435,16 @@ not altered with an escape sequence.")
 
     km)
   "General tree-node key bindings.")
+(make-variable-buffer-local 'allout-item-icon-keymap)
 ;;;_    = allout-item-body-keymap
 (defvar allout-item-body-keymap
   (let ((km (make-sparse-keymap))
-        (local-map (current-local-map)))
-;;    (define-key km [(control return)] 'allout-tree-expand-command)
-;;    (define-key km [(meta return)] 'allout-toggle-torso-command)
-    ;; XXX We need to reset this per buffer's mode; we do so in
-    ;; allout-widgets-mode.
-    (if local-map
-        (set-keymap-parent km local-map))
-
+        (as-parent (if (current-local-map)
+                       (make-composed-keymap (current-local-map)
+                                             (current-global-map))
+                     (current-global-map))))
+    ;; The keymap parent is reset on the each local var when mode starts.
+    (set-keymap-parent km as-parent)
     km)
   "General key bindings for the text content of outline items.")
 (make-variable-buffer-local 'allout-item-body-keymap)
@@ -456,6 +457,7 @@ not altered with an escape sequence.")
     (set-keymap-parent km allout-item-icon-keymap)
     km)
   "Keymap used in the item cue area - the space between the icon and 
headline.")
+(make-variable-buffer-local 'allout-cue-span-keymap)
 ;;;_    = allout-escapes-category
 (defvar allout-escapes-category nil
   "Symbol for category of text property used to hide escapes of prefix-like
@@ -566,8 +568,13 @@ outline hot-spot navigation (see `allout-mode')."
         (add-to-invisibility-spec '(allout-torso . t))
         (add-to-invisibility-spec 'allout-escapes)
 
-        (if (current-local-map)
-            (set-keymap-parent allout-item-body-keymap (current-local-map)))
+        (let ((as-parent (if (current-local-map)
+                             (make-composed-keymap (current-local-map)
+                                                   (current-global-map))
+                           (current-global-map))))
+          (set-keymap-parent allout-item-body-keymap as-parent)
+          ;; allout-cue-span-keymap uses allout-item-icon-keymap as parent.
+          (set-keymap-parent allout-item-icon-keymap as-parent))
 
         (add-hook 'allout-exposure-change-functions
                   'allout-widgets-exposure-change-recorder nil 'local)
@@ -677,7 +684,7 @@ outline hot-spot navigation (see `allout-mode')."
   (setplist 'allout-cue-span-category nil)
   (put 'allout-cue-span-category 'evaporate t)
   (put 'allout-cue-span-category
-       'modification-hooks '(allout-body-modification-handler))
+       'modification-hooks '(allout-graphics-modification-handler))
   (put 'allout-cue-span-category 'local-map allout-cue-span-keymap)
   (put 'allout-cue-span-category 'mouse-face widget-button-face)
   (put 'allout-cue-span-category 'pointer 'arrow)
@@ -988,6 +995,7 @@ Generally invoked via `allout-exposure-change-functions'."
         ;; have to distinguish between concealing and exposing so that, eg,
         ;; `allout-expose-topic's mix is handled properly.
         handled-expose
+        handled-conceal
         covered
         deactivate-mark)
 
@@ -1594,7 +1602,10 @@ We return the item-widget corresponding to the item at 
point."
       (if is-container
           (progn (widget-put item-widget :is-container t)
                  (setq reverse-siblings-chart (list 1)))
-        (goto-char (widget-apply parent :actual-position :from))
+        (let ((parent-position (widget-apply parent
+                                             :actual-position :from)))
+          (when parent-position
+            (goto-char parent-position)))
         (if (widget-get parent :is-container)
             ;; `allout-goto-prefix' will go to first non-container item:
             (allout-goto-prefix)
@@ -1994,8 +2005,7 @@ reapplying this method will rectify the glyphs."
   ;; NOTE: most of the cue-area
 
   (when (not (widget-get item-widget :is-container))
-    (let* ((cue-start (or (widget-get item-widget :distinctive-end)
-                          (widget-get item-widget :icon-end)))
+    (let* ((cue-start (widget-get item-widget :icon-end))
            (body-start (widget-get item-widget :body-start))
            ;(expanded (widget-get item-widget :expanded))
            ;(has-subitems (widget-get item-widget :has-subitems))
@@ -2050,19 +2060,22 @@ Optional FORCE means force reassignment of the region 
property."
 ;;;_   > allout-widgets-undecorate-region (start end)
 (defun allout-widgets-undecorate-region (start end)
   "Eliminate widgets and decorations for all items in region from START to 
END."
-  (let ((next start)
-        widget)
+  (let (done next widget
+        (end (or end (point-max))))
     (save-excursion
       (goto-char start)
-      (while (<  (setq next (next-single-char-property-change next
-                                                              'display
-                                                              (current-buffer)
-                                                              end))
-                 end)
-        (goto-char next)
-        (when (setq widget (allout-get-item-widget))
-          ;; if the next-property/overly progression got us to a widget:
-          (allout-widgets-undecorate-item widget t))))))
+      (while (not done)
+        (when (and (allout-on-current-heading-p)
+                   (setq widget (allout-get-item-widget)))
+            (if widget
+                (allout-widgets-undecorate-item widget t)))
+        (goto-char (setq next
+                         (next-single-char-property-change (point)
+                                                           'display
+                                                           (current-buffer)
+                                                           end)))
+        (if (>= next end)
+            (setq done t))))))
 ;;;_   > allout-widgets-undecorate-text (text)
 (defun allout-widgets-undecorate-text (text)
   "Eliminate widgets and decorations for all items in TEXT."
@@ -2389,7 +2402,7 @@ The elements of LIST are not copied, just the list 
structure itself."
 ;;;_ : provide
 (provide 'allout-widgets)
 
-;;;_. Local emacs vars.
-;;;_ , Local variables:
-;;;_ , allout-layout: (-1 : 0)
-;;;_ , End:
+;;;_ . Local emacs vars.
+;;;_  , Local variables:
+;;;_  , allout-layout: (-1 : 0)
+;;;_  , End:
diff --git a/lisp/bookmark.el b/lisp/bookmark.el
index 5bb1698..de7d60f 100644
--- a/lisp/bookmark.el
+++ b/lisp/bookmark.el
@@ -1774,7 +1774,8 @@ Bookmark names preceded by a \"*\" have annotations.
 \\[bookmark-bmenu-show-annotation] -- show the annotation, if it exists, for 
the current bookmark
   in another buffer.
 \\[bookmark-bmenu-show-all-annotations] -- show the annotations of all 
bookmarks in another buffer.
-\\[bookmark-bmenu-edit-annotation] -- edit the annotation for the current 
bookmark."
+\\[bookmark-bmenu-edit-annotation] -- edit the annotation for the current 
bookmark.
+\\[bookmark-bmenu-search] -- incrementally search for bookmarks."
   (setq truncate-lines t)
   (setq buffer-read-only t))
 
diff --git a/lisp/calc/calc.el b/lisp/calc/calc.el
index 4e4fb67..09b4962 100644
--- a/lisp/calc/calc.el
+++ b/lisp/calc/calc.el
@@ -2429,7 +2429,7 @@ the United States."
          (if (and (memq last-command-event '(?@ ?o ?h ?\' ?m))
                   (string-match " " calc-hms-format))
              (insert " "))
-       (if (and (eq this-command last-command)
+       (if (and (memq last-command '(calcDigit-start calcDigit-key))
                 (eq last-command-event ?.))
            (progn
              (require 'calc-ext)
diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el
index 1ec2708..1942f25 100644
--- a/lisp/cus-edit.el
+++ b/lisp/cus-edit.el
@@ -2102,11 +2102,12 @@ and `face'."
        (insert " "))
       (widget-put widget :children children))))
 
-(defun custom-magic-reset (widget)
+(defun custom-magic-reset (widget &optional buffer)
   "Redraw the :custom-magic property of WIDGET."
   (let ((magic (widget-get widget :custom-magic)))
     (when magic
-      (widget-value-set magic (widget-value magic)))))
+      (with-current-buffer (or buffer (current-buffer))
+        (widget-value-set magic (widget-value magic))))))
 
 ;;; The `custom' Widget.
 
@@ -2217,7 +2218,7 @@ and `face'."
       ;; commands like `M-u' (that work on a region in the buffer)
       ;; will upcase the wrong part of the buffer, since more text has
       ;; been inserted before point.
-      (run-with-idle-timer 0.0 nil #'custom-magic-reset widget)
+      (run-with-idle-timer 0.0 nil #'custom-magic-reset widget 
(current-buffer))
       (apply 'widget-default-notify widget args))))
 
 (defun custom-redraw (widget)
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index 194ceee..6f801be 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -709,6 +709,9 @@
              (integer (if integer-is-first arg1 arg2))
              (other (if integer-is-first arg2 arg1)))
         (list (if (eq integer 1) '1+ '1-) other)))
+     ;; (+ x y z) -> (+ (+ x y) z)
+     ((= (length args) 3)
+      `(+ ,(byte-optimize-plus `(+ ,(car args) ,(cadr args))) ,@(cddr args)))
      ;; not further optimized
      ((equal args (cdr form)) form)
      (t (cons '+ args)))))
@@ -737,6 +740,9 @@
        ((and (null (cdr args))
              (numberp (car args)))
         (- (car args)))
+       ;; (- x y z) -> (- (- x y) z)
+       ((= (length args) 3)
+        `(- ,(byte-optimize-minus `(- ,(car args) ,(cadr args))) ,@(cddr 
args)))
        ;; not further optimized
        ((equal args (cdr form)) form)
        (t (cons '- args))))))
@@ -764,6 +770,10 @@
      ((null args) 1)
      ;; (* n) -> n, where n is a number
      ((and (null (cdr args)) (numberp (car args))) (car args))
+     ;; (* x y z) -> (* (* x y) z)
+     ((= (length args) 3)
+      `(* ,(byte-optimize-multiply `(* ,(car args) ,(cadr args)))
+          ,@(cddr args)))
      ;; not further optimized
      ((equal args (cdr form)) form)
      (t (cons '* args)))))
diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el
index 6ed5bff..fcb104e 100644
--- a/lisp/emacs-lisp/eldoc.el
+++ b/lisp/emacs-lisp/eldoc.el
@@ -5,7 +5,7 @@
 ;; Author: Noah Friedman <friedman@splode.com>
 ;; Keywords: extensions
 ;; Created: 1995-10-06
-;; Version: 1.5.0
+;; Version: 1.6.0
 ;; Package-Requires: ((emacs "26.3"))
 
 ;; This is a GNU ELPA :core package.  Avoid functionality that is not
@@ -340,16 +340,32 @@ Also store it in `eldoc-last-message' and return that 
value."
          ;; for us, but do note that the last-message will be gone.
          (setq eldoc-last-message nil))))
 
-;; Decide whether now is a good time to display a message.
-(defun eldoc-display-message-p ()
-  "Return non-nil when it is appropriate to display an ElDoc message."
-  (and (eldoc-display-message-no-interference-p)
-       ;; If this-command is non-nil while running via an idle
-       ;; timer, we're still in the middle of executing a command,
-       ;; e.g. a query-replace where it would be annoying to
-       ;; overwrite the echo area.
-       (not this-command)
-       (eldoc--message-command-p last-command)))
+(defvar-local eldoc--last-request-state nil
+  "Tuple containing information about last ElDoc request.")
+(defun eldoc--request-state ()
+  "Compute information to store in `eldoc--last-request-state'."
+  (list (current-buffer) (buffer-modified-tick) (point)))
+
+(defun eldoc--request-docs-p (request-state)
+  "Return non-nil when it is appropriate to request docs.
+REQUEST-STATE is a candidate for `eldoc--last-request-state'"
+  (and
+   ;; FIXME: The original idea behind this function is to protect the
+   ;; Echo area from ElDoc interference, but since that is only one of
+   ;; the possible outlets of ElDoc, this must soon be reworked.
+   (eldoc-display-message-no-interference-p)
+   (not (and eldoc--doc-buffer
+             (get-buffer-window eldoc--doc-buffer)
+             (equal request-state
+                    (with-current-buffer
+                        eldoc--doc-buffer
+                      eldoc--last-request-state))))
+   ;; If this-command is non-nil while running via an idle
+   ;; timer, we're still in the middle of executing a command,
+   ;; e.g. a query-replace where it would be annoying to
+   ;; overwrite the echo area.
+   (not this-command)
+   (eldoc--message-command-p last-command)))
 
 
 ;; Check various conditions about the current environment that might make
@@ -400,7 +416,8 @@ so that the global value (i.e. the default value of the 
hook) is
 taken into account if the major mode specific function does not
 return any documentation.")
 
-(defvar eldoc--doc-buffer nil "Buffer holding latest eldoc-produced docs.")
+(defvar eldoc--doc-buffer nil "Buffer displaying latest ElDoc-produced docs.")
+
 (defun eldoc-doc-buffer (&optional interactive)
   "Get latest *eldoc* help buffer.  Interactively, display it."
   (interactive (list t))
@@ -410,6 +427,7 @@ return any documentation.")
           (setq eldoc--doc-buffer (get-buffer-create "*eldoc*")))
     (when interactive (display-buffer eldoc--doc-buffer))))
 
+
 (defun eldoc--handle-docs (docs)
   "Display multiple DOCS in echo area.
 DOCS is a list of (STRING PLIST...).  It is already sorted.
@@ -429,9 +447,12 @@ Honor most of `eldoc-echo-area-use-multiline-p'."
                       (integer val)
                       (t 1)))
          (things-reported-on)
+         (request eldoc--last-request-state)
          single-doc single-doc-sym)
       ;; Then, compose the contents of the `*eldoc*' buffer.
       (with-current-buffer (eldoc-doc-buffer)
+        ;; Set doc-buffer's `eldoc--last-request-state', too
+        (setq eldoc--last-request-state request)
         (let ((inhibit-read-only t))
           (erase-buffer) (setq buffer-read-only t)
           (local-set-key "q" 'quit-window)
@@ -741,14 +762,16 @@ should endeavour to display the docstrings eventually 
produced."
 (defun eldoc-print-current-symbol-info (&optional interactive)
   "Document thing at point."
   (interactive '(t))
-  (cond (interactive
-         (eldoc--invoke-strategy))
-        (t
-         (if (not (eldoc-display-message-p))
-             ;; Erase the last message if we won't display a new one.
-             (when eldoc-last-message
-               (eldoc--message nil))
+  (let ((token (eldoc--request-state)))
+    (cond (interactive
+           (eldoc--invoke-strategy))
+          ((not (eldoc--request-docs-p token))
+           ;; Erase the last message if we won't display a new one.
+           (when eldoc-last-message
+             (eldoc--message nil)))
+          (t
            (let ((non-essential t))
+             (setq eldoc--last-request-state token)
              ;; Only keep looking for the info as long as the user hasn't
              ;; requested our attention.  This also locally disables
              ;; inhibit-quit.
diff --git a/lisp/epa-mail.el b/lisp/epa-mail.el
index 00f560a..6347525 100644
--- a/lisp/epa-mail.el
+++ b/lisp/epa-mail.el
@@ -85,7 +85,10 @@ The buffer is expected to contain a mail message."
 ;;;###autoload
 (defun epa-mail-sign (start end signers mode)
   "Sign the current buffer.
-The buffer is expected to contain a mail message."
+The buffer is expected to contain a mail message, and signing is
+performed with your default key.
+With prefix argument, asks you to select interactively the key to
+use from your key ring."
   (declare (interactive-only t))
   (interactive
    (save-excursion
diff --git a/lisp/gnus/gnus-start.el b/lisp/gnus/gnus-start.el
index 78e0749..ba8b91b 100644
--- a/lisp/gnus/gnus-start.el
+++ b/lisp/gnus/gnus-start.el
@@ -2111,6 +2111,7 @@ The info element is shared with the same element of
      ((string= gnus-ignored-newsgroups "")
       (delete-matching-lines "^to\\."))
      (t
+      ;; relint suppression: Duplicated alternative branch
       (delete-matching-lines (concat "^to\\.\\|" gnus-ignored-newsgroups))))
 
     (goto-char (point-min))
diff --git a/lisp/gnus/mm-decode.el b/lisp/gnus/mm-decode.el
index 96695aa..587c4e0 100644
--- a/lisp/gnus/mm-decode.el
+++ b/lisp/gnus/mm-decode.el
@@ -1680,8 +1680,14 @@ If RECURSIVE, search recursively."
                    (t (y-or-n-p
                        (format "Decrypt (S/MIME) part? "))))
                   (mm-view-pkcs7 parts from))
-         (goto-char (point-min))
-         (insert "Content-type: text/plain\n\n")
+         ;; Normally there will be a Content-type header here, but
+         ;; some mailers don't add that to the encrypted part, which
+         ;; makes the subsequent re-dissection fail here.
+         (save-restriction
+           (mail-narrow-to-head)
+           (unless (mail-fetch-field "content-type")
+             (goto-char (point-max))
+             (insert "Content-type: text/plain\n\n")))
          (setq parts (mm-dissect-buffer t)))))
      ((equal subtype "signed")
       (unless (and (setq protocol
diff --git a/lisp/ielm.el b/lisp/ielm.el
index 47c5158..b3654b9 100644
--- a/lisp/ielm.el
+++ b/lisp/ielm.el
@@ -537,7 +537,9 @@ Customized bindings may be defined in `ielm-map', which 
currently contains:
        '(comint-replace-by-expanded-history
          ielm-complete-filename elisp-completion-at-point))
   (add-hook 'eldoc-documentation-functions
-            #'elisp-eldoc-documentation-function nil t)
+            #'elisp-eldoc-var-docstring nil t)
+  (add-hook 'eldoc-documentation-functions
+            #'elisp-eldoc-funcall nil t)
   (set (make-local-variable 'ielm-prompt-internal) ielm-prompt)
   (set (make-local-variable 'comint-prompt-read-only) ielm-prompt-read-only)
   (setq comint-get-old-input 'ielm-get-old-input)
diff --git a/lisp/man.el b/lisp/man.el
index 8a36f3a..3121334 100644
--- a/lisp/man.el
+++ b/lisp/man.el
@@ -1396,7 +1396,7 @@ synchronously, PROCESS is the name of the buffer where 
the manpage
 command is run.  Second argument STRING is the entire string of output."
   (save-excursion
     (let ((Man-buffer (process-buffer process)))
-      (if (null (buffer-name Man-buffer)) ;; deleted buffer
+      (if (not (buffer-live-p Man-buffer)) ;; deleted buffer
          (set-process-buffer process nil)
 
        (with-current-buffer Man-buffer
@@ -1430,7 +1430,7 @@ manpage command."
        (delete-buff nil)
        message)
 
-    (if (null (buffer-name Man-buffer)) ;; deleted buffer
+    (if (not (buffer-live-p Man-buffer)) ;; deleted buffer
        (or (stringp process)
            (set-process-buffer process nil))
 
diff --git a/lisp/net/gnutls.el b/lisp/net/gnutls.el
index cd86b4d..e713c94 100644
--- a/lisp/net/gnutls.el
+++ b/lisp/net/gnutls.el
@@ -105,12 +105,13 @@ Security'."
 
 (defcustom gnutls-trustfiles
   '(
-    "/etc/ssl/certs/ca-certificates.crt"     ; Debian, Ubuntu, Gentoo and Arch 
Linux
+    "/etc/ssl/certs/ca-certificates.crt"     ; Debian, Ubuntu, Gentoo,
+                                             ; Arch, Guix, Parabola
     "/etc/pki/tls/certs/ca-bundle.crt"       ; Fedora and RHEL
     "/etc/ssl/ca-bundle.pem"                 ; Suse
     "/usr/ssl/certs/ca-bundle.crt"           ; Cygwin
     "/usr/local/share/certs/ca-root-nss.crt" ; FreeBSD
-    "/etc/ssl/cert.pem"                      ; macOS
+    "/etc/ssl/cert.pem"                      ; macOS, Dragora, Parabola
     "/etc/certs/ca-certificates.crt"         ; OpenIndiana
     )
   "List of CA bundle location filenames or a function returning said list.
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index cd35e3f..19cf333 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -2012,9 +2012,11 @@ without a visible progress reporter."
      (tramp-message ,vec ,level "%s..." ,message)
      (let ((cookie "failed")
            (tm
-            ;; We start a pulsing progress reporter after 3
-            ;; seconds. Display only when there is a minimum level.
-           (when-let ((pr (and (<= ,level (min tramp-verbose 3))
+            ;; We start a pulsing progress reporter after 3 seconds.
+            ;; Start only when there is no other progress reporter
+            ;; running, and when there is a minimum level.
+           (when-let ((pr (and (null tramp-inhibit-progress-reporter)
+                               (<= ,level (min tramp-verbose 3))
                                (make-progress-reporter ,message nil nil))))
              (run-at-time 3 0.1 #'tramp-progress-reporter-update pr))))
        (unwind-protect
diff --git a/lisp/progmodes/bug-reference.el b/lisp/progmodes/bug-reference.el
index b88ea0a..c52331f 100644
--- a/lisp/progmodes/bug-reference.el
+++ b/lisp/progmodes/bug-reference.el
@@ -353,38 +353,45 @@ and set it if applicable."
 
 This takes action if `bug-reference-mode' is enabled in IRC
 channels using one of Emacs' IRC clients (rcirc and ERC).
-Currently, only rcirc is supported.
+Currently, rcirc and ERC are supported.
 
 Each element has the form
 
-  (CHANNEL-REGEXP SERVER-REGEXP BUG-REGEXP URL-FORMAT)
+  (CHANNEL-REGEXP NETWORK-REGEXP BUG-REGEXP URL-FORMAT)
 
-CHANNEL-REGEXP is a regexp matched against the current mail IRC
-channel name.  SERVER-REGEXP is matched against the IRC server
-name.  If any of those matches, BUG-REGEXP is set as
+CHANNEL-REGEXP is a regexp matched against the current IRC
+channel name (e.g. #emacs).  NETWORK-REGEXP is matched against
+the IRC network name (e.g. freenode).  Both entries are optional.
+If all given entries match, BUG-REGEXP is set as
 `bug-reference-bug-regexp' and URL-FORMAT is set as
 `bug-reference-url-format'.")
 
-(defun bug-reference--maybe-setup-from-irc (channel server)
-  "Set up according to IRC CHANNEL or SERVER.
-CHANNEL is an IRC channel name and SERVER is that channel's
-server name.
+(defun bug-reference--maybe-setup-from-irc (channel network)
+  "Set up according to IRC CHANNEL or NETWORK.
+CHANNEL is an IRC channel name (or generally a target, i.e., it
+could also be a user name) and NETWORK is that channel's network
+name.
 
-If any CHANNEL-REGEXP or SERVER-REGEXP of
-`bug-reference-setup-from-irc-alist' matches CHANNEL or SERVER,
-the corresponding BUG-REGEXP and URL-FORMAT are set."
+If any `bug-reference-setup-from-irc-alist' entry's
+CHANNEL-REGEXP and NETWORK-REGEXP match CHANNEL and NETWORK, the
+corresponding BUG-REGEXP and URL-FORMAT are set."
   (catch 'setup-done
     (dolist (config bug-reference-setup-from-irc-alist)
-      (when (or
-             (and channel
-                  (car config)
-                  (string-match-p (car config) channel))
-             (and server
-                  (nth 1 config)
-                  (string-match-p (car config) server)))
-        (setq-local bug-reference-bug-regexp (nth 2 config))
-        (setq-local bug-reference-url-format (nth 3 config))
-        (throw 'setup-done t)))))
+      (let ((channel-rx (car config))
+            (network-rx (nth 1 config)))
+        (when (and
+               ;; One of both has to be given.
+               (or channel-rx network-rx)
+               ;; The args have to be set.
+               channel network)
+          (when (and
+                 (or (null channel-rx)
+                     (string-match-p channel-rx channel))
+                 (or (null network-rx)
+                     (string-match-p network-rx network)))
+            (setq-local bug-reference-bug-regexp (nth 2 config))
+            (setq-local bug-reference-url-format (nth 3 config))
+            (throw 'setup-done t)))))))
 
 (defvar rcirc-target)
 (defvar rcirc-server-buffer)
@@ -402,6 +409,18 @@ and set it if applicable."
           (with-current-buffer rcirc-server-buffer
             rcirc-server)))))
 
+(declare-function erc-format-target "erc")
+(declare-function erc-network-name "erc-networks")
+
+(defun bug-reference-try-setup-from-erc ()
+  "Try setting up `bug-reference-mode' based on ERC channel and server.
+Test each configuration in `bug-reference-setup-from-irc-alist'
+and set it if applicable."
+  (when (derived-mode-p 'erc-mode)
+    (bug-reference--maybe-setup-from-irc
+     (erc-format-target)
+     (erc-network-name))))
+
 (defun bug-reference--run-auto-setup ()
   (when (or bug-reference-mode
             bug-reference-prog-mode)
@@ -414,7 +433,8 @@ and set it if applicable."
         (catch 'setup
           (dolist (f (list #'bug-reference-try-setup-from-vc
                            #'bug-reference-try-setup-from-gnus
-                           #'bug-reference-try-setup-from-rcirc))
+                           #'bug-reference-try-setup-from-rcirc
+                           #'bug-reference-try-setup-from-erc))
             (when (funcall f)
               (throw 'setup t))))))))
 
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index db8e54b..5cfc6a2 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -37,11 +37,29 @@
 ;; current project, without having to know which package handles
 ;; detection of that project type, parsing its config files, etc.
 ;;
-;; Infrastructure:
+;; This file consists of following parts:
 ;;
-;; Function `project-current', to determine the current project
-;; instance, and 4 (at the moment) generic functions that act on it.
-;; This list is to be extended in future versions.
+;; Infrastructure (the public API):
+;;
+;; Function `project-current' that returns the current project
+;; instance based on the value of the hook `project-find-functions',
+;; and several generic functions that act on it.
+;;
+;; `project-root' must be defined for every project.
+;; `project-files' can be overridden for performance purposes.
+;; `project-ignores' and `project-external-roots' describe the project
+;; files and its relations to external directories.  `project-files'
+;; should be consistent with `project-ignores'.
+;;
+;; This list can change in future versions.
+;;
+;; VC project:
+;;
+;; Originally conceived as an example implementation, now it's a
+;; relatively fast backend that delegates to 'git ls-files' or 'hg
+;; status' to list the project's files.  It honors the VC ignore
+;; files, but supports additions to the list using the user option
+;; `project-vc-ignores' (usually through .dir-locals.el).
 ;;
 ;; Utils:
 ;;
@@ -50,9 +68,49 @@
 ;;
 ;; Commands:
 ;;
-;; `project-find-file', `project-find-regexp' and
-;; `project-or-external-find-regexp' use the current API, and thus
-;; will work in any project that has an adapter.
+;; `project-prefix-map' contains the full list of commands defined in
+;; this package.  This map uses the prefix `C-x p' by default.
+;; Type `C-x p f' to find file in the current project.
+;; Type `C-x p C-h' to see all available commands and bindings.
+;;
+;; All commands defined in this package are implemented using the
+;; public API only.  As a result, they will work with any project
+;; backend that follows the protocol.
+;;
+;; Any third-party code that wants to use this package should likewise
+;; target the public API.  Use any of the built-in commands as the
+;; example.
+;;
+;; How to create a new backend:
+;;
+;; - Consider whether you really should, or whether there are other
+;; ways to reach your goals.  If the backend's performance is
+;; significantly lower than that of the built-in one, and it's first
+;; in the list, it will affect all commands that use it.  Unless you
+;; are going to be using it only yourself or in special circumstances,
+;; you will probably want it to be fast, and it's unlikely to be a
+;; trivial endeavor.  `project-files' is the method to optimize (the
+;; default implementation gets slower the more files the directory
+;; has, and the longer the list of ignores is).
+;;
+;; - Choose the format of the value that represents a project for your
+;; backend (we call it project instance).  Don't use any of the
+;; formats from other backends.  The format can be arbitrary, as long
+;; as the datatype is something `cl-defmethod' can dispatch on.  The
+;; value should be stable (when compared with `equal') across
+;; invocations, meaning calls to that function from buffers belonging
+;; to the same project should return equal values.
+;;
+;; - Write a new function that will determine the current project
+;; based on the directory and add it to `project-find-functions'
+;; (which see) using `add-hook'. It is a good idea to depend on the
+;; directory only, and not on the current major mode, for example.
+;; Because the usual expectation is that all files in the directory
+;; belong to the same project (even if some/most of them are ignored).
+;;
+;; - Define new methods for some or all generic functions for this
+;; backend using `cl-defmethod'.  A `project-root' method is
+;; mandatory, `project-files' is recommended, the rest are optional.
 
 ;;; TODO:
 
@@ -139,7 +197,7 @@ of the project instance object."
             pr (project--find-in-directory directory))))
     (when maybe-prompt
       (if pr
-          (project--add-to-project-list-front pr)
+          (project-remember-project pr)
         (project--remove-from-project-list directory)
         (setq pr (cons 'transient directory))))
     pr))
@@ -517,6 +575,7 @@ DIRS must contain directory names."
 (defvar project-prefix-map
   (let ((map (make-sparse-keymap)))
     (define-key map "f" 'project-find-file)
+    (define-key map "F" 'project-or-external-find-file)
     (define-key map "b" 'project-switch-to-buffer)
     (define-key map "s" 'project-shell)
     (define-key map "d" 'project-dired)
@@ -526,6 +585,7 @@ DIRS must contain directory names."
     (define-key map "k" 'project-kill-buffers)
     (define-key map "p" 'project-switch-project)
     (define-key map "g" 'project-find-regexp)
+    (define-key map "G" 'project-or-external-find-regexp)
     (define-key map "r" 'project-query-replace-regexp)
     map)
   "Keymap for project commands.")
@@ -927,7 +987,8 @@ With some possible metadata (to be decided).")
       (pp project--list (current-buffer))
       (write-region nil nil filename nil 'silent))))
 
-(defun project--add-to-project-list-front (pr)
+;;;###autoload
+(defun project-remember-project (pr)
   "Add project PR to the front of the project list.
 Save the result in `project-list-file' if the list of projects has changed."
   (project--ensure-read-project-list)
diff --git a/lisp/shell.el b/lisp/shell.el
index 1e2679f..dc52841 100644
--- a/lisp/shell.el
+++ b/lisp/shell.el
@@ -184,16 +184,13 @@ shell buffer.  The value may depend on the operating 
system or shell."
     shell-environment-variable-completion
     shell-command-completion
     shell-c-a-p-replace-by-expanded-directory
+    pcomplete-completions-at-point
     shell-filename-completion
-    comint-filename-completion
-    ;; Put `pcomplete-completions-at-point' last so that other
-    ;; functions can run before it does, see bug#34330.
-    pcomplete-completions-at-point)
+    comint-filename-completion)
   "List of functions called to perform completion.
 This variable is used to initialize `comint-dynamic-complete-functions' in the
 shell buffer."
   :type '(repeat function)
-  :version "27.1"
   :group 'shell)
 
 (defcustom shell-command-regexp "[^;&|\n]+"
diff --git a/lisp/url/url.el b/lisp/url/url.el
index 12a8a9c..321e79c 100644
--- a/lisp/url/url.el
+++ b/lisp/url/url.el
@@ -238,7 +238,8 @@ how long to wait for a response before giving up."
   (let ((retrieval-done nil)
        (start-time (current-time))
         (url-asynchronous nil)
-        (asynch-buffer nil))
+        (asynch-buffer nil)
+        (timed-out nil))
     (setq asynch-buffer
          (url-retrieve url (lambda (&rest ignored)
                              (url-debug 'retrieval "Synchronous fetching done 
(%S)" (current-buffer))
@@ -261,7 +262,9 @@ how long to wait for a response before giving up."
        ;; process output.
        (while (and (not retrieval-done)
                     (or (not timeout)
-                       (time-less-p (time-since start-time) timeout)))
+                       (not (setq timed-out
+                                   (time-less-p timeout
+                                                (time-since start-time))))))
          (url-debug 'retrieval
                     "Spinning in url-retrieve-synchronously: %S (%S)"
                     retrieval-done asynch-buffer)
@@ -300,8 +303,16 @@ how long to wait for a response before giving up."
              (when quit-flag
                (delete-process proc))
               (setq proc (and (not quit-flag)
-                             (get-buffer-process asynch-buffer)))))))
-      asynch-buffer)))
+                             (get-buffer-process asynch-buffer))))))
+        ;; On timeouts, make sure we kill any pending processes.
+        ;; There may be more than one if we had a redirect.
+        (when timed-out
+          (when (process-live-p proc)
+            (delete-process proc))
+          (when-let ((aproc (get-buffer-process asynch-buffer)))
+            (when (process-live-p aproc)
+              (delete-process aproc))))))
+    asynch-buffer))
 
 ;; url-mm-callback called from url-mm, which requires mm-decode.
 (declare-function mm-dissect-buffer "mm-decode"
diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el
index b5cb842..7f6e1db 100644
--- a/lisp/vc/vc-git.el
+++ b/lisp/vc/vc-git.el
@@ -1237,7 +1237,7 @@ log entries."
   (set (make-local-variable 'log-view-message-re)
        (if (not (memq vc-log-view-type '(long log-search with-diff)))
           (cadr vc-git-root-log-format)
-        "^commit *\\([0-9a-z]+\\)"))
+        "^commit +\\([0-9a-z]+\\)"))
   ;; Allow expanding short log entries.
   (when (memq vc-log-view-type '(short log-outgoing log-incoming mergebase))
     (setq truncate-lines t)
diff --git a/lisp/xwidget.el b/lisp/xwidget.el
index 775dddf..aed6c09 100644
--- a/lisp/xwidget.el
+++ b/lisp/xwidget.el
@@ -92,6 +92,9 @@ Interactively, URL defaults to the string looking like a url 
around point."
   (or (featurep 'xwidget-internal)
       (user-error "Your Emacs was not compiled with xwidgets support"))
   (when (stringp url)
+    ;; If it's a "naked url", just try adding https: to it.
+    (unless (string-match "\\`[A-Za-z]+:" url)
+      (setq url (concat "https://"; url)))
     (if new-session
         (xwidget-webkit-new-session url)
       (xwidget-webkit-goto-url url))))
diff --git a/src/emacs-module.c b/src/emacs-module.c
index 3d1827c..e4e7da0 100644
--- a/src/emacs-module.c
+++ b/src/emacs-module.c
@@ -78,6 +78,7 @@ To add a new module function, proceed as follows:
 #include "emacs-module.h"
 
 #include <stdarg.h>
+#include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <stdlib.h>
@@ -154,11 +155,11 @@ struct emacs_value_frame
 /* A structure that holds an initial frame (so that the first local
    values require no dynamic allocation) and keeps track of the
    current frame.  */
-static struct emacs_value_storage
+struct emacs_value_storage
 {
   struct emacs_value_frame initial;
   struct emacs_value_frame *current;
-} global_storage;
+};
 
 
 /* Private runtime and environment members.  */
@@ -371,10 +372,57 @@ module_get_environment (struct emacs_runtime *runtime)
 }
 
 /* To make global refs (GC-protected global values) keep a hash that
-   maps global Lisp objects to reference counts.  */
+   maps global Lisp objects to 'struct module_global_reference'
+   objects.  We store the 'emacs_value' in the hash table so that it
+   is automatically garbage-collected (Bug#42482).  */
 
 static Lisp_Object Vmodule_refs_hash;
 
+/* Pseudovector type for global references.  The pseudovector tag is
+   PVEC_OTHER since these values are never printed and don't need to
+   be special-cased for garbage collection.  */
+
+struct module_global_reference {
+  /* Pseudovector header, must come first. */
+  union vectorlike_header header;
+
+  /* Holds the emacs_value for the object.  The Lisp_Object stored
+     therein must be the same as the hash key.  */
+  struct emacs_value_tag value;
+
+  /* Reference count, always positive.  */
+  ptrdiff_t refcount;
+};
+
+static struct module_global_reference *
+XMODULE_GLOBAL_REFERENCE (Lisp_Object o)
+{
+  eassert (PSEUDOVECTORP (o, PVEC_OTHER));
+  return XUNTAG (o, Lisp_Vectorlike, struct module_global_reference);
+}
+
+/* Returns whether V is a global reference.  Only used to check module
+   assertions.  If V is not a global reference, increment *N by the
+   number of global references (for debugging output).  */
+
+static bool
+module_global_reference_p (emacs_value v, ptrdiff_t *n)
+{
+  struct Lisp_Hash_Table *h = XHASH_TABLE (Vmodule_refs_hash);
+  /* Note that we can't use `hash_lookup' because V might be a local
+     reference that's identical to some global reference.  */
+  for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i)
+    {
+      if (!EQ (HASH_KEY (h, i), Qunbound)
+          && &XMODULE_GLOBAL_REFERENCE (HASH_VALUE (h, i))->value == v)
+        return true;
+    }
+  /* Only used for debugging, so we don't care about overflow, just
+     make sure the operation is defined.  */
+  INT_ADD_WRAPV (*n, h->count, n);
+  return false;
+}
+
 static emacs_value
 module_make_global_ref (emacs_env *env, emacs_value value)
 {
@@ -383,21 +431,30 @@ module_make_global_ref (emacs_env *env, emacs_value value)
   Lisp_Object new_obj = value_to_lisp (value), hashcode;
   ptrdiff_t i = hash_lookup (h, new_obj, &hashcode);
 
+  /* Note: This approach requires the garbage collector to never move
+     objects.  */
+
   if (i >= 0)
     {
       Lisp_Object value = HASH_VALUE (h, i);
-      EMACS_INT refcount = XFIXNAT (value) + 1;
-      if (MOST_POSITIVE_FIXNUM < refcount)
+      struct module_global_reference *ref = XMODULE_GLOBAL_REFERENCE (value);
+      bool overflow = INT_ADD_WRAPV (ref->refcount, 1, &ref->refcount);
+      if (overflow)
        overflow_error ();
-      value = make_fixed_natnum (refcount);
-      set_hash_value_slot (h, i, value);
+      return &ref->value;
     }
   else
     {
-      hash_put (h, new_obj, make_fixed_natnum (1), hashcode);
+      struct module_global_reference *ref
+        = ALLOCATE_PLAIN_PSEUDOVECTOR (struct module_global_reference,
+                                       PVEC_OTHER);
+      ref->value.v = new_obj;
+      ref->refcount = 1;
+      Lisp_Object value;
+      XSETPSEUDOVECTOR (value, ref, PVEC_OTHER);
+      hash_put (h, new_obj, value, hashcode);
+      return &ref->value;
     }
-
-  return allocate_emacs_value (env, &global_storage, new_obj);
 }
 
 static void
@@ -411,25 +468,21 @@ module_free_global_ref (emacs_env *env, emacs_value 
global_value)
   Lisp_Object obj = value_to_lisp (global_value);
   ptrdiff_t i = hash_lookup (h, obj, NULL);
 
-  if (i >= 0)
+  if (module_assertions)
     {
-      EMACS_INT refcount = XFIXNAT (HASH_VALUE (h, i)) - 1;
-      if (refcount > 0)
-        set_hash_value_slot (h, i, make_fixed_natnum (refcount));
-      else
-        {
-          eassert (refcount == 0);
-          hash_remove_from_table (h, obj);
-        }
+      ptrdiff_t n = 0;
+      if (! module_global_reference_p (global_value, &n))
+        module_abort ("Global value was not found in list of %"pD"d globals",
+                      n);
     }
 
-  if (module_assertions)
+  if (i >= 0)
     {
-      ptrdiff_t count = 0;
-      if (value_storage_contains_p (&global_storage, global_value, &count))
-        return;
-      module_abort ("Global value was not found in list of %"pD"d globals",
-                    count);
+      Lisp_Object value = HASH_VALUE (h, i);
+      struct module_global_reference *ref = XMODULE_GLOBAL_REFERENCE (value);
+      eassert (0 < ref->refcount);
+      if (--ref->refcount == 0)
+        hash_remove_from_table (h, obj);
     }
 }
 
@@ -1250,7 +1303,7 @@ value_to_lisp (emacs_value v)
           ++num_environments;
         }
       /* Also check global values.  */
-      if (value_storage_contains_p (&global_storage, v, &num_values))
+      if (module_global_reference_p (v, &num_values))
         goto ok;
       module_abort (("Emacs value not found in %"pD"d values "
                     "of %"pD"d environments"),
@@ -1467,10 +1520,7 @@ module_handle_nonlocal_exit (emacs_env *env, enum 
nonlocal_exit type,
 void
 init_module_assertions (bool enable)
 {
-  /* If enabling module assertions, use a hidden environment for
-     storing the globals.  This environment is never freed.  */
   module_assertions = enable;
-  initialize_storage (&global_storage);
 }
 
 /* Return whether STORAGE contains VALUE.  Used to check module
diff --git a/src/emacs.c b/src/emacs.c
index 228ac29..34717cd 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -2356,6 +2356,8 @@ DEFUN ("kill-emacs", Fkill_emacs, Skill_emacs, 0, 1, "P",
        doc: /* Exit the Emacs job and kill it.
 If ARG is an integer, return ARG as the exit program code.
 If ARG is a string, stuff it as keyboard input.
+Any other value of ARG, or ARG omitted, means return an
+exit code that indicates successful program termination.
 
 This function is called upon receipt of the signals SIGTERM
 or SIGHUP, and upon SIGINT in batch mode.
diff --git a/src/w32proc.c b/src/w32proc.c
index 16e32e4..c50f246 100644
--- a/src/w32proc.c
+++ b/src/w32proc.c
@@ -2790,11 +2790,11 @@ sys_kill (pid_t pid, int sig)
               /* Set the foreground window to the child.  */
               if (SetForegroundWindow (cp->hwnd))
                 {
-                 /* Record the state of the Ctrl key: the user could
-                    have it depressed while we are simulating Ctrl-C,
-                    in which case we will have to leave the state of
-                    Ctrl depressed when we are done.  */
-                 short ctrl_state = GetKeyState (VK_CONTROL) & 0x8000;
+                 /* Record the state of the left Ctrl key: the user
+                    could have it depressed while we are simulating
+                    Ctrl-C, in which case we will have to leave the
+                    state of that Ctrl depressed when we are done.  */
+                 short ctrl_state = GetKeyState (VK_LCONTROL) & 0x8000;
 
                   /* Generate keystrokes as if user had typed Ctrl-Break or
                      Ctrl-C.  */
diff --git a/test/data/emacs-module/mod-test.c 
b/test/data/emacs-module/mod-test.c
index 1e64bcd..ed289d7 100644
--- a/test/data/emacs-module/mod-test.c
+++ b/test/data/emacs-module/mod-test.c
@@ -201,7 +201,19 @@ Fmod_test_globref_free (emacs_env *env, ptrdiff_t nargs, 
emacs_value args[],
   return env->intern (env, "ok");
 }
 
+/* Treat a local reference as global and free it.  Module assertions
+   should detect this case even if a global reference representing the
+   same object also exists.  */
 
+static emacs_value
+Fmod_test_globref_invalid_free (emacs_env *env, ptrdiff_t nargs,
+                                emacs_value *args, void *data)
+{
+  emacs_value local = env->make_integer (env, 9876);
+  env->make_global_ref (env, local);
+  env->free_global_ref (env, local);  /* Not allowed. */
+  return env->intern (env, "nil");
+}
 
 /* Return a copy of the argument string where every 'a' is replaced
    with 'b'.  */
@@ -306,6 +318,22 @@ Fmod_test_invalid_load (emacs_env *env, ptrdiff_t nargs, 
emacs_value *args,
   return invalid_stored_value;
 }
 
+/* The next function works in conjunction with the two previous ones.
+   It stows away a copy of the object created by
+   `Fmod_test_invalid_store' in a global reference.  Module assertions
+   should still detect the invalid load of the local reference.  */
+
+static emacs_value global_copy_of_invalid_stored_value;
+
+static emacs_value
+Fmod_test_invalid_store_copy (emacs_env *env, ptrdiff_t nargs,
+                              emacs_value *args, void *data)
+{
+  emacs_value local = Fmod_test_invalid_store (env, 0, NULL, NULL);
+  return global_copy_of_invalid_stored_value
+         = env->make_global_ref (env, local);
+}
+
 /* An invalid finalizer: Finalizers are run during garbage collection,
    where Lisp code can't be executed.  -module-assertions tests for
    this case.  */
@@ -678,12 +706,16 @@ emacs_module_init (struct emacs_runtime *ert)
         1, 1, NULL, NULL);
   DEFUN ("mod-test-globref-make", Fmod_test_globref_make, 0, 0, NULL, NULL);
   DEFUN ("mod-test-globref-free", Fmod_test_globref_free, 4, 4, NULL, NULL);
+  DEFUN ("mod-test-globref-invalid-free", Fmod_test_globref_invalid_free, 0, 0,
+         NULL, NULL);
   DEFUN ("mod-test-string-a-to-b", Fmod_test_string_a_to_b, 1, 1, NULL, NULL);
   DEFUN ("mod-test-userptr-make", Fmod_test_userptr_make, 1, 1, NULL, NULL);
   DEFUN ("mod-test-userptr-get", Fmod_test_userptr_get, 1, 1, NULL, NULL);
   DEFUN ("mod-test-vector-fill", Fmod_test_vector_fill, 2, 2, NULL, NULL);
   DEFUN ("mod-test-vector-eq", Fmod_test_vector_eq, 2, 2, NULL, NULL);
   DEFUN ("mod-test-invalid-store", Fmod_test_invalid_store, 0, 0, NULL, NULL);
+  DEFUN ("mod-test-invalid-store-copy", Fmod_test_invalid_store_copy, 0, 0,
+         NULL, NULL);
   DEFUN ("mod-test-invalid-load", Fmod_test_invalid_load, 0, 0, NULL, NULL);
   DEFUN ("mod-test-invalid-finalizer", Fmod_test_invalid_finalizer, 0, 0,
          NULL, NULL);
diff --git a/test/src/emacs-module-tests.el b/test/src/emacs-module-tests.el
index 411b450..8465fd0 100644
--- a/test/src/emacs-module-tests.el
+++ b/test/src/emacs-module-tests.el
@@ -272,6 +272,24 @@ must evaluate to a regular expression string."
     (mod-test-invalid-store)
     (mod-test-invalid-load)))
 
+(ert-deftest module--test-assertions--load-non-live-object-with-global-copy ()
+  "Check that -module-assertions verify that non-live objects aren't accessed.
+This differs from `module--test-assertions-load-non-live-object'
+in that it stows away a global reference.  The module assertions
+should nevertheless detect the invalid load."
+  (skip-unless (or (file-executable-p mod-test-emacs)
+                   (and (eq system-type 'windows-nt)
+                        (file-executable-p (concat mod-test-emacs ".exe")))))
+  ;; This doesn't yet cause undefined behavior.
+  (should (eq (mod-test-invalid-store-copy) 123))
+  (module--test-assertion (rx "Emacs value not found in "
+                              (+ digit) " values of "
+                              (+ digit) " environments\n")
+    ;; Storing and reloading a local value causes undefined behavior,
+    ;; which should be detected by the module assertions.
+    (mod-test-invalid-store-copy)
+    (mod-test-invalid-load)))
+
 (ert-deftest module--test-assertions--call-emacs-from-gc ()
   "Check that -module-assertions prevents calling Emacs functions
 during garbage collection."
@@ -283,6 +301,17 @@ during garbage collection."
     (mod-test-invalid-finalizer)
     (garbage-collect)))
 
+(ert-deftest module--test-assertions--globref-invalid-free ()
+  "Check that -module-assertions detects invalid freeing of a
+local reference."
+    (skip-unless (or (file-executable-p mod-test-emacs)
+                   (and (eq system-type 'windows-nt)
+                        (file-executable-p (concat mod-test-emacs ".exe")))))
+  (module--test-assertion
+      (rx "Global value was not found in list of " (+ digit) " globals")
+    (mod-test-globref-invalid-free)
+    (garbage-collect)))
+
 (ert-deftest module/describe-function-1 ()
   "Check that Bug#30163 is fixed."
   (with-temp-buffer



reply via email to

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