emacs-diffs
[Top][All Lists]
Advanced

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

feature/native-comp 3e1ec5d 1/6: Merge remote-tracking branch 'savannah/


From: Andrea Corallo
Subject: feature/native-comp 3e1ec5d 1/6: Merge remote-tracking branch 'savannah/master' into HEAD
Date: Wed, 26 Feb 2020 08:09:10 -0500 (EST)

branch: feature/native-comp
commit 3e1ec5d87de2953a8ba0d08602a45b050641ef47
Merge: 48b131c 4a94881
Author: Andrea Corallo <address@hidden>
Commit: Andrea Corallo <address@hidden>

    Merge remote-tracking branch 'savannah/master' into HEAD
---
 admin/merge-gnulib                     |   2 +-
 admin/release-process                  |   9 +-
 doc/emacs/programs.texi                |  24 ++++-
 doc/emacs/sending.texi                 |  11 +-
 doc/lispref/files.texi                 |  27 +++--
 doc/lispref/os.texi                    |   2 +-
 doc/lispref/searching.texi             |   9 +-
 etc/NEWS                               |  22 ++++
 etc/NEWS.27                            |   8 ++
 lib/careadlinkat.h                     |   2 +-
 lib/fchmodat.c                         | 144 ++++++++++++++++++++++++++
 lib/fcntl.in.h                         |   6 ++
 lib/gnulib.mk.in                       |  26 +++++
 lib/lchmod.c                           | 110 ++++++++++++++++++++
 lib/md5.h                              |   8 +-
 lib/sha1.h                             |   7 +-
 lib/sha256.h                           |  20 ++--
 lib/sha512.h                           |  20 ++--
 lib/strftime.h                         |   2 +-
 lib/string.in.h                        |   3 +-
 lisp/comint.el                         |   2 +-
 lisp/dired-aux.el                      |   3 +-
 lisp/doc-view.el                       |   4 +-
 lisp/emacs-lisp/autoload.el            |   2 +-
 lisp/emacs-lisp/byte-opt.el            |   2 +-
 lisp/emacs-lisp/bytecomp.el            |  12 ++-
 lisp/emacs-lisp/cursor-sensor.el       |   7 +-
 lisp/emacs-lisp/eldoc.el               |  77 ++++++++++----
 lisp/emacs-lisp/package.el             |   3 +-
 lisp/emacs-lisp/syntax.el              |  26 ++---
 lisp/eshell/em-pred.el                 |   2 +-
 lisp/eshell/em-prompt.el               |   2 +-
 lisp/files.el                          |  12 ++-
 lisp/gnus/gnus-util.el                 |   4 +-
 lisp/gnus/mail-source.el               |   2 +-
 lisp/gnus/mm-decode.el                 |   2 +-
 lisp/gnus/nnmail.el                    |   2 +-
 lisp/hexl.el                           |   6 +-
 lisp/ielm.el                           |   4 +-
 lisp/net/ange-ftp.el                   |   3 +-
 lisp/net/tramp-adb.el                  |   8 +-
 lisp/net/tramp-compat.el               |  22 +++-
 lisp/net/tramp-gvfs.el                 |   4 +-
 lisp/net/tramp-sh.el                   |  38 +++++--
 lisp/net/tramp-smb.el                  |   4 +-
 lisp/net/tramp-sudoedit.el             |  21 ++--
 lisp/net/tramp.el                      |  22 ++--
 lisp/org/org.el                        |   2 +-
 lisp/progmodes/cc-engine.el            |  30 +++++-
 lisp/progmodes/cfengine.el             |  15 +--
 lisp/progmodes/elisp-mode.el           |   4 +-
 lisp/progmodes/octave.el               |   3 +-
 lisp/progmodes/python.el               |   6 +-
 lisp/progmodes/verilog-mode.el         | 181 +++++++++++++++++++--------------
 lisp/server.el                         |   2 +-
 lisp/textmodes/nroff-mode.el           |   1 -
 lisp/url/url-util.el                   |   4 +-
 lisp/vc/pcvs.el                        |   4 +-
 lisp/vc/vc-cvs.el                      |  45 +++++---
 lisp/vc/vc-dir.el                      |   4 +-
 lisp/vc/vc.el                          |  57 ++++++-----
 m4/fchmodat.m4                         |  82 +++++++++++++++
 m4/getloadavg.m4                       |   6 +-
 m4/gnulib-comp.m4                      |  40 ++++++++
 m4/lchmod.m4                           |  31 ++++++
 m4/nstrftime.m4                        |   4 +-
 nt/gnulib-cfg.mk                       |   2 +
 nt/mingw-cfg.site                      |   3 +
 src/fileio.c                           |  46 +++++----
 src/w32.c                              |  41 +++++++-
 src/w32.h                              |   2 +
 test/lisp/emacs-lisp/bytecomp-tests.el |   7 +-
 test/lisp/net/tramp-tests.el           |  86 +++++++++++++---
 73 files changed, 1142 insertions(+), 324 deletions(-)

diff --git a/admin/merge-gnulib b/admin/merge-gnulib
index 48c81e6..5571194 100755
--- a/admin/merge-gnulib
+++ b/admin/merge-gnulib
@@ -33,7 +33,7 @@ GNULIB_MODULES='
   crypto/md5-buffer crypto/sha1-buffer crypto/sha256-buffer 
crypto/sha512-buffer
   d-type diffseq dosname double-slash-root dtoastr dtotimespec dup2
   environ execinfo explicit_bzero faccessat
-  fcntl fcntl-h fdopendir
+  fchmodat fcntl fcntl-h fdopendir
   filemode filevercmp flexmember fpieee fstatat fsusage fsync
   getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog
   ieee754-h ignore-value intprops largefile lstat
diff --git a/admin/release-process b/admin/release-process
index b3dfad5..1ed7a2e 100644
--- a/admin/release-process
+++ b/admin/release-process
@@ -197,16 +197,11 @@ and change key bindings where necessary.  The current 
list of modes:
 2. Minibuffer binds 'M-s' to 'next-matching-history-element'
    (not useful any more since C-s can now search in the history).
 
-3. 'center-line' in Text mode was already moved to the text formatting
-   keymap as 'M-o M-s' (thus this binding is not necessary any more
-   in 'nroff-mode-map' too and can be removed now from the nroff mode
-   because it can now use the global key binding 'M-o M-s' 'center-line').
-
-4. PCL-CVS binds 'M-s' to 'cvs-status', and log-edit-mode binds it to
+3. PCL-CVS binds 'M-s' to 'cvs-status', and log-edit-mode binds it to
    'log-edit-comment-search-forward'.  Perhaps search commands
    on the global key binding 'M-s' are useless in these modes.
 
-5. Rmail binds '\es' to 'rmail-search'/'rmail-summary-search'.
+4. Rmail binds '\es' to 'rmail-search'/'rmail-summary-search'.
 
 
 * DOCUMENTATION
diff --git a/doc/emacs/programs.texi b/doc/emacs/programs.texi
index 683374c..865a3a6 100644
--- a/doc/emacs/programs.texi
+++ b/doc/emacs/programs.texi
@@ -1269,9 +1269,27 @@ information whenever there is a Lisp function or 
variable at point;
 for a function, it shows the argument list, and for a variable it
 shows the first line of the variable's documentation string.  To
 toggle Eldoc mode, type @kbd{M-x eldoc-mode}.  There's also a Global
-Eldoc mode, which is turned on by default, and affects buffers, such
-as @samp{*scratch*}, whose major mode is Emacs Lisp or Lisp
-Interaction (@w{@kbd{M-x global-eldoc-mode}} to turn it off globally).
+Eldoc mode, which is turned on by default, and affects buffers whose
+major mode sets the variables described below.  Use @w{@kbd{M-x
+global-eldoc-mode}} to turn it off globally.
+
+@vindex eldoc-documentation-function
+@vindex eldoc-documentation-functions
+  These variables can be used to configure ElDoc mode:
+
+@table @code
+@item eldoc-documentation-function
+This variable holds the function which is used to retrieve
+documentation for the item at point from the functions in the hook
+@code{eldoc-documentation-functions}.  By default,
+@code{eldoc-documentation-function} returns the first documentation
+string produced by the @code{eldoc-documentation-functions} hook.
+
+@item eldoc-documentation-functions
+This abnormal hook holds documentation functions.  It acts as a
+collection of backends for ElDoc.  This is what modes should use to
+register their documentation functions with ElDoc.
+@end table
 
 @node Hideshow
 @section Hideshow minor mode
diff --git a/doc/emacs/sending.texi b/doc/emacs/sending.texi
index 283a59a..190549a 100644
--- a/doc/emacs/sending.texi
+++ b/doc/emacs/sending.texi
@@ -338,14 +338,14 @@ Send the message, and leave the mail buffer selected 
(@code{message-send}).
 @kindex C-c C-s @r{(Message mode)}
 @kindex C-c C-c @r{(Message mode)}
 @findex message-send
+@findex message-send-and-exit
 @vindex message-kill-buffer-on-exit
   The usual command to send a message is @kbd{C-c C-c}
-(@code{mail-send-and-exit}).  This sends the message and then
+(@code{message-send-and-exit}).  This sends the message and then
 buries the mail buffer, putting it at the lowest priority for
 reselection.  If you want it to kill the mail buffer instead, change
 the variable @code{message-kill-buffer-on-exit} to @code{t}.
 
-@findex message-send-and-exit
   The command @kbd{C-c C-s} (@code{message-send}) sends the message
 and leaves the buffer selected.  Use this command if you want to
 modify the message (perhaps with new recipients) and send it again.
@@ -361,9 +361,12 @@ twice).
 @cindex Feedmail
 @cindex Sendmail
 @cindex Mailclient
+@vindex message-send-mail-function
 @vindex send-mail-function
-  The variable @code{send-mail-function} controls how the message is
-delivered.  Its value should be one of the following functions:
+  The variable @code{message-send-mail-function} controls how the
+message is delivered (@code{send-mail-function} is used for Mail mode).
+The value of @code{send-mail-function} should be one of the following
+functions:
 
 @table @code
 @item sendmail-query-once
diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi
index a93da39..a69a4e5 100644
--- a/doc/lispref/files.texi
+++ b/doc/lispref/files.texi
@@ -928,7 +928,7 @@ also checks that the file's group would be unchanged.
 This function does not follow symbolic links.
 @end defun
 
-@defun file-modes filename
+@defun file-modes filename &optional flag
 @cindex mode bits
 @cindex file permissions
 @cindex permissions, file
@@ -946,12 +946,19 @@ The highest possible value is 4095 (7777 octal), meaning 
that everyone
 has read, write, and execute permission, the @acronym{SUID} bit is set
 for both others and group, and the sticky bit is set.
 
+By default this function follows symbolic links.  However, if the
+optional argument @var{flag} is the symbol @code{nofollow}, this
+function does not follow @var{filename} if it is a symbolic link;
+this can help prevent inadvertently obtaining the mode bits of a file
+somewhere else, and is more consistent with @code{file-attributes}
+(@pxref{File Attributes}).
+
 @xref{Changing Files}, for the @code{set-file-modes} function, which
 can be used to set these permissions.
 
 @example
 @group
-(file-modes "~/junk/diffs")
+(file-modes "~/junk/diffs" 'nofollow)
      @result{} 492               ; @r{Decimal integer.}
 @end group
 @group
@@ -960,7 +967,7 @@ can be used to set these permissions.
 @end group
 
 @group
-(set-file-modes "~/junk/diffs" #o666)
+(set-file-modes "~/junk/diffs" #o666 'nofollow)
      @result{} nil
 @end group
 
@@ -1801,9 +1808,17 @@ See also @code{delete-directory} in @ref{Create/Delete 
Dirs}.
 @cindex file permissions, setting
 @cindex permissions, file
 @cindex file modes, setting
-@deffn Command set-file-modes filename mode
+@deffn Command set-file-modes filename mode &optional flag
 This function sets the @dfn{file mode} (or @dfn{permissions}) of
-@var{filename} to @var{mode}.  This function follows symbolic links.
+@var{filename} to @var{mode}.
+
+By default this function follows symbolic links.  However, if the
+optional argument @var{flag} is the symbol @code{nofollow}, this
+function does not follow @var{filename} if it is a symbolic link;
+this can help prevent inadvertently changing the mode bits of a file
+somewhere else.  On platforms that do not support changing mode bits
+on a symbolic link, this function signals an error when @var{filename}
+is a symbolic link and @var{flag} is @code{nofollow}.
 
 If called non-interactively, @var{mode} must be an integer.  Only the
 lowest 12 bits of the integer are used; on most systems, only the
@@ -1811,7 +1826,7 @@ lowest 9 bits are meaningful.  You can use the Lisp 
construct for
 octal numbers to enter @var{mode}.  For example,
 
 @example
-(set-file-modes #o644)
+(set-file-modes "myfile" #o644 'nofollow)
 @end example
 
 @noindent
diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi
index a034ccd..cf4ef52 100644
--- a/doc/lispref/os.texi
+++ b/doc/lispref/os.texi
@@ -3127,7 +3127,7 @@ being reported.  For example:
 @end group
 
 @group
-(set-file-modes "/tmp/foo" (default-file-modes))
+(set-file-modes "/tmp/foo" (default-file-modes) 'nofollow)
      @result{} Event (35025468 attribute-changed "/tmp/foo")
 @end group
 @end example
diff --git a/doc/lispref/searching.texi b/doc/lispref/searching.texi
index 1f6db06..a4d5a27 100644
--- a/doc/lispref/searching.texi
+++ b/doc/lispref/searching.texi
@@ -582,8 +582,13 @@ an unquoted @samp{[} is special again and a @samp{]} not.
 @cindex alpha character class, regexp
 @cindex xdigit character class, regexp
 
-  Here is a table of the classes you can use in a character alternative,
-and what they mean:
+  Below is a table of the classes you can use in a character
+alternative, and what they mean.  Note that the @samp{[} and @samp{]}
+characters that enclose the class name are part of the name, so a
+regular expression using these classes needs one more pair of
+brackets.  For example, a regular expression matching a sequence of
+one or more letters and digits would be @samp{[[:alnum:]]+}, not
+@samp{[:alnum:]+}.
 
 @table @samp
 @item [:ascii:]
diff --git a/etc/NEWS b/etc/NEWS
index 0279879..ee3a3c1 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -125,6 +125,18 @@ To revert to the previous behaviour,
 unconditionally aborts the current edebug instrumentation with the
 supplied error message.
 
++++
+** ElDoc
+
+*** New hook 'eldoc-documentation-functions' to be used for registering
+doc string functions.  This makes the results of all doc string
+functions accessible to the user through the existing single function hook
+'eldoc-documentation-function'.
+
+*** 'eldoc-documentation-function' is now a custom variable.
+Modes should use the new hook instead of this variable to register
+their backends.
+
 ** Tramp
 
 +++
@@ -163,6 +175,13 @@ key             binding
 * New Modes and Packages in Emacs 28.1
 
 
+* Incompatible Editing Changes in Emacs 28.1
+
+** In nroff mode, 'center-line' is now bound to 'M-o M-s'.
+The original key binding was 'M-s', which interfered with I-search,
+since the latter uses 'M-s' as a prefix key of the search prefix map.
+
+
 * Incompatible Lisp Changes in Emacs 28.1
 
 ** 'equal' no longer examines some contents of window configurations.
@@ -198,6 +217,9 @@ called when the function object is garbage-collected.  Use
 'set_function_finalizer' to set the finalizer and
 'get_function_finalizer' to retrieve it.
 
+** 'file-modes' and 'set-file-modes' now have an optional argument
+specifying whether to follow symbolic links.
+
 ** 'parse-time-string' can now parse ISO 8601 format strings,
 such as "2020-01-15T16:12:21-08:00".
 
diff --git a/etc/NEWS.27 b/etc/NEWS.27
index 380ac71..e9dfd26 100644
--- a/etc/NEWS.27
+++ b/etc/NEWS.27
@@ -3352,6 +3352,14 @@ backslash, although there is no harm in doing so to make 
the code
 easier to edit with an older Emacs version.
 
 ---
+** New symbolic accessor functions for a parse state list.
+The new accessor functions 'ppss-depth', 'ppss-list-start',
+'ppss-last-sexp-start', 'ppss-string-terminator', 'comment-depth',
+'quoted-p', 'comment-style', 'comment-or-string-start', 'open-parens',
+and 'two-character-syntax' can be used on the list value returned by
+'parse-partial-sexp' and 'syntax-ppss'.
+
+---
 ** The 'server-name' and 'server-socket-dir' variables are set when a
 socket has been passed to Emacs.
 
diff --git a/lib/careadlinkat.h b/lib/careadlinkat.h
index 584cfe9..a4a37b2 100644
--- a/lib/careadlinkat.h
+++ b/lib/careadlinkat.h
@@ -47,7 +47,7 @@ struct allocator;
    set errno.  */
 
 char *careadlinkat (int fd, char const *filename,
-                    char *buffer, size_t buffer_size,
+                    char *restrict buffer, size_t buffer_size,
                     struct allocator const *alloc,
                     ssize_t (*preadlinkat) (int, char const *,
                                             char *, size_t));
diff --git a/lib/fchmodat.c b/lib/fchmodat.c
new file mode 100644
index 0000000..8950168
--- /dev/null
+++ b/lib/fchmodat.c
@@ -0,0 +1,144 @@
+/* Change the protections of file relative to an open directory.
+   Copyright (C) 2006, 2009-2020 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/>.  */
+
+/* written by Jim Meyering and Paul Eggert */
+
+/* If the user's config.h happens to include <sys/stat.h>, let it include only
+   the system's <sys/stat.h> here, so that orig_fchmodat doesn't recurse to
+   rpl_fchmodat.  */
+#define __need_system_sys_stat_h
+#include <config.h>
+
+/* Specification.  */
+#include <sys/stat.h>
+#undef __need_system_sys_stat_h
+
+#if HAVE_FCHMODAT
+static int
+orig_fchmodat (int dir, char const *file, mode_t mode, int flags)
+{
+  return fchmodat (dir, file, mode, flags);
+}
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#ifdef __osf__
+/* Write "sys/stat.h" here, not <sys/stat.h>, otherwise OSF/1 5.1 DTK cc
+   eliminates this include because of the preliminary #include <sys/stat.h>
+   above.  */
+# include "sys/stat.h"
+#else
+# include <sys/stat.h>
+#endif
+
+#include <intprops.h>
+
+/* Invoke chmod or lchmod on FILE, using mode MODE, in the directory
+   open on descriptor FD.  If possible, do it without changing the
+   working directory.  Otherwise, resort to using save_cwd/fchdir,
+   then (chmod|lchmod)/restore_cwd.  If either the save_cwd or the
+   restore_cwd fails, then give a diagnostic and exit nonzero.
+   Note that an attempt to use a FLAG value of AT_SYMLINK_NOFOLLOW
+   on a system without lchmod support causes this function to fail.  */
+
+#if HAVE_FCHMODAT
+int
+fchmodat (int dir, char const *file, mode_t mode, int flags)
+{
+# if NEED_FCHMODAT_NONSYMLINK_FIX
+  if (flags == AT_SYMLINK_NOFOLLOW)
+    {
+      struct stat st;
+
+#  if defined O_PATH && defined AT_EMPTY_PATH
+      /* Open a file descriptor with O_NOFOLLOW, to make sure we don't
+         follow symbolic links, if /proc is mounted.  O_PATH is used to
+         avoid a failure if the file is not readable.
+         Cf. <https://sourceware.org/bugzilla/show_bug.cgi?id=14578>  */
+      int fd = openat (dir, file, O_PATH | O_NOFOLLOW | O_CLOEXEC);
+      if (fd < 0)
+        return fd;
+
+      /* Up to Linux 5.3 at least, when FILE refers to a symbolic link, the
+         chmod call below will change the permissions of the symbolic link
+         - which is undesired - and on many file systems (ext4, btrfs, jfs,
+         xfs, ..., but not reiserfs) fail with error EOPNOTSUPP - which is
+         misleading.  Therefore test for a symbolic link explicitly.
+         Use fstatat because fstat does not work on O_PATH descriptors
+         before Linux 3.6.  */
+      if (fstatat (fd, "", &st, AT_EMPTY_PATH) != 0)
+        {
+          int stat_errno = errno;
+          close (fd);
+          errno = stat_errno;
+          return -1;
+        }
+      if (S_ISLNK (st.st_mode))
+        {
+          close (fd);
+          errno = EOPNOTSUPP;
+          return -1;
+        }
+
+#   if defined __linux__ || defined __ANDROID__
+      static char const fmt[] = "/proc/self/fd/%d";
+      char buf[sizeof fmt - sizeof "%d" + INT_BUFSIZE_BOUND (int)];
+      sprintf (buf, fmt, fd);
+      int chmod_result = chmod (buf, mode);
+      int chmod_errno = errno;
+      close (fd);
+      if (chmod_result == 0)
+        return chmod_result;
+      if (chmod_errno != ENOENT)
+        {
+          errno = chmod_errno;
+          return chmod_result;
+        }
+#   endif
+      /* /proc is not mounted or would not work as in GNU/Linux.  */
+
+#  else
+      int fstatat_result = fstatat (dir, file, &st, AT_SYMLINK_NOFOLLOW);
+      if (fstatat_result != 0)
+        return fstatat_result;
+      if (S_ISLNK (st.st_mode))
+        {
+          errno = EOPNOTSUPP;
+          return -1;
+        }
+#  endif
+
+      /* Fall back on orig_fchmodat with no flags, despite a possible race.  */
+      flags = 0;
+    }
+# endif
+
+  return orig_fchmodat (dir, file, mode, flags);
+}
+#else
+# define AT_FUNC_NAME fchmodat
+# define AT_FUNC_F1 lchmod
+# define AT_FUNC_F2 chmod
+# define AT_FUNC_USE_F1_COND AT_SYMLINK_NOFOLLOW
+# define AT_FUNC_POST_FILE_PARAM_DECLS , mode_t mode, int flag
+# define AT_FUNC_POST_FILE_ARGS        , mode
+# include "at-func.c"
+#endif
diff --git a/lib/fcntl.in.h b/lib/fcntl.in.h
index b2e1e51..0a21c95 100644
--- a/lib/fcntl.in.h
+++ b/lib/fcntl.in.h
@@ -116,9 +116,15 @@ _GL_WARN_ON_USE (creat, "creat is not always POSIX 
compliant - "
 #  endif
 _GL_FUNCDECL_RPL (fcntl, int, (int fd, int action, ...));
 _GL_CXXALIAS_RPL (fcntl, int, (int fd, int action, ...));
+#  if !GNULIB_defined_rpl_fcntl
+#   define GNULIB_defined_rpl_fcntl 1
+#  endif
 # else
 #  if !@HAVE_FCNTL@
 _GL_FUNCDECL_SYS (fcntl, int, (int fd, int action, ...));
+#   if !GNULIB_defined_fcntl
+#    define GNULIB_defined_fcntl 1
+#   endif
 #  endif
 _GL_CXXALIAS_SYS (fcntl, int, (int fd, int action, ...));
 # endif
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in
index 3c01e61..d4dc6a3 100644
--- a/lib/gnulib.mk.in
+++ b/lib/gnulib.mk.in
@@ -95,6 +95,7 @@
 #  execinfo \
 #  explicit_bzero \
 #  faccessat \
+#  fchmodat \
 #  fcntl \
 #  fcntl-h \
 #  fdopendir \
@@ -1082,6 +1083,7 @@ gl_GNULIB_ENABLED_dirfd = @gl_GNULIB_ENABLED_dirfd@
 gl_GNULIB_ENABLED_euidaccess = @gl_GNULIB_ENABLED_euidaccess@
 gl_GNULIB_ENABLED_getdtablesize = @gl_GNULIB_ENABLED_getdtablesize@
 gl_GNULIB_ENABLED_getgroups = @gl_GNULIB_ENABLED_getgroups@
+gl_GNULIB_ENABLED_lchmod = @gl_GNULIB_ENABLED_lchmod@
 gl_GNULIB_ENABLED_malloca = @gl_GNULIB_ENABLED_malloca@
 gl_GNULIB_ENABLED_open = @gl_GNULIB_ENABLED_open@
 gl_GNULIB_ENABLED_strtoll = @gl_GNULIB_ENABLED_strtoll@
@@ -1586,6 +1588,17 @@ EXTRA_libgnu_a_SOURCES += at-func.c faccessat.c
 endif
 ## end   gnulib module faccessat
 
+## begin gnulib module fchmodat
+ifeq (,$(OMIT_GNULIB_MODULE_fchmodat))
+
+
+EXTRA_DIST += at-func.c fchmodat.c
+
+EXTRA_libgnu_a_SOURCES += at-func.c fchmodat.c
+
+endif
+## end   gnulib module fchmodat
+
 ## begin gnulib module fcntl
 ifeq (,$(OMIT_GNULIB_MODULE_fcntl))
 
@@ -1936,6 +1949,19 @@ EXTRA_DIST += inttypes.in.h
 endif
 ## end   gnulib module inttypes-incomplete
 
+## begin gnulib module lchmod
+ifeq (,$(OMIT_GNULIB_MODULE_lchmod))
+
+ifneq (,$(gl_GNULIB_ENABLED_lchmod))
+
+endif
+EXTRA_DIST += lchmod.c
+
+EXTRA_libgnu_a_SOURCES += lchmod.c
+
+endif
+## end   gnulib module lchmod
+
 ## begin gnulib module libc-config
 ifeq (,$(OMIT_GNULIB_MODULE_libc-config))
 
diff --git a/lib/lchmod.c b/lib/lchmod.c
new file mode 100644
index 0000000..e113211
--- /dev/null
+++ b/lib/lchmod.c
@@ -0,0 +1,110 @@
+/* Implement lchmod on platforms where it does not work correctly.
+
+   Copyright 2020 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/>.  */
+
+/* written by Paul Eggert */
+
+#include <config.h>
+
+/* Specification.  */
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#ifdef __osf__
+/* Write "sys/stat.h" here, not <sys/stat.h>, otherwise OSF/1 5.1 DTK cc
+   eliminates this include because of the preliminary #include <sys/stat.h>
+   above.  */
+# include "sys/stat.h"
+#else
+# include <sys/stat.h>
+#endif
+
+#include <intprops.h>
+
+/* Work like chmod, except when FILE is a symbolic link.
+   In that case, on systems where permissions on symbolic links are unsupported
+   (such as Linux), set errno to EOPNOTSUPP and return -1.  */
+
+int
+lchmod (char const *file, mode_t mode)
+{
+#if defined O_PATH && defined AT_EMPTY_PATH
+  /* Open a file descriptor with O_NOFOLLOW, to make sure we don't
+     follow symbolic links, if /proc is mounted.  O_PATH is used to
+     avoid a failure if the file is not readable.
+     Cf. <https://sourceware.org/bugzilla/show_bug.cgi?id=14578>  */
+  int fd = open (file, O_PATH | O_NOFOLLOW | O_CLOEXEC);
+  if (fd < 0)
+    return fd;
+
+  /* Up to Linux 5.3 at least, when FILE refers to a symbolic link, the
+     chmod call below will change the permissions of the symbolic link
+     - which is undesired - and on many file systems (ext4, btrfs, jfs,
+     xfs, ..., but not reiserfs) fail with error EOPNOTSUPP - which is
+     misleading.  Therefore test for a symbolic link explicitly.
+     Use fstatat because fstat does not work on O_PATH descriptors
+     before Linux 3.6.  */
+  struct stat st;
+  if (fstatat (fd, "", &st, AT_EMPTY_PATH) != 0)
+    {
+      int stat_errno = errno;
+      close (fd);
+      errno = stat_errno;
+      return -1;
+    }
+  if (S_ISLNK (st.st_mode))
+    {
+      close (fd);
+      errno = EOPNOTSUPP;
+      return -1;
+    }
+
+# if defined __linux__ || defined __ANDROID__
+  static char const fmt[] = "/proc/self/fd/%d";
+  char buf[sizeof fmt - sizeof "%d" + INT_BUFSIZE_BOUND (int)];
+  sprintf (buf, fmt, fd);
+  int chmod_result = chmod (buf, mode);
+  int chmod_errno = errno;
+  close (fd);
+  if (chmod_result == 0)
+    return chmod_result;
+  if (chmod_errno != ENOENT)
+    {
+      errno = chmod_errno;
+      return chmod_result;
+    }
+# endif
+  /* /proc is not mounted or would not work as in GNU/Linux.  */
+
+#elif HAVE_LSTAT
+  struct stat st;
+  int lstat_result = lstat (file, &st);
+  if (lstat_result != 0)
+    return lstat_result;
+  if (S_ISLNK (st.st_mode))
+    {
+      errno = EOPNOTSUPP;
+      return -1;
+    }
+#endif
+
+  /* Fall back on chmod, despite a possible race.  */
+  return chmod (file, mode);
+}
diff --git a/lib/md5.h b/lib/md5.h
index 239748a..3c60482 100644
--- a/lib/md5.h
+++ b/lib/md5.h
@@ -105,13 +105,15 @@ extern void __md5_process_bytes (const void *buffer, 
size_t len,
    in first 16 bytes following RESBUF.  The result is always in little
    endian byte order, so that a byte-wise output yields to the wanted
    ASCII representation of the message digest.  */
-extern void *__md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) __THROW;
+extern void *__md5_finish_ctx (struct md5_ctx *ctx, void *restrict resbuf)
+     __THROW;
 
 
 /* Put result from CTX in first 16 bytes following RESBUF.  The result is
    always in little endian byte order, so that a byte-wise output yields
    to the wanted ASCII representation of the message digest.  */
-extern void *__md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) __THROW;
+extern void *__md5_read_ctx (const struct md5_ctx *ctx, void *restrict resbuf)
+     __THROW;
 
 
 /* Compute MD5 message digest for LEN bytes beginning at BUFFER.  The
@@ -119,7 +121,7 @@ extern void *__md5_read_ctx (const struct md5_ctx *ctx, 
void *resbuf) __THROW;
    output yields to the wanted ASCII representation of the message
    digest.  */
 extern void *__md5_buffer (const char *buffer, size_t len,
-                           void *resblock) __THROW;
+                           void *restrict resblock) __THROW;
 
 # endif
 /* Compute MD5 message digest for bytes read from STREAM.
diff --git a/lib/sha1.h b/lib/sha1.h
index 2c9c2d4..b767884 100644
--- a/lib/sha1.h
+++ b/lib/sha1.h
@@ -71,20 +71,21 @@ extern void sha1_process_bytes (const void *buffer, size_t 
len,
    in first 20 bytes following RESBUF.  The result is always in little
    endian byte order, so that a byte-wise output yields to the wanted
    ASCII representation of the message digest.  */
-extern void *sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf);
+extern void *sha1_finish_ctx (struct sha1_ctx *ctx, void *restrict resbuf);
 
 
 /* Put result from CTX in first 20 bytes following RESBUF.  The result is
    always in little endian byte order, so that a byte-wise output yields
    to the wanted ASCII representation of the message digest.  */
-extern void *sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf);
+extern void *sha1_read_ctx (const struct sha1_ctx *ctx, void *restrict resbuf);
 
 
 /* Compute SHA1 message digest for LEN bytes beginning at BUFFER.  The
    result is always in little endian byte order, so that a byte-wise
    output yields to the wanted ASCII representation of the message
    digest.  */
-extern void *sha1_buffer (const char *buffer, size_t len, void *resblock);
+extern void *sha1_buffer (const char *buffer, size_t len,
+                          void *restrict resblock);
 
 # endif
 /* Compute SHA1 message digest for bytes read from STREAM.
diff --git a/lib/sha256.h b/lib/sha256.h
index 1bc61d4..750d78a 100644
--- a/lib/sha256.h
+++ b/lib/sha256.h
@@ -70,23 +70,27 @@ extern void sha256_process_bytes (const void *buffer, 
size_t len,
    in first 32 (28) bytes following RESBUF.  The result is always in little
    endian byte order, so that a byte-wise output yields to the wanted
    ASCII representation of the message digest.  */
-extern void *sha256_finish_ctx (struct sha256_ctx *ctx, void *resbuf);
-extern void *sha224_finish_ctx (struct sha256_ctx *ctx, void *resbuf);
+extern void *sha256_finish_ctx (struct sha256_ctx *ctx, void *restrict resbuf);
+extern void *sha224_finish_ctx (struct sha256_ctx *ctx, void *restrict resbuf);
 
 
 /* Put result from CTX in first 32 (28) bytes following RESBUF.  The result is
    always in little endian byte order, so that a byte-wise output yields
    to the wanted ASCII representation of the message digest.  */
-extern void *sha256_read_ctx (const struct sha256_ctx *ctx, void *resbuf);
-extern void *sha224_read_ctx (const struct sha256_ctx *ctx, void *resbuf);
+extern void *sha256_read_ctx (const struct sha256_ctx *ctx,
+                              void *restrict resbuf);
+extern void *sha224_read_ctx (const struct sha256_ctx *ctx,
+                              void *restrict resbuf);
 
 
-/* Compute SHA256 (SHA224) message digest for LEN bytes beginning at BUFFER.  
The
-   result is always in little endian byte order, so that a byte-wise
+/* Compute SHA256 (SHA224) message digest for LEN bytes beginning at BUFFER.
+   The result is always in little endian byte order, so that a byte-wise
    output yields to the wanted ASCII representation of the message
    digest.  */
-extern void *sha256_buffer (const char *buffer, size_t len, void *resblock);
-extern void *sha224_buffer (const char *buffer, size_t len, void *resblock);
+extern void *sha256_buffer (const char *buffer, size_t len,
+                            void *restrict resblock);
+extern void *sha224_buffer (const char *buffer, size_t len,
+                            void *restrict resblock);
 
 # endif
 /* Compute SHA256 (SHA224) message digest for bytes read from STREAM.
diff --git a/lib/sha512.h b/lib/sha512.h
index aaf35a5..21c2f58 100644
--- a/lib/sha512.h
+++ b/lib/sha512.h
@@ -70,8 +70,8 @@ extern void sha512_process_bytes (const void *buffer, size_t 
len,
    in first 64 (48) bytes following RESBUF.  The result is always in little
    endian byte order, so that a byte-wise output yields to the wanted
    ASCII representation of the message digest.  */
-extern void *sha512_finish_ctx (struct sha512_ctx *ctx, void *resbuf);
-extern void *sha384_finish_ctx (struct sha512_ctx *ctx, void *resbuf);
+extern void *sha512_finish_ctx (struct sha512_ctx *ctx, void *restrict resbuf);
+extern void *sha384_finish_ctx (struct sha512_ctx *ctx, void *restrict resbuf);
 
 
 /* Put result from CTX in first 64 (48) bytes following RESBUF.  The result is
@@ -80,16 +80,20 @@ extern void *sha384_finish_ctx (struct sha512_ctx *ctx, 
void *resbuf);
 
    IMPORTANT: On some systems it is required that RESBUF is correctly
    aligned for a 32 bits value.  */
-extern void *sha512_read_ctx (const struct sha512_ctx *ctx, void *resbuf);
-extern void *sha384_read_ctx (const struct sha512_ctx *ctx, void *resbuf);
+extern void *sha512_read_ctx (const struct sha512_ctx *ctx,
+                              void *restrict resbuf);
+extern void *sha384_read_ctx (const struct sha512_ctx *ctx,
+                              void *restrict resbuf);
 
 
-/* Compute SHA512 (SHA384) message digest for LEN bytes beginning at BUFFER.  
The
-   result is always in little endian byte order, so that a byte-wise
+/* Compute SHA512 (SHA384) message digest for LEN bytes beginning at BUFFER.
+   The result is always in little endian byte order, so that a byte-wise
    output yields to the wanted ASCII representation of the message
    digest.  */
-extern void *sha512_buffer (const char *buffer, size_t len, void *resblock);
-extern void *sha384_buffer (const char *buffer, size_t len, void *resblock);
+extern void *sha512_buffer (const char *buffer, size_t len,
+                            void *restrict resblock);
+extern void *sha384_buffer (const char *buffer, size_t len,
+                            void *restrict resblock);
 
 # endif
 /* Compute SHA512 (SHA384) message digest for bytes read from STREAM.
diff --git a/lib/strftime.h b/lib/strftime.h
index 97a062c..e850163 100644
--- a/lib/strftime.h
+++ b/lib/strftime.h
@@ -25,7 +25,7 @@ extern "C" {
    POSIX requires that strftime use the local timezone information.
    Use the timezone __TZ instead.  Use __NS as the number of
    nanoseconds in the %N directive.  */
-size_t nstrftime (char *, size_t, char const *, struct tm const *,
+size_t nstrftime (char *restrict, size_t, char const *, struct tm const *,
                   timezone_t __tz, int __ns);
 
 #ifdef __cplusplus
diff --git a/lib/string.in.h b/lib/string.in.h
index 5bc0084..596c99b 100644
--- a/lib/string.in.h
+++ b/lib/string.in.h
@@ -969,7 +969,8 @@ _GL_EXTERN_C char * mbssep (char **stringp, const char 
*delim)
    Caveat: The identity of the delimiting character is lost.
 
    See also mbssep().  */
-_GL_EXTERN_C char * mbstok_r (char *string, const char *delim, char **save_ptr)
+_GL_EXTERN_C char * mbstok_r (char *restrict string, const char *delim,
+                              char **save_ptr)
      _GL_ARG_NONNULL ((2, 3));
 #endif
 
diff --git a/lisp/comint.el b/lisp/comint.el
index 5c521ff..ea06f8a 100644
--- a/lisp/comint.el
+++ b/lisp/comint.el
@@ -3641,7 +3641,7 @@ and does not normally need to be invoked by the end user 
or programmer."
     (setq-local comint-redirect-previous-input-string "")
 
     (setq mode-line-process
-         (if mode-line-process
+         (if (and mode-line-process (stringp (elt mode-line-process 0)))
              (list (concat (elt mode-line-process 0) " Redirection"))
            (list ":%s Redirection")))))
 
diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el
index 0069c17..8f00317 100644
--- a/lisp/dired-aux.el
+++ b/lisp/dired-aux.el
@@ -409,7 +409,8 @@ has no effect on MS-Windows."
       (set-file-modes
        file
        (if num-modes num-modes
-        (file-modes-symbolic-to-number modes (file-modes file)))))
+        (file-modes-symbolic-to-number modes (file-modes file 'nofollow)))
+       'nofollow))
     (dired-do-redisplay arg)))
 
 ;;;###autoload
diff --git a/lisp/doc-view.el b/lisp/doc-view.el
index 3788d79..8b3d552 100644
--- a/lisp/doc-view.el
+++ b/lisp/doc-view.el
@@ -683,8 +683,6 @@ at the top edge of the page moves to the previous page."
       ;; time-window of loose permissions otherwise.
       (with-file-modes #o0700 (make-directory dir))
     (file-already-exists
-     (when (file-symlink-p dir)
-       (error "Danger: %s points to a symbolic link" dir))
      ;; In case it was created earlier with looser rights.
      ;; We could check the mode info returned by file-attributes, but it's
      ;; a pain to parse and it may not tell you what we want under
@@ -694,7 +692,7 @@ at the top edge of the page moves to the previous page."
      ;; sure we have write-access to the directory and that we own it, thus
      ;; closing a bunch of security holes.
      (condition-case error
-        (set-file-modes dir #o0700)
+        (set-file-modes dir #o0700 'nofollow)
        (file-error
        (error
         (format "Unable to use temporary directory %s: %s"
diff --git a/lisp/emacs-lisp/autoload.el b/lisp/emacs-lisp/autoload.el
index 53d3538..6180bee 100644
--- a/lisp/emacs-lisp/autoload.el
+++ b/lisp/emacs-lisp/autoload.el
@@ -895,7 +895,7 @@ FILE's modification time."
           (cons (lambda () (ignore-errors (delete-file tempfile)))
                 kill-emacs-hook)))
     (unless (= temp-modes desired-modes)
-      (set-file-modes tempfile desired-modes))
+      (set-file-modes tempfile desired-modes 'nofollow))
     (write-region (point-min) (point-max) tempfile nil 1)
     (backup-buffer)
     (rename-file tempfile buffer-file-name t))
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index fe0930c..4f72251 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -1515,7 +1515,7 @@
      byte-eqlsign byte-gtr byte-lss byte-leq byte-geq byte-diff byte-negate
      byte-plus byte-max byte-min byte-mult byte-char-after byte-char-syntax
      byte-buffer-substring byte-string= byte-string< byte-nthcdr byte-elt
-     byte-member byte-assq byte-quo byte-rem)
+     byte-member byte-assq byte-quo byte-rem byte-substring)
    byte-compile-side-effect-and-error-free-ops))
 
 ;; This crock is because of the way DEFVAR_BOOL variables work.
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index b3bd687..72c6fc7 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -2031,7 +2031,7 @@ The value is non-nil if there were no errors, nil if 
errors."
                                           (delete-file tempfile)))
                              kill-emacs-hook)))
                  (unless (= temp-modes desired-modes)
-                   (set-file-modes tempfile desired-modes))
+                   (set-file-modes tempfile desired-modes 'nofollow))
                  (write-region (point-min) (point-max) tempfile nil 1)
                  ;; This has the intentional side effect that any
                  ;; hard-links to target-file continue to
@@ -3535,7 +3535,7 @@ the opcode to be used.  If function is a list, the first 
element
 is the function and the second element is the bytecode-symbol.
 The second element may be nil, meaning there is no opcode.
 COMPILE-HANDLER is the function to use to compile this byte-op, or
-may be the abbreviations 0, 1, 2, 3, 0-1, or 1-2.
+may be the abbreviations 0, 1, 2, 2-and, 3, 0-1, 1-2, 1-3, or 2-3.
 If it is nil, then the handler is \"byte-compile-SYMBOL.\""
   (let (opcode)
     (if (symbolp function)
@@ -3554,6 +3554,7 @@ If it is nil, then the handler is 
\"byte-compile-SYMBOL.\""
                                        (0-1 . byte-compile-zero-or-one-arg)
                                        (1-2 . byte-compile-one-or-two-args)
                                        (2-3 . byte-compile-two-or-three-args)
+                                       (1-3 . byte-compile-one-to-three-args)
                                        )))
                           compile-handler
                           (intern (concat "byte-compile-"
@@ -3738,6 +3739,13 @@ These implicitly `and' together a bunch of two-arg 
bytecodes."
          ((= len 4) (byte-compile-three-args form))
          (t (byte-compile-subr-wrong-args form "2-3")))))
 
+(defun byte-compile-one-to-three-args (form)
+  (let ((len (length form)))
+    (cond ((= len 2) (byte-compile-three-args (append form '(nil nil))))
+          ((= len 3) (byte-compile-three-args (append form '(nil))))
+          ((= len 4) (byte-compile-three-args form))
+          (t (byte-compile-subr-wrong-args form "1-3")))))
+
 (defun byte-compile-noop (_form)
   (byte-compile-constant nil))
 
diff --git a/lisp/emacs-lisp/cursor-sensor.el b/lisp/emacs-lisp/cursor-sensor.el
index d8e8eeb..7728e78 100644
--- a/lisp/emacs-lisp/cursor-sensor.el
+++ b/lisp/emacs-lisp/cursor-sensor.el
@@ -146,9 +146,10 @@ By convention, this is a list of symbols where each symbol 
stands for the
            ;; It's often desirable to make the cursor-sensor-functions property
            ;; non-sticky on both ends, but that means get-pos-property might
            ;; never see it.
-           (new (or (get-char-property point 'cursor-sensor-functions)
-                    (unless (<= (point-min) point)
-                      (get-char-property (1- point) 
'cursor-sensor-functions))))
+           (new (and (eq (current-buffer) (window-buffer))
+                     (or (get-char-property point 'cursor-sensor-functions)
+                         (unless (<= (point-min) point)
+                           (get-char-property (1- point) 
'cursor-sensor-functions)))))
            (old (window-parameter window 'cursor-sensor--last-state))
            (oldposmark (car old))
            (oldpos (or (if oldposmark (marker-position oldposmark))
diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el
index 7a7b8ec..456a650 100644
--- a/lisp/emacs-lisp/eldoc.el
+++ b/lisp/emacs-lisp/eldoc.el
@@ -40,9 +40,9 @@
 ;;      (add-hook 'ielm-mode-hook 'eldoc-mode)
 ;;      (add-hook 'eval-expression-minibuffer-setup-hook 'eldoc-mode)
 
-;; Major modes for other languages may use ElDoc by defining an
-;; appropriate function as the buffer-local value of
-;; `eldoc-documentation-function'.
+;; Major modes for other languages may use ElDoc by adding an
+;; appropriate function to the buffer-local value of
+;; `eldoc-documentation-functions'.
 
 ;;; Code:
 
@@ -222,8 +222,8 @@ expression point is on."
 (defun eldoc--eval-expression-setup ()
   ;; Setup `eldoc', similar to `emacs-lisp-mode'.  FIXME: Call
   ;; `emacs-lisp-mode' itself?
-  (add-function :before-until (local 'eldoc-documentation-function)
-                #'elisp-eldoc-documentation-function)
+  (add-hook 'eldoc-documentation-functions
+            #'elisp-eldoc-documentation-function nil t)
   (eldoc-mode +1))
 
 ;;;###autoload
@@ -235,7 +235,11 @@ See `eldoc-documentation-function' for more detail."
 
 (defun eldoc--supported-p ()
   "Non-nil if an ElDoc function is set for this buffer."
-  (not (memq eldoc-documentation-function '(nil ignore))))
+  (let ((hook 'eldoc-documentation-functions))
+    (and (not (memq eldoc-documentation-function '(nil ignore)))
+         (or (and (local-variable-p hook)
+                  (buffer-local-value hook (current-buffer)))
+             (default-value hook)))))
 
 
 (defun eldoc-schedule-timer ()
@@ -347,8 +351,46 @@ Also store it in `eldoc-last-message' and return that 
value."
   (not (or executing-kbd-macro (bound-and-true-p edebug-active))))
 
 
-;;;###autoload
-(defvar eldoc-documentation-function #'ignore
+(defvar eldoc-documentation-functions nil
+  "Hook for functions to call to return doc string.
+Each function should accept no arguments and return a one-line
+string for displaying doc about a function etc. appropriate to
+the context around point.  It should return nil if there's no doc
+appropriate for the context.  Typically doc is returned if point
+is on a function-like name or in its arg list.
+
+Major modes should modify this hook locally, for example:
+  (add-hook \\='eldoc-documentation-functions #\\='foo-mode-eldoc nil t)
+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.")
+
+(defun eldoc-documentation-default ()
+  "Show first doc string for item at point.
+Default value for `eldoc-documentation-function'."
+  (let ((res (run-hook-with-args-until-success 
'eldoc-documentation-functions)))
+    (when res
+      (if eldoc-echo-area-use-multiline-p res
+        (truncate-string-to-width
+         res (1- (window-width (minibuffer-window))))))))
+
+(defun eldoc-documentation-compose ()
+  "Show multiple doc string results at once.
+Meant as a value for `eldoc-documentation-function'."
+  (let (res)
+    (run-hook-wrapped
+     'eldoc-documentation-functions
+     (lambda (f)
+       (let ((str (funcall f)))
+         (when str (push str res))
+         nil)))
+    (when res
+      (setq res (mapconcat #'identity (nreverse res) ", "))
+      (if eldoc-echo-area-use-multiline-p res
+        (truncate-string-to-width
+         res (1- (window-width (minibuffer-window))))))))
+
+(defcustom eldoc-documentation-function #'eldoc-documentation-default
   "Function to call to return doc string.
 The function of no args should return a one-line string for displaying
 doc about a function etc. appropriate to the context around point.
@@ -359,14 +401,14 @@ arg list.
 The result is used as is, so the function must explicitly handle
 the variables `eldoc-argument-case' and `eldoc-echo-area-use-multiline-p',
 and the face `eldoc-highlight-function-argument', if they are to have any
-effect.
-
-Major modes should modify this variable using `add-function', for example:
-  (add-function :before-until (local \\='eldoc-documentation-function)
-                #\\='foo-mode-eldoc-function)
-so that the global documentation function (i.e. the default value of the
-variable) is taken into account if the major mode specific function does not
-return any documentation.")
+effect."
+  :link '(info-link "(emacs) Lisp Doc")
+  :type '(radio (function-item eldoc-documentation-default)
+                (function-item eldoc-documentation-compose)
+                (function :tag "Other function")
+                (const :tag "None" nil))
+  :version "28.1"
+  :group 'eldoc)
 
 (defun eldoc-print-current-symbol-info ()
   "Print the text produced by `eldoc-documentation-function'."
@@ -381,7 +423,8 @@ return any documentation.")
         ;; Only keep looking for the info as long as the user hasn't
         ;; requested our attention.  This also locally disables inhibit-quit.
         (while-no-input
-          (eldoc-message (funcall eldoc-documentation-function)))))))
+          (let ((fun eldoc-documentation-function))
+            (when fun (eldoc-message (funcall fun)))))))))
 
 ;; If the entire line cannot fit in the echo area, the symbol name may be
 ;; truncated or eliminated entirely from the output to make room for the
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index c91ee44..43eb038 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -2081,7 +2081,8 @@ to install it but still mark it as selected."
                  (package-compute-transaction () (list (list pkg))))))
         (progn
           (package-download-transaction transaction)
-          (package--quickstart-maybe-refresh))
+          (package--quickstart-maybe-refresh)
+          (message  "Package `%s' installed." name))
       (message "`%s' is already installed" name))))
 
 (defun package-strip-rcs-id (str)
diff --git a/lisp/emacs-lisp/syntax.el b/lisp/emacs-lisp/syntax.el
index 6b464bc..11cc198 100644
--- a/lisp/emacs-lisp/syntax.el
+++ b/lisp/emacs-lisp/syntax.el
@@ -89,33 +89,33 @@ Put first the functions more likely to cause a change and 
cheaper to compute.")
                (:constructor make-ppss)
                (:copier nil)
                (:type list))
-  (depth nil :documentation "depth in parens")
+  (depth nil :documentation "Depth in parens.")
   (innermost-start
    nil :documentation
-   "character address of start of innermost containing list; nil if none.")
+   "Character address of start of innermost containing list; nil if none.")
   (last-complete-sexp-start
    nil :documentation
-   "character address of start of last complete sexp terminated.")
+   "Character address of start of last complete sexp terminated.")
   (string-terminator nil :documentation "\
-non-nil if inside a string.
-(it is the character that will terminate the string, or t if the
+Non-nil if inside a string.
+\(it is the character that will terminate the string, or t if the
 string should be terminated by a generic string delimiter.)")
-  (comment-nesting nil :documentation "\
+  (comment-depth nil :documentation "\
 nil if outside a comment, t if inside a non-nestable comment,
 else an integer (the current comment nesting).")
-  (after-quote-p nil :documentation "t if following a quote character.")
-  (minimum-paren-depth
-   nil :documentation "the minimum paren-depth encountered during this scan.")
-  (comment-style nil :documentation "style of comment, if any.")
+  (quoted-p nil :documentation "t if following a quote character.")
+  (min-depth
+   nil :documentation "The minimum depth in parens encountered during this 
scan.")
+  (comment-style nil :documentation "Style of comment, if any.")
   (comment-or-string-start
    nil :documentation
-   "character address of start of comment or string; nil if not in one.")
-  (open-paren-positions
+   "Character address of start of comment or string; nil if not in one.")
+  (open-parens
    nil :documentation
    "List of positions of currently open parens, outermost first.")
   (two-character-syntax nil :documentation "\
 When the last position scanned holds the first character of a
-(potential) two character construct, the syntax of that position,
+\(potential) two character construct, the syntax of that position,
 otherwise nil.  That construct can be a two character comment
 delimiter or an Escaped or Char-quoted character."))
 
diff --git a/lisp/eshell/em-pred.el b/lisp/eshell/em-pred.el
index 04bf3ff..7219af4 100644
--- a/lisp/eshell/em-pred.el
+++ b/lisp/eshell/em-pred.el
@@ -478,7 +478,7 @@ that `ls -l' will show in the first column of its display."
 (defsubst eshell-pred-file-mode (mode)
   "Return a test which tests that MODE pertains to the file."
   `(lambda (file)
-     (let ((modes (file-modes file)))
+     (let ((modes (file-modes file 'nofollow)))
        (if modes
           (logand ,mode modes)))))
 
diff --git a/lisp/eshell/em-prompt.el b/lisp/eshell/em-prompt.el
index 25b8cca..9ae5ae1 100644
--- a/lisp/eshell/em-prompt.el
+++ b/lisp/eshell/em-prompt.el
@@ -187,7 +187,7 @@ See `eshell-prompt-regexp'."
   "Move to end of Nth previous prompt in the buffer.
 See `eshell-prompt-regexp'."
   (interactive "p")
-  (beginning-of-line)            ; Don't count prompt on current line.
+  (forward-line 0)            ; Don't count prompt on current line.
   (eshell-next-prompt (- n)))
 
 (defun eshell-skip-prompt ()
diff --git a/lisp/files.el b/lisp/files.el
index 683f4a8..2e7694d 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -4672,6 +4672,7 @@ BACKUPNAME is the backup file name, which is the old file 
renamed."
   ;; Create temp files with strict access rights.  It's easy to
   ;; loosen them later, whereas it's impossible to close the
   ;; time-window of loose permissions otherwise.
+ (let (nofollow-flag)
   (with-file-modes ?\700
     (when (condition-case nil
              ;; Try to overwrite old backup first.
@@ -4682,6 +4683,7 @@ BACKUPNAME is the backup file name, which is the old file 
renamed."
                   (when (file-exists-p to-name)
                     (delete-file to-name))
                   (copy-file from-name to-name nil t t)
+                  (setq nofollow-flag 'nofollow)
                   nil)
               (file-already-exists t))
        ;; The file was somehow created by someone else between
@@ -4694,7 +4696,7 @@ BACKUPNAME is the backup file name, which is the old file 
renamed."
               (with-demoted-errors
                 (set-file-extended-attributes to-name extended-attributes)))
     (and modes
-        (set-file-modes to-name (logand modes #o1777)))))
+        (set-file-modes to-name (logand modes #o1777) nofollow-flag)))))
 
 (defvar file-name-version-regexp
   "\\(?:~\\|\\.~[-[:alnum:]:#@^._]+\\(?:~[[:digit:]]+\\)?~\\)"
@@ -5900,7 +5902,8 @@ into NEWNAME instead."
   ;; If default-directory is a remote directory, make sure we find its
   ;; copy-directory handler.
   (let ((handler (or (find-file-name-handler directory 'copy-directory)
-                    (find-file-name-handler newname 'copy-directory))))
+                    (find-file-name-handler newname 'copy-directory)))
+       (follow parents))
     (if handler
        (funcall handler 'copy-directory directory
                  newname keep-time parents copy-contents)
@@ -5920,7 +5923,8 @@ into NEWNAME instead."
                 (or parents (not (file-directory-p newname)))
               (setq newname (concat newname
                                     (file-name-nondirectory directory))))
-            (make-directory (directory-file-name newname) parents)))
+            (make-directory (directory-file-name newname) parents))
+           (t (setq follow t)))
 
       ;; Copy recursively.
       (dolist (file
@@ -5941,7 +5945,7 @@ into NEWNAME instead."
       (let ((modes (file-modes directory))
            (times (and keep-time (file-attribute-modification-time
                                   (file-attributes directory)))))
-       (if modes (set-file-modes newname modes))
+       (if modes (set-file-modes newname modes (unless follow 'nofollow)))
        (if times (set-file-times newname times))))))
 
 
diff --git a/lisp/gnus/gnus-util.el b/lisp/gnus/gnus-util.el
index eb0fd25..83a8516 100644
--- a/lisp/gnus/gnus-util.el
+++ b/lisp/gnus/gnus-util.el
@@ -1601,10 +1601,10 @@ empty directories from OLD-PATH."
                         (file-truename
                          (concat old-dir "..")))))))))
 
-(defun gnus-set-file-modes (filename mode)
+(defun gnus-set-file-modes (filename mode &optional flag)
   "Wrapper for set-file-modes."
   (ignore-errors
-    (set-file-modes filename mode)))
+    (set-file-modes filename mode flag)))
 
 (defun gnus-rescale-image (image size)
   "Rescale IMAGE to SIZE if possible.
diff --git a/lisp/gnus/mail-source.el b/lisp/gnus/mail-source.el
index f5b6878..acf35a3 100644
--- a/lisp/gnus/mail-source.el
+++ b/lisp/gnus/mail-source.el
@@ -695,7 +695,7 @@ Deleting old (> %s day(s)) incoming mail file `%s'." diff 
bfile)
                         mail-source-movemail-program
                         nil errors nil from to)))))
              (when (file-exists-p to)
-               (set-file-modes to mail-source-default-file-modes))
+               (set-file-modes to mail-source-default-file-modes 'nofollow))
              (if (and (or (not (buffer-modified-p errors))
                           (zerop (buffer-size errors)))
                       (and (numberp result)
diff --git a/lisp/gnus/mm-decode.el b/lisp/gnus/mm-decode.el
index 2dab278..96695aa 100644
--- a/lisp/gnus/mm-decode.el
+++ b/lisp/gnus/mm-decode.el
@@ -948,7 +948,7 @@ external if displayed external."
          ;; The file is deleted after the viewer exists.  If the users edits
          ;; the file, changes will be lost.  Set file to read-only to make it
          ;; clear.
-         (set-file-modes file #o400)
+         (set-file-modes file #o400 'nofollow)
          (message "Viewing with %s" method)
          (cond
           (needsterm
diff --git a/lisp/gnus/nnmail.el b/lisp/gnus/nnmail.el
index 6e01b5c..93e4b0e 100644
--- a/lisp/gnus/nnmail.el
+++ b/lisp/gnus/nnmail.el
@@ -1958,7 +1958,7 @@ If TIME is nil, then return the cutoff time for oldness 
instead."
   (let ((coding-system-for-write nnmail-file-coding-system)
        (file-name-coding-system nnmail-pathname-coding-system))
     (write-region start end filename append visit lockname)
-    (set-file-modes filename nnmail-default-file-modes)))
+    (set-file-modes filename nnmail-default-file-modes 'nofollow)))
 
 ;;;
 ;;; Status functions
diff --git a/lisp/hexl.el b/lisp/hexl.el
index 58518e7..cf7118f 100644
--- a/lisp/hexl.el
+++ b/lisp/hexl.el
@@ -367,8 +367,8 @@ You can use \\[hexl-find-file] to visit a file in Hexl mode.
     (add-hook 'change-major-mode-hook #'hexl-maybe-dehexlify-buffer nil t)
 
     ;; Set a callback function for eldoc.
-    (add-function :before-until (local 'eldoc-documentation-function)
-                  #'hexl-print-current-point-info)
+    (add-hook 'eldoc-documentation-functions
+              #'hexl-print-current-point-info nil t)
     (eldoc-add-command-completions "hexl-")
     (eldoc-remove-command "hexl-save-buffer"
                          "hexl-current-address")
@@ -455,6 +455,8 @@ and edit the file in `hexl-mode'."
     ;; 2. reset change-major-mode-hook in case that `hexl-mode'
     ;; previously added hexl-maybe-dehexlify-buffer to it.
     (remove-hook 'change-major-mode-hook #'hexl-maybe-dehexlify-buffer t)
+    (remove-hook 'eldoc-documentation-functions
+                 #'hexl-print-current-point-info t)
     (setq major-mode 'fundamental-mode)
     (hexl-mode)))
 
diff --git a/lisp/ielm.el b/lisp/ielm.el
index 41675c0..fc06ebf 100644
--- a/lisp/ielm.el
+++ b/lisp/ielm.el
@@ -541,8 +541,8 @@ Customized bindings may be defined in `ielm-map', which 
currently contains:
   (set (make-local-variable 'completion-at-point-functions)
        '(comint-replace-by-expanded-history
          ielm-complete-filename elisp-completion-at-point))
-  (add-function :before-until (local 'eldoc-documentation-function)
-                #'elisp-eldoc-documentation-function)
+  (add-hook 'eldoc-documentation-functions
+            #'elisp-eldoc-documentation-function 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/net/ange-ftp.el b/lisp/net/ange-ftp.el
index f283942..e2d4d7d 100644
--- a/lisp/net/ange-ftp.el
+++ b/lisp/net/ange-ftp.el
@@ -4740,7 +4740,8 @@ NEWNAME should be the name to give the new compressed or 
uncompressed file.")
   (setq ange-ftp-ls-cache-file nil)    ;Stop confusing Dired.
   0)
 
-(defun ange-ftp-set-file-modes (filename mode)
+(defun ange-ftp-set-file-modes (filename mode &optional flag)
+  flag ;; FIXME: Support 'nofollow'.
   (ange-ftp-call-chmod (list (format "%o" mode) filename)))
 
 (defun ange-ftp-make-symbolic-link (&rest _arguments)
diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el
index aa7fe14..a118e7d 100644
--- a/lisp/net/tramp-adb.el
+++ b/lisp/net/tramp-adb.el
@@ -591,7 +591,9 @@ Emacs dired can't find files."
          (ignore-errors (delete-file tmpfile))
          (tramp-error
           v 'file-error "Cannot make local copy of file `%s'" filename))
-       (set-file-modes tmpfile (logior (or (file-modes filename) 0) #o0400)))
+       (set-file-modes
+        tmpfile
+        (logior (or (tramp-compat-file-modes filename 'nofollow) 0) #o0400)))
       tmpfile)))
 
 (defun tramp-adb-handle-file-writable-p (filename)
@@ -665,9 +667,11 @@ But handle the case, if the \"test\" command is not 
available."
        (tramp-message v 0 "Wrote %s" filename))
       (run-hooks 'tramp-handle-write-region-hook))))
 
-(defun tramp-adb-handle-set-file-modes (filename mode)
+(defun tramp-adb-handle-set-file-modes (filename mode &optional flag)
   "Like `set-file-modes' for Tramp files."
   (with-parsed-tramp-file-name filename nil
+    (when (and (eq flag 'nofollow) (file-symlink-p filename))
+      (tramp-error v 'file-error "Cannot chmod %s with %s flag" filename flag))
     (tramp-flush-file-properties v localname)
     (tramp-adb-send-command-and-check v (format "chmod %o %s" mode 
localname))))
 
diff --git a/lisp/net/tramp-compat.el b/lisp/net/tramp-compat.el
index 87bcd08..8f85550 100644
--- a/lisp/net/tramp-compat.el
+++ b/lisp/net/tramp-compat.el
@@ -165,7 +165,7 @@ This is a string of ten letters or dashes as in ls -l."
   "The error symbol for the `file-missing' error.")
 
 ;; `file-local-name', `file-name-quoted-p', `file-name-quote' and
-;; `file-name-unquote' are introduced in Emacs 26.
+;; `file-name-unquote' are introduced in Emacs 26.1.
 (defalias 'tramp-compat-file-local-name
   (if (fboundp 'file-local-name)
       #'file-local-name
@@ -175,7 +175,8 @@ It returns a file name which can be used directly as 
argument of
 `process-file', `start-file-process', or `shell-command'."
       (or (file-remote-p name 'localname) name))))
 
-;; `file-name-quoted-p' got a second argument in Emacs 27.1.
+;; `file-name-quoted-p', `file-name-quote' and `file-name-unquote' got
+;; a second argument in Emacs 27.1.
 (defalias 'tramp-compat-file-name-quoted-p
   (if (and
        (fboundp 'file-name-quoted-p)
@@ -217,7 +218,7 @@ NAME is unquoted."
           localname (if (= (length localname) 2) "/" (substring localname 2))))
        (concat (file-remote-p name) localname)))))
 
-;; `tramp-syntax' has changed its meaning in Emacs 26.  We still
+;; `tramp-syntax' has changed its meaning in Emacs 26.1.  We still
 ;; support old settings.
 (defsubst tramp-compat-tramp-syntax ()
   "Return proper value of `tramp-syntax'."
@@ -275,6 +276,19 @@ A nil value for either argument stands for the current 
time."
     (lambda (reporter &optional value _suffix)
       (progress-reporter-update reporter value))))
 
+;; `file-modes' and `set-file-modes' got argument FLAG in Emacs 28.1.
+(defalias 'tramp-compat-file-modes
+  (if (equal (tramp-compat-funcall 'func-arity #'file-modes) '(1 . 2))
+      #'file-modes
+    (lambda (filename &optional _flag)
+      (file-modes filename))))
+
+(defalias 'tramp-compat-set-file-modes
+  (if (equal (tramp-compat-funcall 'func-arity #'set-file-modes) '(2 . 3))
+      #'set-file-modes
+    (lambda (filename mode &optional _flag)
+      (set-file-modes filename mode))))
+
 (add-hook 'tramp-unload-hook
          (lambda ()
            (unload-feature 'tramp-loaddefs 'force)
@@ -284,6 +298,8 @@ A nil value for either argument stands for the current 
time."
 
 ;;; TODO:
 ;;
+;; * `func-arity' exists since Emacs 26.1.
+;;
 ;; * Starting with Emacs 27.1, there's no need to escape open
 ;;   parentheses with a backslash in docstrings anymore.
 
diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el
index 762c4fe..3ce7bbb 100644
--- a/lisp/net/tramp-gvfs.el
+++ b/lisp/net/tramp-gvfs.el
@@ -1562,12 +1562,12 @@ If FILE-SYSTEM is non-nil, return file system 
attributes."
     (tramp-run-real-handler
      #'rename-file (list filename newname ok-if-already-exists))))
 
-(defun tramp-gvfs-handle-set-file-modes (filename mode)
+(defun tramp-gvfs-handle-set-file-modes (filename mode &optional flag)
   "Like `set-file-modes' for Tramp files."
   (with-parsed-tramp-file-name filename nil
     (tramp-flush-file-properties v localname)
     (tramp-gvfs-send-command
-     v "gvfs-set-attribute" "-t" "uint32"
+     v "gvfs-set-attribute" (if (eq flag 'nofollow) "-nt" "-t") "uint32"
      (tramp-gvfs-url-file-name (tramp-make-tramp-file-name v))
      "unix::mode" (number-to-string mode))))
 
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index 5a3abc3..761f594 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -1478,15 +1478,20 @@ of."
             ;; only if that agrees with the buffer's record.
             (t (tramp-compat-time-equal-p mt tramp-time-doesnt-exist)))))))))
 
-(defun tramp-sh-handle-set-file-modes (filename mode)
+(defun tramp-sh-handle-set-file-modes (filename mode &optional flag)
   "Like `set-file-modes' for Tramp files."
   (with-parsed-tramp-file-name filename nil
-    (tramp-flush-file-properties v localname)
-    ;; FIXME: extract the proper text from chmod's stderr.
-    (tramp-barf-unless-okay
-     v
-     (format "chmod %o %s" mode (tramp-shell-quote-argument localname))
-     "Error while changing file's mode %s" filename)))
+    (let ((chmod "chmod"))
+      (when (and (eq flag 'nofollow) (file-symlink-p filename))
+       (or (setq chmod (tramp-get-remote-chmod-h v))
+           (tramp-error
+            v 'file-error "Cannot chmod %s with %s flag" filename flag)))
+      (tramp-flush-file-properties v localname)
+      ;; FIXME: extract the proper text from chmod's stderr.
+      (tramp-barf-unless-okay
+       v
+       (format "%s %o %s" chmod mode (tramp-shell-quote-argument localname))
+       "Error while changing file's mode %s" filename))))
 
 (defun tramp-sh-handle-set-file-times (filename &optional time)
   "Like `set-file-times' for Tramp files."
@@ -3270,7 +3275,8 @@ STDERR can also be a file name."
           #'write-region
           (list start end localname append 'no-message lockname))
 
-       (let* ((modes (save-excursion (tramp-default-file-modes filename)))
+       (let* ((modes (tramp-default-file-modes
+                      filename (and (eq mustbenew 'excl) 'nofollow)))
               ;; We use this to save the value of
               ;; `last-coding-system-used' after writing the tmp
               ;; file.  At the end of the function, we set
@@ -5895,6 +5901,22 @@ ID-FORMAT valid values are `string' and `integer'."
                vec (concat command " -A n </dev/null"))
               command)))))
 
+(defun tramp-get-remote-chmod-h (vec)
+  "Determine remote `chmod' command which supports nofollow argument."
+  (with-tramp-connection-property vec "chmod-h"
+    (tramp-message vec 5 "Finding a suitable `chmod' command with nofollow")
+    (let ((tmpfile
+          (make-temp-name
+           (expand-file-name
+            tramp-temp-name-prefix (tramp-get-remote-tmpdir vec)))))
+      (when (tramp-send-command-and-check
+            vec
+            (format
+             "ln -s foo %s && chmod -h %s 0777"
+             (tramp-file-local-name tmpfile) (tramp-file-local-name tmpfile)))
+       (delete-file tmpfile)
+       "chmod -h"))))
+
 (defun tramp-get-env-with-u-option (vec)
   "Check, whether the remote `env' command supports the -u option."
   (with-tramp-connection-property vec "env-u-option"
diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el
index f02be39..abd369f 100644
--- a/lisp/net/tramp-smb.el
+++ b/lisp/net/tramp-smb.el
@@ -1464,9 +1464,11 @@ component is used as the target of the symlink."
            (tramp-flush-connection-property v "process-name")
            (tramp-flush-connection-property v "process-buffer")))))))
 
-(defun tramp-smb-handle-set-file-modes (filename mode)
+(defun tramp-smb-handle-set-file-modes (filename mode &optional flag)
   "Like `set-file-modes' for Tramp files."
   (with-parsed-tramp-file-name filename nil
+    (when (and (eq flag 'nofollow) (file-symlink-p filename))
+      (tramp-error v 'file-error "Cannot chmod %s with %s flag" filename flag))
     (when (tramp-smb-get-cifs-capabilities v)
       (tramp-flush-file-properties v localname)
       (unless (tramp-smb-send-command
diff --git a/lisp/net/tramp-sudoedit.el b/lisp/net/tramp-sudoedit.el
index f258ad6..e70ee4e 100644
--- a/lisp/net/tramp-sudoedit.el
+++ b/lisp/net/tramp-sudoedit.el
@@ -463,9 +463,11 @@ the result will be a local, non-Tramp, file name."
       (tramp-sudoedit-send-command
        v "test" "-r" (tramp-compat-file-name-unquote localname)))))
 
-(defun tramp-sudoedit-handle-set-file-modes (filename mode)
+(defun tramp-sudoedit-handle-set-file-modes (filename mode &optional flag)
   "Like `set-file-modes' for Tramp files."
   (with-parsed-tramp-file-name filename nil
+    (when (and (eq flag 'nofollow) (file-symlink-p filename))
+      (tramp-error v 'file-error "Cannot chmod %s with %s flag" filename flag))
     (tramp-flush-file-properties v localname)
     (unless (tramp-sudoedit-send-command
             v "chmod" (format "%o" mode)
@@ -715,13 +717,14 @@ ID-FORMAT valid values are `string' and `integer'."
   (start end filename &optional append visit lockname mustbenew)
   "Like `write-region' for Tramp files."
   (with-parsed-tramp-file-name filename nil
-    (let ((uid (or (tramp-compat-file-attribute-user-id
-                   (file-attributes filename 'integer))
-                  (tramp-sudoedit-get-remote-uid v 'integer)))
-         (gid (or (tramp-compat-file-attribute-group-id
-                   (file-attributes filename 'integer))
-                  (tramp-sudoedit-get-remote-gid v 'integer)))
-         (modes (tramp-default-file-modes filename)))
+    (let* ((uid (or (tramp-compat-file-attribute-user-id
+                    (file-attributes filename 'integer))
+                   (tramp-sudoedit-get-remote-uid v 'integer)))
+          (gid (or (tramp-compat-file-attribute-group-id
+                    (file-attributes filename 'integer))
+                   (tramp-sudoedit-get-remote-gid v 'integer)))
+          (flag (and (eq mustbenew 'excl) 'nofollow))
+          (modes (tramp-default-file-modes filename flag)))
       (prog1
          (tramp-handle-write-region
           start end filename append visit lockname mustbenew)
@@ -735,7 +738,7 @@ ID-FORMAT valid values are `string' and `integer'."
                         (file-attributes filename 'integer))
                        gid))
           (tramp-set-file-uid-gid filename uid gid))
-       (set-file-modes filename modes)))))
+       (tramp-compat-set-file-modes filename modes flag)))))
 
 
 ;; Internal functions.
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 409e1f7..c498f8c 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -2135,11 +2135,13 @@ For definition of that list see 
`tramp-set-completion-function'."
 (defvar tramp-devices 0
   "Keeps virtual device numbers.")
 
-(defun tramp-default-file-modes (filename)
+(defun tramp-default-file-modes (filename &optional flag)
   "Return file modes of FILENAME as integer.
-If the file modes of FILENAME cannot be determined, return the
-value of `default-file-modes', without execute permissions."
-  (or (file-modes filename)
+If optional FLAG is ‘nofollow’, do not follow FILENAME if it is a
+symbolic link.  If the file modes of FILENAME cannot be
+determined, return the value of `default-file-modes', without
+execute permissions."
+  (or (tramp-compat-file-modes filename flag)
       (logand (default-file-modes) #o0666)))
 
 (defun tramp-replace-environment-variables (filename)
@@ -3179,10 +3181,13 @@ User is always nil."
       (copy-file filename tmpfile 'ok-if-already-exists 'keep-time)
       tmpfile)))
 
-(defun tramp-handle-file-modes (filename)
+(defun tramp-handle-file-modes (filename &optional flag)
   "Like `file-modes' for Tramp files."
-  (when-let ((attrs (file-attributes (or (file-truename filename) filename))))
-    (tramp-mode-string-to-int (tramp-compat-file-attribute-modes attrs))))
+  (when-let ((attrs (file-attributes filename))
+            (mode-string (tramp-compat-file-attribute-modes attrs)))
+    (if (and (not (eq flag 'nofollow)) (eq ?l (aref mode-string 0)))
+       (file-modes (file-truename filename))
+      (tramp-mode-string-to-int mode-string))))
 
 ;; Localname manipulation functions that grok Tramp localnames...
 (defun tramp-handle-file-name-as-directory (file)
@@ -3876,7 +3881,8 @@ of."
       (tramp-error v 'file-already-exists filename))
 
     (let ((tmpfile (tramp-compat-make-temp-file filename))
-         (modes (save-excursion (tramp-default-file-modes filename))))
+         (modes (tramp-default-file-modes
+                 filename (and (eq mustbenew 'excl) 'nofollow))))
       (when (and append (file-exists-p filename))
        (copy-file filename tmpfile 'ok))
       ;; The permissions of the temporary file should be set.  If
diff --git a/lisp/org/org.el b/lisp/org/org.el
index 52b7281..f1a7f61 100644
--- a/lisp/org/org.el
+++ b/lisp/org/org.el
@@ -568,7 +568,7 @@ Effort estimates given in this property need to have the 
format H:MM.")
   "Regular expression for fast time stamp matching.")
 
 (defconst org-ts-regexp-inactive
-  "\\[\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}[^\r\n>]*\\)\\]"
+  "\\[\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}[^]\r\n>]*\\)\\]"
   "Regular expression for fast inactive time stamp matching.")
 
 (defconst org-ts-regexp-both 
"[[<]\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}[^]\r\n>]*\\)[]>]"
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index 0c338fa..bccef68 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -9034,7 +9034,7 @@ point unchanged and return nil."
                           (if (looking-at c-:-op-cont-regexp)
                               (progn (goto-char (match-end 0)) t)
                             (not
-                             (and (c-major-mode-is 'c++-mode)
+                             (and (c-major-mode-is '(c++-mode java-mode))
                                   (save-excursion
                                     (and
                                      (c-go-up-list-backward)
@@ -9275,9 +9275,10 @@ This function might do hidden buffer changes."
   ;;
   ;;   The third element of the return value is non-nil when the declaration
   ;;   parsed might be an expression.  The fourth element is the position of
-  ;;   the start of the type identifier.  The fifth element is t if either
-  ;;   CONTEXT was 'top, or the declaration is detected to be treated as top
-  ;;   level (e.g. with the keyword "extern").
+  ;;   the start of the type identifier, or the same as the first element when
+  ;;   there is no type identifier.  The fifth element is t if either CONTEXT
+  ;;   was 'top, or the declaration is detected to be treated as top level
+  ;;   (e.g. with the keyword "extern").
   ;;
   ;; If a cast is parsed:
   ;;
@@ -9680,7 +9681,26 @@ This function might do hidden buffer changes."
               (setq got-identifier (c-forward-name))
               (setq name-start pos))
          (when (looking-at "[0-9]")
-           (setq got-number t))) ; We've probably got an arithmetic expression.
+           (setq got-number t)) ; We probably have an arithmetic expression.
+         (and maybe-typeless
+              (or (eq at-type 'maybe)
+                  (when (eq at-type 'found)
+                    ;; Remove the ostensible type from the found types list.
+                    (when type-start
+                      (c-unfind-type
+                       (buffer-substring-no-properties
+                        type-start
+                        (save-excursion
+                          (goto-char type-start)
+                          (c-end-of-token)
+                          (point)))))
+                    t))
+              ;; The token which we assumed to be a type is actually the
+              ;; identifier, and we have no explicit type.
+              (setq at-type nil
+                    name-start type-start
+                    id-start type-start
+                    got-identifier t)))
 
       ;; Skip over type decl suffix operators and trailing noise macros.
       (while
diff --git a/lisp/progmodes/cfengine.el b/lisp/progmodes/cfengine.el
index 18df372..f25b3cb 100644
--- a/lisp/progmodes/cfengine.el
+++ b/lisp/progmodes/cfengine.el
@@ -1390,12 +1390,15 @@ to the action header."
                  (when buffer-file-name
                    (shell-quote-argument buffer-file-name)))))
 
-  ;; For emacs < 25.1 where `eldoc-documentation-function' defaults to
-  ;; nil.
-  (or eldoc-documentation-function
-      (setq-local eldoc-documentation-function #'ignore))
-  (add-function :before-until (local 'eldoc-documentation-function)
-                #'cfengine3-documentation-function)
+  (if (boundp 'eldoc-documentation-functions)
+      (add-hook 'eldoc-documentation-functions
+                #'cfengine3-documentation-function nil t)
+    ;; For emacs < 25.1 where `eldoc-documentation-function' defaults
+    ;; to nil.
+    (or eldoc-documentation-function
+        (setq-local eldoc-documentation-function #'ignore))
+    (add-function :before-until (local 'eldoc-documentation-function)
+                  #'cfengine3-documentation-function))
 
   (add-hook 'completion-at-point-functions
             #'cfengine3-completion-function nil t)
diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el
index 2617a6e..813b628 100644
--- a/lisp/progmodes/elisp-mode.el
+++ b/lisp/progmodes/elisp-mode.el
@@ -250,8 +250,8 @@ Blank lines separate paragraphs.  Semicolons start comments.
     (add-hook 'electric-pair-mode-hook #'emacs-lisp-set-electric-text-pairs))
   (setq-local electric-quote-string t)
   (setq imenu-case-fold-search nil)
-  (add-function :before-until (local 'eldoc-documentation-function)
-                #'elisp-eldoc-documentation-function)
+  (add-hook 'eldoc-documentation-functions
+            #'elisp-eldoc-documentation-function nil t)
   (add-hook 'xref-backend-functions #'elisp--xref-backend nil t)
   (setq-local project-vc-external-roots-function #'elisp-load-path-roots)
   (add-hook 'completion-at-point-functions
diff --git a/lisp/progmodes/octave.el b/lisp/progmodes/octave.el
index 9e03956..352c181 100644
--- a/lisp/progmodes/octave.el
+++ b/lisp/progmodes/octave.el
@@ -619,8 +619,7 @@ Key bindings:
   (add-hook 'before-save-hook 'octave-sync-function-file-names nil t)
   (setq-local beginning-of-defun-function 'octave-beginning-of-defun)
   (and octave-font-lock-texinfo-comment (octave-font-lock-texinfo-comment))
-  (add-function :before-until (local 'eldoc-documentation-function)
-                'octave-eldoc-function)
+  (add-hook 'eldoc-documentation-functions 'octave-eldoc-function nil t)
 
   (easy-menu-add octave-mode-menu))
 
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index a2d85d0..67383b3 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -5544,8 +5544,10 @@ REPORT-FN is Flymake's callback function."
       ;; Emacs<25
       (set (make-local-variable 'eldoc-documentation-function)
            #'python-eldoc-function)
-    (add-function :before-until (local 'eldoc-documentation-function)
-                  #'python-eldoc-function))
+    (if (boundp 'eldoc-documentation-functions)
+        (add-hook 'eldoc-documentation-functions #'python-eldoc-function nil t)
+      (add-function :before-until (local 'eldoc-documentation-function)
+                    #'python-eldoc-function)))
 
   (add-to-list
    'hs-special-modes-alist
diff --git a/lisp/progmodes/verilog-mode.el b/lisp/progmodes/verilog-mode.el
index cc60160..87f901a 100644
--- a/lisp/progmodes/verilog-mode.el
+++ b/lisp/progmodes/verilog-mode.el
@@ -9,7 +9,7 @@
 ;; Keywords: languages
 ;; The "Version" is the date followed by the decimal rendition of the Git
 ;;     commit hex.
-;; Version: 2019.12.17.268053413
+;; Version: 2020.02.23.232634261
 
 ;; Yoni Rabkin <address@hidden> contacted the maintainer of this
 ;; file on 19/3/2008, and the maintainer agreed that when a bug is
@@ -124,7 +124,7 @@
 ;;
 
 ;; This variable will always hold the version number of the mode
-(defconst verilog-mode-version "2019-12-17-ffa2ba5-vpo-GNU"
+(defconst verilog-mode-version "2020-02-23-dddb795-vpo-GNU"
   "Version of this Verilog mode.")
 (defconst verilog-mode-release-emacs t
   "If non-nil, this version of Verilog mode was released with Emacs itself.")
@@ -1282,6 +1282,18 @@ won't merge conflict."
 (put 'verilog-auto-inst-template-numbers 'safe-local-variable
      '(lambda (x) (memq x '(nil t lhs))))
 
+(defcustom verilog-auto-inst-template-required nil
+  "If non-nil, when creating a port with AUTOINST, require a template.
+Any port which does not have a template will be ommitted from the
+instantiation.
+
+If nil, if a port is not templated it will be inserted to connect
+to a net with the same name as the port."
+  :version "28.0"
+  :group 'verilog-mode-auto
+  :type 'boolean)
+(put 'verilog-auto-inst-template-required 'safe-local-variable 
'verilog-booleanp)
+
 (defcustom verilog-auto-inst-column 40
   "Indent-to column number for net name part of AUTOINST created pin."
   :group 'verilog-mode-indent
@@ -3117,7 +3129,7 @@ See also `verilog-font-lock-extra-types'.")
      (:foreground "DimGray" :italic t))
     (((class grayscale) (background dark))
      (:foreground "LightGray" :italic t))
-    (t (:italis t)))
+    (t (:italic t)))
   "Font lock mode face used to background highlight translate-off regions."
   :group 'font-lock-highlighting-faces)
 
@@ -4571,9 +4583,11 @@ More specifically, point @ in the line foo : @ begin"
       nil)))
 
 (defun verilog-backward-up-list (arg)
-  "Call `backward-up-list' ARG, ignoring comments."
+  "Call `backward-up-list' ARG, ignoring comments and errors."
   (let ((parse-sexp-ignore-comments t))
-    (backward-up-list arg)))
+    (condition-case nil
+        (backward-up-list arg)  ;; May throw Unbalanced parenthesis
+      (error nil))))
 
 (defun verilog-forward-sexp-cmt (arg)
   "Call `forward-sexp' ARG, inside comments."
@@ -11370,9 +11384,10 @@ See the example in `verilog-auto-inout-modport'."
 (defvar vl-bits  nil "See `verilog-auto-inst'.") ; Prevent compile warning
 (defvar vl-mbits nil "See `verilog-auto-inst'.") ; Prevent compile warning
 
-(defun verilog-auto-inst-port (port-st indent-pt moddecls tpl-list tpl-num 
for-star par-values)
+(defun verilog-auto-inst-port (section port-st indent-pt moddecls tpl-list 
tpl-num
+                                       for-star par-values)
   "Print out an instantiation connection for this PORT-ST.
-Insert to INDENT-PT, use template TPL-LIST.
+Inside SECTION, insert to INDENT-PT, use template TPL-LIST.
 @ are instantiation numbers, replaced with TPL-NUM.
 @\"(expression @)\" are evaluated, with @ as a variable.
 If FOR-STAR add comment it is a .* expansion.
@@ -11474,60 +11489,74 @@ If PAR-VALUES replace final strings with these 
parameter values."
       (setq tpl-net (verilog-string-replace-matches "\\[\\]\\[\\]" dflt-bits 
nil nil tpl-net))
       (setq tpl-net (verilog-string-replace-matches "\\[\\]" vl-bits nil nil 
tpl-net)))
     ;; Insert it
-    (indent-to indent-pt)
-    (insert "." port)
-    (unless (and verilog-auto-inst-dot-name
-                (equal port tpl-net))
-      (indent-to verilog-auto-inst-column)
-      (insert "(" tpl-net ")"))
-    (insert ",")
-    (cond (tpl-ass
-          (verilog-read-auto-template-hit tpl-ass)
-          (indent-to (+ (if (< verilog-auto-inst-column 48) 24 16)
-                        verilog-auto-inst-column))
-          ;; verilog-insert requires the complete comment in one call - 
including the newline
-          (cond ((equal verilog-auto-inst-template-numbers 'lhs)
-                 (verilog-insert " // Templated"
-                                 " LHS: " (nth 0 tpl-ass)
-                                 "\n"))
-                (verilog-auto-inst-template-numbers
-                 (verilog-insert " // Templated"
-                                 " T" (int-to-string (nth 2 tpl-ass))
-                                 " L" (int-to-string (nth 3 tpl-ass))
-                                 "\n"))
-                (t
-                 (verilog-insert " // Templated\n"))))
-         (for-star
-          (indent-to (+ (if (< verilog-auto-inst-column 48) 24 16)
-                        verilog-auto-inst-column))
-          (verilog-insert " // Implicit .*\n"))
-         (t
-          (insert "\n")))))
-;;(verilog-auto-inst-port (list "foo" "[5:0]") 10 (list (list "foo" "a@\"(% (+ 
@ 1) 4)\"a")) "3")
+    (when (or tpl-ass (not verilog-auto-inst-template-required))
+      (verilog-auto-inst-first section)
+      (indent-to indent-pt)
+      (insert "." port)
+      (unless (and verilog-auto-inst-dot-name
+                   (equal port tpl-net))
+        (indent-to verilog-auto-inst-column)
+        (insert "(" tpl-net ")"))
+      (insert ",")
+      (cond (tpl-ass
+             (verilog-read-auto-template-hit tpl-ass)
+             (indent-to (+ (if (< verilog-auto-inst-column 48) 24 16)
+                           verilog-auto-inst-column))
+             ;; verilog-insert requires the complete comment in one call - 
including the newline
+             (cond ((equal verilog-auto-inst-template-numbers 'lhs)
+                    (verilog-insert " // Templated"
+                                    " LHS: " (nth 0 tpl-ass)
+                                    "\n"))
+                   (verilog-auto-inst-template-numbers
+                    (verilog-insert " // Templated"
+                                    " T" (int-to-string (nth 2 tpl-ass))
+                                    " L" (int-to-string (nth 3 tpl-ass))
+                                    "\n"))
+                   (t
+                    (verilog-insert " // Templated\n"))))
+            (for-star
+             (indent-to (+ (if (< verilog-auto-inst-column 48) 24 16)
+                           verilog-auto-inst-column))
+             (verilog-insert " // Implicit .*\n"))
+            (t
+             (insert "\n"))))))
+;;(verilog-auto-inst-port "" (list "foo" "[5:0]") 10 (list (list "foo" "a@\"(% 
(+ @ 1) 4)\"a")) "3")
 ;;(x "incom[@\"(+ (* 8 @) 7)\":@\"(* 8 @)\"]")
 ;;(x ".out (outgo[@\"(concat (+ (* 8 @) 7) \\\":\\\" ( * 8 @))\"]));")
 
-(defun verilog-auto-inst-port-list (sig-list indent-pt moddecls tpl-list 
tpl-num for-star par-values)
-  "For `verilog-auto-inst' print a list of ports using 
`verilog-auto-inst-port'."
-  (when verilog-auto-inst-sort
-    (setq sig-list (sort (copy-alist sig-list) 
#'verilog-signals-sort-compare)))
-  (mapc (lambda (port)
-         (verilog-auto-inst-port port indent-pt moddecls
-                                 tpl-list tpl-num for-star par-values))
-       sig-list))
+(defvar verilog-auto-inst-first-section nil
+  "Local first-in-section for `verilog-auto-inst-first'.")
+(defvar verilog-auto-inst-first-any nil
+  "Local first-in-any-section for `verilog-auto-inst-first'.")
 
-(defun verilog-auto-inst-first ()
-  "Insert , etc before first ever port in this instant, as part of 
\\[verilog-auto-inst]."
+(defun verilog-auto-inst-first (section)
+  "Insert , and SECTION before port, as part of \\[verilog-auto-inst]."
   ;; Do we need a trailing comma?
   ;; There maybe an ifdef or something similar before us.  What a mess.  Thus
   ;; to avoid trouble we only insert on preceding ) or *.
   ;; Insert first port on new line
-  (insert "\n")  ; Must insert before search, so point will move forward if 
insert comma
-  (save-excursion
-    (verilog-re-search-backward-quick "[^ \t\n\f]" nil nil)
-    (when (looking-at ")\\|\\*")  ; Generally don't insert, unless we are 
fairly sure
-      (forward-char 1)
-      (insert ","))))
+  (when verilog-auto-inst-first-any
+    (setq verilog-auto-inst-first-any nil)
+    (insert "\n")  ; Must insert before search, so point will move forward if 
insert comma
+    (save-excursion
+      (verilog-re-search-backward-quick "[^ \t\n\f]" nil nil)
+      (when (looking-at ")\\|\\*")  ; Generally don't insert, unless we are 
fairly sure
+        (forward-char 1)
+        (insert ","))))
+  (when verilog-auto-inst-first-section
+    (setq verilog-auto-inst-first-section nil)
+    (verilog-insert-indent section)))
+
+(defun verilog-auto-inst-port-list (section sig-list indent-pt moddecls
+                                            tpl-list tpl-num for-star 
par-values)
+  "For `verilog-auto-inst' print a list of ports using 
`verilog-auto-inst-port'."
+  (when verilog-auto-inst-sort
+    (setq sig-list (sort (copy-alist sig-list) 
#'verilog-signals-sort-compare)))
+  (let ((verilog-auto-inst-first-section t))
+    (mapc (lambda (port)
+            (verilog-auto-inst-port section port indent-pt moddecls
+                                    tpl-list tpl-num for-star par-values))
+          sig-list)))
 
 (defun verilog-auto-star ()
   "Expand SystemVerilog .* pins, as part of \\[verilog-auto].
@@ -11697,6 +11726,10 @@ Templates:
   debugging is completed though, it will result in lots of extra differences
   and merge conflicts.
 
+  If a connection name does not match any template, it is
+  connected to a net by the same name as the port (unless
+  `verilog-auto-inst-template-required' is true).
+
   Setting `verilog-auto-template-warn-unused' will report errors
   if any template lines are unused.
 
@@ -11874,10 +11907,11 @@ For more information see the \\[verilog-faq] and 
forums at URL
                                      (1+ (current-column))))
           (verilog-auto-inst-column (max verilog-auto-inst-column
                                          (+ 16 (* 8 (/ (+ indent-pt 7) 8)))))
+           (verilog-auto-inst-first-any t)
           (modi (verilog-modi-current))
           (moddecls (verilog-modi-get-decls modi))
           submod submodi submoddecls
-          inst skip-pins tpl-list tpl-num did-first par-values)
+           inst skip-pins tpl-list tpl-num par-values)
 
       ;; Find module name that is instantiated
       (setq submod  (verilog-read-inst-module)
@@ -11914,51 +11948,46 @@ For more information see the \\[verilog-faq] and 
forums at URL
              (vl-dir "interfaced"))
          (when (and sig-list
                     verilog-auto-inst-interfaced-ports)
-           (when (not did-first) (verilog-auto-inst-first) (setq did-first t))
             ;; Note these are searched for in verilog-read-sub-decls.
-           (verilog-insert-indent "// Interfaced\n")
-           (verilog-auto-inst-port-list sig-list indent-pt moddecls
+            (verilog-auto-inst-port-list "// Interfaced\n"
+                                         sig-list indent-pt moddecls
                                         tpl-list tpl-num for-star par-values)))
        (let ((sig-list (verilog-signals-not-in
                         (verilog-decls-get-interfaces submoddecls)
                         skip-pins))
              (vl-dir "interface"))
          (when sig-list
-           (when (not did-first) (verilog-auto-inst-first) (setq did-first t))
             ;; Note these are searched for in verilog-read-sub-decls.
-           (verilog-insert-indent "// Interfaces\n")
-           (verilog-auto-inst-port-list sig-list indent-pt moddecls
-                                        tpl-list tpl-num for-star par-values)))
+            (verilog-auto-inst-port-list "// Interfaces\n"
+                                         sig-list indent-pt moddecls
+                                         tpl-list tpl-num for-star 
par-values)))
        (let ((sig-list (verilog-signals-not-in
                         (verilog-decls-get-outputs submoddecls)
                         skip-pins))
              (vl-dir "output"))
          (when sig-list
-           (when (not did-first) (verilog-auto-inst-first) (setq did-first t))
-           (verilog-insert-indent "// Outputs\n")
-           (verilog-auto-inst-port-list sig-list indent-pt moddecls
+            (verilog-auto-inst-port-list "// Outputs\n"
+                                         sig-list indent-pt moddecls
                                         tpl-list tpl-num for-star par-values)))
        (let ((sig-list (verilog-signals-not-in
                         (verilog-decls-get-inouts submoddecls)
                         skip-pins))
              (vl-dir "inout"))
          (when sig-list
-           (when (not did-first) (verilog-auto-inst-first) (setq did-first t))
-           (verilog-insert-indent "// Inouts\n")
-           (verilog-auto-inst-port-list sig-list indent-pt moddecls
+            (verilog-auto-inst-port-list "// Inouts\n"
+                                         sig-list indent-pt moddecls
                                         tpl-list tpl-num for-star par-values)))
        (let ((sig-list (verilog-signals-not-in
                         (verilog-decls-get-inputs submoddecls)
                         skip-pins))
              (vl-dir "input"))
          (when sig-list
-           (when (not did-first) (verilog-auto-inst-first) (setq did-first t))
-           (verilog-insert-indent "// Inputs\n")
-           (verilog-auto-inst-port-list sig-list indent-pt moddecls
+            (verilog-auto-inst-port-list "// Inputs\n"
+                                         sig-list indent-pt moddecls
                                         tpl-list tpl-num for-star par-values)))
        ;; Kill extra semi
        (save-excursion
-         (cond (did-first
+          (cond ((not verilog-auto-inst-first-any)
                 (re-search-backward "," pt t)
                 (delete-char 1)
                 (insert ");")
@@ -12020,10 +12049,11 @@ Templates:
                                      (1+ (current-column))))
           (verilog-auto-inst-column (max verilog-auto-inst-column
                                          (+ 16 (* 8 (/ (+ indent-pt 7) 8)))))
+           (verilog-auto-inst-first-any t)
           (modi (verilog-modi-current))
           (moddecls (verilog-modi-get-decls modi))
           submod submodi submoddecls
-          inst skip-pins tpl-list tpl-num did-first)
+           inst skip-pins tpl-list tpl-num)
       ;; Find module name that is instantiated
       (setq submod (save-excursion
                     ;; Get to the point where AUTOINST normally is to read the 
module
@@ -12060,14 +12090,13 @@ Templates:
           (when regexp
             (setq sig-list (verilog-signals-matching-regexp sig-list regexp)))
          (when sig-list
-           (when (not did-first) (verilog-auto-inst-first) (setq did-first t))
             ;; Note these are searched for in verilog-read-sub-decls.
-           (verilog-insert-indent "// Parameters\n")
-           (verilog-auto-inst-port-list sig-list indent-pt moddecls
+            (verilog-auto-inst-port-list "// Parameters\n"
+                                         sig-list indent-pt moddecls
                                         tpl-list tpl-num nil nil)))
        ;; Kill extra semi
        (save-excursion
-         (cond (did-first
+          (cond ((not verilog-auto-inst-first-any)
                 (re-search-backward "," pt t)
                 (delete-char 1)
                 (insert ")")
diff --git a/lisp/server.el b/lisp/server.el
index e6d8b17..1861218 100644
--- a/lisp/server.el
+++ b/lisp/server.el
@@ -563,7 +563,7 @@ See variable `server-auth-dir' for details."
                      (format "it is not owned by you (owner = %s (%d))"
                              (user-full-name uid) uid))
                     (w32 nil)           ; on NTFS?
-                    ((let ((modes (file-modes dir)))
+                    ((let ((modes (file-modes dir 'nofollow)))
                        (unless (zerop (logand (or modes 0) #o077))
                          (format "it is accessible by others (%03o)" modes))))
                     (t nil))))
diff --git a/lisp/textmodes/nroff-mode.el b/lisp/textmodes/nroff-mode.el
index 62e8b1f..bb2582c 100644
--- a/lisp/textmodes/nroff-mode.el
+++ b/lisp/textmodes/nroff-mode.el
@@ -50,7 +50,6 @@
   (let ((map (make-sparse-keymap))
        (menu-map (make-sparse-keymap)))
     (define-key map "\t"  'tab-to-tab-stop)
-    (define-key map "\es" 'center-line)
     (define-key map "\e?" 'nroff-count-text-lines)
     (define-key map "\n"  'nroff-electric-newline)
     (define-key map "\en" 'nroff-forward-text-line)
diff --git a/lisp/url/url-util.el b/lisp/url/url-util.el
index 645011a..6dd7a9c 100644
--- a/lisp/url/url-util.el
+++ b/lisp/url/url-util.el
@@ -615,9 +615,7 @@ Creates FILE and its parent directories if they do not 
exist."
         (with-temp-buffer
           (write-region (point-min) (point-max) file nil 'silent nil 'excl)))
     (file-already-exists
-     (if (file-symlink-p file)
-         (error "Danger: `%s' is a symbolic link" file))
-     (set-file-modes file #o0600))))
+     (set-file-modes file #o0600 'nofollow))))
 
 (autoload 'puny-encode-domain "puny")
 (autoload 'url-domsuf-cookie-allowed-p "url-domsuf")
diff --git a/lisp/vc/pcvs.el b/lisp/vc/pcvs.el
index dcba504..cb0494e 100644
--- a/lisp/vc/pcvs.el
+++ b/lisp/vc/pcvs.el
@@ -106,7 +106,6 @@
 ;;     right now, it's killed without further ado.
 ;; - make `cvs-mode-ignore' allow manually entering a pattern.
 ;;     to which dir should it apply ?
-;; - cvs-mode-ignore should try to remove duplicate entries.
 ;; - maybe poll/check CVS/Entries files to react to external `cvs' commands ?
 ;; - some kind of `cvs annotate' support ?
 ;;     but vc-annotate can be used instead.
@@ -1972,7 +1971,8 @@ This command ignores files that are not flagged as 
`Unknown'."
   (interactive)
   (dolist (fi (cvs-mode-marked 'ignore))
     (vc-cvs-append-to-ignore (cvs-fileinfo->dir fi) (cvs-fileinfo->file fi)
-                         (eq (cvs-fileinfo->subtype fi) 'NEW-DIR))
+                         (eq (cvs-fileinfo->subtype fi) 'NEW-DIR)
+                          cvs-sort-ignore-file)
     (setf (cvs-fileinfo->type fi) 'DEAD))
   (cvs-cleanup-collection cvs-cookies nil nil nil))
 
diff --git a/lisp/vc/vc-cvs.el b/lisp/vc/vc-cvs.el
index 16566a8..b6afda6 100644
--- a/lisp/vc/vc-cvs.el
+++ b/lisp/vc/vc-cvs.el
@@ -1220,14 +1220,33 @@ is non-nil."
   "Return the administrative directory of FILE."
   (vc-find-root file "CVS"))
 
-(defun vc-cvs-ignore (file &optional _directory _remove)
-  "Ignore FILE under CVS."
-  (vc-cvs-append-to-ignore (file-name-directory file) file))
-
-(defun vc-cvs-append-to-ignore (dir str &optional old-dir)
+(defun vc-cvs-ignore (file &optional directory _remove)
+  "Ignore FILE under CVS.
+FILE is either absolute or relative to DIRECTORY.  The basename
+of FILE is written unmodified into the ignore file and is
+therefore evaluated by CVS as an ignore pattern which follows
+glob(7) syntax.  If the pattern should match any of the special
+characters ‘?*[\\\’ literally, they must be escaped with a
+backslash.
+
+CVS processes one ignore file for each subdirectory.  Patterns
+are separated by whitespace and only match files in the same
+directory.  Since FILE can be a relative filename with leading
+diretories, FILE is expanded against DIRECTORY to determine the
+correct absolute filename.  The directory name of this path is
+then used to determine the location of the ignore file.  The base
+name of this path is used as pattern for the ignore file.
+
+Since patterns are whitespace sparated, it is usually better to
+replace spaces in filenames with question marks ‘?’."
+  (setq file (directory-file-name (expand-file-name file directory)))
+  (vc-cvs-append-to-ignore (file-name-directory file) (file-name-nondirectory 
file)))
+
+(defun vc-cvs-append-to-ignore (dir str &optional old-dir sort)
   "In DIR, add STR to the .cvsignore file.
 If OLD-DIR is non-nil, then this is a directory that we don't want
-to hear about anymore."
+to hear about anymore.  If SORT is non-nil, sort the lines of the
+ignore file."
   (with-current-buffer
       (find-file-noselect (expand-file-name ".cvsignore" dir))
     (when (ignore-errors
@@ -1236,13 +1255,13 @@ to hear about anymore."
                 (not (vc-editable-p buffer-file-name))))
       ;; CVSREAD=on special case
       (vc-checkout buffer-file-name t))
-    (goto-char (point-max))
-    (unless (bolp) (insert "\n"))
-    (insert str (if old-dir "/\n" "\n"))
-    ;; FIXME this is a pcvs variable.
-    (if (bound-and-true-p cvs-sort-ignore-file)
-        (sort-lines nil (point-min) (point-max)))
-    (save-buffer)))
+    (goto-char (point-min))
+    (save-match-data
+      (unless (re-search-forward (concat "^" (regexp-quote str) "$") nil 'move)
+        (unless (bolp) (insert "\n"))
+        (insert str (if old-dir "/\n" "\n"))
+        (if sort (sort-lines nil (point-min) (point-max)))
+        (save-buffer)))))
 
 (provide 'vc-cvs)
 
diff --git a/lisp/vc/vc-dir.el b/lisp/vc/vc-dir.el
index 033cb27..e5c5e16 100644
--- a/lisp/vc/vc-dir.el
+++ b/lisp/vc/vc-dir.el
@@ -879,7 +879,9 @@ If a prefix argument is given, ignore all marked files."
           (vc-ignore (vc-dir-fileinfo->name filearg))
           t))
        vc-ewoc)
-    (vc-ignore (vc-dir-current-file))))
+    (vc-ignore
+     (file-relative-name (vc-dir-current-file))
+     default-directory)))
 
 (defun vc-dir-current-file ()
   (let ((node (ewoc-locate vc-ewoc)))
diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el
index f7d651f..ec10265 100644
--- a/lisp/vc/vc.el
+++ b/lisp/vc/vc.el
@@ -480,8 +480,8 @@
 ;;
 ;; - ignore (file &optional directory)
 ;;
-;;   Ignore FILE under the VCS of DIRECTORY (default is `default-directory').
-;;   FILE is a file wildcard.
+;;   Ignore FILE under DIRECTORY (default is 'default-directory').
+;;   FILE is a file wildcard relative to DIRECTORY.
 ;;   When called interactively and with a prefix argument, remove FILE
 ;;   from ignored files.
 ;;   When called from Lisp code, if DIRECTORY is non-nil, the
@@ -1427,40 +1427,43 @@ When called interactively, prompt for a FILE to ignore, 
unless a
 prefix argument is given, in which case prompt for a file FILE to
 remove from the list of ignored files."
   (interactive
-   (list
-    (if (not current-prefix-arg)
-        (read-file-name "File to ignore: ")
-      (completing-read
-       "File to remove: "
-       (vc-call-backend
-        (or (vc-responsible-backend default-directory)
-            (error "Unknown backend"))
-        'ignore-completion-table default-directory)))
-    nil current-prefix-arg))
+   (let* ((backend (vc-responsible-backend default-directory))
+          (rel-dir
+           (condition-case nil
+               (file-name-directory
+                (vc-call-backend backend 'find-ignore-file
+                                 default-directory))
+             (vc-not-supported
+              default-directory)))
+          (file (read-file-name "File to ignore: ")))
+     (when (and (file-name-absolute-p file)
+                (file-in-directory-p file rel-dir))
+       (setq file (file-relative-name file rel-dir)))
+     (list file
+           rel-dir
+           current-prefix-arg)))
   (let* ((directory (or directory default-directory))
         (backend (or (vc-responsible-backend default-directory)
                       (error "Unknown backend"))))
     (vc-call-backend backend 'ignore file directory remove)))
 
 (defun vc-default-ignore (backend file &optional directory remove)
-  "Ignore FILE under the VCS of DIRECTORY (default is `default-directory').
-FILE is a wildcard specification, either relative to
-DIRECTORY or absolute.
+  "Ignore FILE under DIRECTORY (default is `default-directory').
+FILE is a wildcard specification relative to DIRECTORY.
+
 When called from Lisp code, if DIRECTORY is non-nil, the
-repository to use will be deduced by DIRECTORY; if REMOVE is
-non-nil, remove FILE from ignored files.
-Argument BACKEND is the backend you are using."
+repository to use will be deduced by DIRECTORY.
+
+If REMOVE is non-nil, remove FILE from ignored files instead.
+
+Argument BACKEND is the backend to use."
   (let ((ignore
-        (vc-call-backend backend 'find-ignore-file (or directory 
default-directory)))
-       file-path root-dir pattern)
-    (setq file-path (expand-file-name file directory))
-    (setq root-dir (file-name-directory ignore))
-    (when (not (string= (substring file-path 0 (length root-dir)) root-dir))
-      (error "Ignore spec %s is not below project root %s" file-path root-dir))
-    (setq pattern (substring file-path (length root-dir)))
+         (vc-call-backend backend
+                          'find-ignore-file
+                          (or directory default-directory))))
     (if remove
-       (vc--remove-regexp (concat "^" (regexp-quote pattern ) "\\(\n\\|$\\)") 
ignore)
-      (vc--add-line pattern ignore))))
+        (vc--remove-regexp (concat "^" (regexp-quote file) "\\(\n\\|$\\)") 
ignore)
+      (vc--add-line file ignore))))
 
 (defun vc-default-ignore-completion-table (backend file)
   "Return the list of ignored files under BACKEND."
diff --git a/m4/fchmodat.m4 b/m4/fchmodat.m4
new file mode 100644
index 0000000..e3f2f04
--- /dev/null
+++ b/m4/fchmodat.m4
@@ -0,0 +1,82 @@
+# fchmodat.m4 serial 4
+dnl Copyright (C) 2004-2020 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+# Written by Jim Meyering.
+
+AC_DEFUN([gl_FUNC_FCHMODAT],
+[
+  AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS])
+  AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_CHECK_FUNCS_ONCE([fchmodat lchmod])
+  if test $ac_cv_func_fchmodat != yes; then
+    HAVE_FCHMODAT=0
+  else
+    AC_CACHE_CHECK(
+      [whether fchmodat+AT_SYMLINK_NOFOLLOW works on non-symlinks],
+      [gl_cv_func_fchmodat_works],
+      [dnl This test fails on GNU/Linux with glibc 2.31 (but not on
+       dnl GNU/kFreeBSD nor GNU/Hurd) and Cygwin 2.9.
+       AC_RUN_IFELSE(
+         [AC_LANG_PROGRAM(
+            [
+              AC_INCLUDES_DEFAULT[
+              #include <fcntl.h>
+              #ifndef S_IRUSR
+               #define S_IRUSR 0400
+              #endif
+              #ifndef S_IWUSR
+               #define S_IWUSR 0200
+              #endif
+              #ifndef S_IRWXU
+               #define S_IRWXU 0700
+              #endif
+              #ifndef S_IRWXG
+               #define S_IRWXG 0070
+              #endif
+              #ifndef S_IRWXO
+               #define S_IRWXO 0007
+              #endif
+            ]],
+            [[
+              int permissive = S_IRWXU | S_IRWXG | S_IRWXO;
+              int desired = S_IRUSR | S_IWUSR;
+              static char const f[] = "conftest.fchmodat";
+              struct stat st;
+              if (creat (f, permissive) < 0)
+                return 1;
+              if (fchmodat (AT_FDCWD, f, desired, AT_SYMLINK_NOFOLLOW) != 0)
+                return 1;
+              if (stat (f, &st) != 0)
+                return 1;
+              return ! ((st.st_mode & permissive) == desired);
+            ]])],
+         [gl_cv_func_fchmodat_works=yes],
+         [gl_cv_func_fchmodat_works=no],
+         [case "$host_os" in
+            dnl Guess no on Linux with glibc and Cygwin, yes otherwise.
+            linux-gnu* | cygwin*) gl_cv_func_fchmodat_works="guessing no" ;;
+            *)                    
gl_cv_func_fchmodat_works="$gl_cross_guess_normal" ;;
+          esac
+         ])
+       rm -f conftest.fchmodat])
+    case $gl_cv_func_fchmodat_works in
+      *yes) ;;
+      *)
+        AC_DEFINE([NEED_FCHMODAT_NONSYMLINK_FIX], [1],
+          [Define to 1 if fchmodat+AT_SYMLINK_NOFOLLOW does not work right on 
non-symlinks.])
+        REPLACE_FCHMODAT=1
+        ;;
+    esac
+  fi
+])
+
+# Prerequisites of lib/fchmodat.c.
+AC_DEFUN([gl_PREREQ_FCHMODAT],
+[
+  AC_CHECK_FUNCS_ONCE([lchmod])
+  :
+])
diff --git a/m4/getloadavg.m4 b/m4/getloadavg.m4
index 3bd2a14..8e96965 100644
--- a/m4/getloadavg.m4
+++ b/m4/getloadavg.m4
@@ -7,7 +7,7 @@
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-#serial 8
+#serial 9
 
 # Autoconf defines AC_FUNC_GETLOADAVG, but that is obsolescent.
 # New applications should use gl_GETLOADAVG instead.
@@ -45,7 +45,9 @@ AC_CHECK_FUNC([getloadavg], [],
      # There is a commonly available library for RS/6000 AIX.
      # Since it is not a standard part of AIX, it might be installed locally.
      gl_getloadavg_LIBS=$LIBS
-     LIBS="-L/usr/local/lib $LIBS"
+     if test $cross_compiling != yes; then
+       LIBS="-L/usr/local/lib $LIBS"
+     fi
      AC_CHECK_LIB([getloadavg], [getloadavg],
                   [LIBS="-lgetloadavg $LIBS" gl_func_getloadavg_done=yes],
                   [LIBS=$gl_getloadavg_LIBS])
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
index 48d8030..1465ce8 100644
--- a/m4/gnulib-comp.m4
+++ b/m4/gnulib-comp.m4
@@ -82,6 +82,7 @@ AC_DEFUN([gl_EARLY],
   # Code from module extensions:
   # Code from module extern-inline:
   # Code from module faccessat:
+  # Code from module fchmodat:
   # Code from module fcntl:
   # Code from module fcntl-h:
   # Code from module fdopendir:
@@ -111,6 +112,7 @@ AC_DEFUN([gl_EARLY],
   # Code from module inttypes-incomplete:
   # Code from module largefile:
   AC_REQUIRE([AC_SYS_LARGEFILE])
+  # Code from module lchmod:
   # Code from module libc-config:
   # Code from module limits-h:
   # Code from module localtime-buffer:
@@ -211,6 +213,7 @@ AC_DEFUN([gl_INIT],
   gl_MODULE_INDICATOR([canonicalize-lgpl])
   gl_STDLIB_MODULE_INDICATOR([canonicalize_file_name])
   gl_STDLIB_MODULE_INDICATOR([realpath])
+  AC_REQUIRE([AC_C_RESTRICT])
   AC_CHECK_FUNCS_ONCE([readlinkat])
   gl_CLOCK_TIME
   gl_MODULE_INDICATOR([close-stream])
@@ -219,9 +222,13 @@ AC_DEFUN([gl_INIT],
     AC_LIBOBJ([copy-file-range])
   fi
   gl_UNISTD_MODULE_INDICATOR([copy-file-range])
+  AC_REQUIRE([AC_C_RESTRICT])
   gl_MD5
+  AC_REQUIRE([AC_C_RESTRICT])
   gl_SHA1
+  AC_REQUIRE([AC_C_RESTRICT])
   gl_SHA256
+  AC_REQUIRE([AC_C_RESTRICT])
   gl_SHA512
   gl_CHECK_TYPE_STRUCT_DIRENT_D_TYPE
   gl_DIRENT_H
@@ -250,6 +257,12 @@ AC_DEFUN([gl_INIT],
   fi
   gl_MODULE_INDICATOR([faccessat])
   gl_UNISTD_MODULE_INDICATOR([faccessat])
+  gl_FUNC_FCHMODAT
+  if test $HAVE_FCHMODAT = 0 || test $REPLACE_FCHMODAT = 1; then
+    AC_LIBOBJ([fchmodat])
+    gl_PREREQ_FCHMODAT
+  fi
+  gl_SYS_STAT_MODULE_INDICATOR([fchmodat])
   gl_FUNC_FCNTL
   if test $HAVE_FCNTL = 0 || test $REPLACE_FCNTL = 1; then
     AC_LIBOBJ([fcntl])
@@ -463,6 +476,7 @@ AC_DEFUN([gl_INIT],
   gl_gnulib_enabled_getgroups=false
   gl_gnulib_enabled_be453cec5eecf5731a274f2de7f2db36=false
   gl_gnulib_enabled_a9786850e999ae65a836a6041e8e5ed1=false
+  gl_gnulib_enabled_lchmod=false
   gl_gnulib_enabled_21ee726a3540c09237a8e70c0baf7467=false
   gl_gnulib_enabled_2049e887c7e5308faad27b3f894bb8c9=false
   gl_gnulib_enabled_malloca=false
@@ -564,6 +578,18 @@ AC_DEFUN([gl_INIT],
       fi
     fi
   }
+  func_gl_gnulib_m4code_lchmod ()
+  {
+    if ! $gl_gnulib_enabled_lchmod; then
+      gl_FUNC_LCHMOD
+      if test $HAVE_LCHMOD = 0; then
+        AC_LIBOBJ([lchmod])
+        gl_PREREQ_LCHMOD
+      fi
+      gl_SYS_STAT_MODULE_INDICATOR([lchmod])
+      gl_gnulib_enabled_lchmod=true
+    fi
+  }
   func_gl_gnulib_m4code_21ee726a3540c09237a8e70c0baf7467 ()
   {
     if ! $gl_gnulib_enabled_21ee726a3540c09237a8e70c0baf7467; then
@@ -655,6 +681,15 @@ AC_DEFUN([gl_INIT],
   if test $HAVE_FACCESSAT = 0 || test $REPLACE_FACCESSAT = 1; then
     func_gl_gnulib_m4code_03e0aaad4cb89ca757653bd367a6ccb7
   fi
+  if test $HAVE_FCHMODAT = 0; then
+    func_gl_gnulib_m4code_260941c0e5dc67ec9e87d1fb321c300b
+  fi
+  if test $HAVE_FCHMODAT = 0; then
+    func_gl_gnulib_m4code_lchmod
+  fi
+  if test $HAVE_FCHMODAT = 0; then
+    func_gl_gnulib_m4code_03e0aaad4cb89ca757653bd367a6ccb7
+  fi
   if test $HAVE_FCNTL = 0 || test $REPLACE_FCNTL = 1; then
     func_gl_gnulib_m4code_getdtablesize
   fi
@@ -703,6 +738,7 @@ AC_DEFUN([gl_INIT],
   AM_CONDITIONAL([gl_GNULIB_ENABLED_getgroups], [$gl_gnulib_enabled_getgroups])
   AM_CONDITIONAL([gl_GNULIB_ENABLED_be453cec5eecf5731a274f2de7f2db36], 
[$gl_gnulib_enabled_be453cec5eecf5731a274f2de7f2db36])
   AM_CONDITIONAL([gl_GNULIB_ENABLED_a9786850e999ae65a836a6041e8e5ed1], 
[$gl_gnulib_enabled_a9786850e999ae65a836a6041e8e5ed1])
+  AM_CONDITIONAL([gl_GNULIB_ENABLED_lchmod], [$gl_gnulib_enabled_lchmod])
   AM_CONDITIONAL([gl_GNULIB_ENABLED_21ee726a3540c09237a8e70c0baf7467], 
[$gl_gnulib_enabled_21ee726a3540c09237a8e70c0baf7467])
   AM_CONDITIONAL([gl_GNULIB_ENABLED_2049e887c7e5308faad27b3f894bb8c9], 
[$gl_gnulib_enabled_2049e887c7e5308faad27b3f894bb8c9])
   AM_CONDITIONAL([gl_GNULIB_ENABLED_malloca], [$gl_gnulib_enabled_malloca])
@@ -903,6 +939,7 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/execinfo.in.h
   lib/explicit_bzero.c
   lib/faccessat.c
+  lib/fchmodat.c
   lib/fcntl.c
   lib/fcntl.in.h
   lib/fdopendir.c
@@ -941,6 +978,7 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/ignore-value.h
   lib/intprops.h
   lib/inttypes.in.h
+  lib/lchmod.c
   lib/libc-config.h
   lib/limits.in.h
   lib/localtime-buffer.c
@@ -1053,6 +1091,7 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/extensions.m4
   m4/extern-inline.m4
   m4/faccessat.m4
+  m4/fchmodat.m4
   m4/fcntl-o.m4
   m4/fcntl.m4
   m4/fcntl_h.m4
@@ -1078,6 +1117,7 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/include_next.m4
   m4/inttypes.m4
   m4/largefile.m4
+  m4/lchmod.m4
   m4/limits-h.m4
   m4/localtime-buffer.m4
   m4/lstat.m4
diff --git a/m4/lchmod.m4 b/m4/lchmod.m4
new file mode 100644
index 0000000..b9e8a97
--- /dev/null
+++ b/m4/lchmod.m4
@@ -0,0 +1,31 @@
+#serial 7
+
+dnl Copyright (C) 2005-2006, 2008-2020 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Paul Eggert.
+dnl Provide a replacement for lchmod on hosts that lack a working version.
+
+AC_DEFUN([gl_FUNC_LCHMOD],
+[
+  AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS])
+
+  dnl Persuade glibc <sys/stat.h> to declare lchmod().
+  AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
+
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+
+  AC_CHECK_FUNCS_ONCE([lchmod lstat])
+  if test "$ac_cv_func_lchmod" = no; then
+    HAVE_LCHMOD=0
+  fi
+])
+
+# Prerequisites of lib/lchmod.c.
+AC_DEFUN([gl_PREREQ_LCHMOD],
+[
+  AC_REQUIRE([AC_C_INLINE])
+  :
+])
diff --git a/m4/nstrftime.m4 b/m4/nstrftime.m4
index c15fab3..6f2762a 100644
--- a/m4/nstrftime.m4
+++ b/m4/nstrftime.m4
@@ -1,4 +1,4 @@
-# serial 34
+# serial 35
 
 # Copyright (C) 1996-1997, 1999-2007, 2009-2020 Free Software Foundation, Inc.
 #
@@ -10,6 +10,8 @@
 
 AC_DEFUN([gl_FUNC_GNU_STRFTIME],
 [
+ AC_REQUIRE([AC_C_RESTRICT])
+
  # This defines (or not) HAVE_TZNAME and HAVE_TM_ZONE.
  AC_REQUIRE([AC_STRUCT_TIMEZONE])
 
diff --git a/nt/gnulib-cfg.mk b/nt/gnulib-cfg.mk
index 08e83e0..1d120a9 100644
--- a/nt/gnulib-cfg.mk
+++ b/nt/gnulib-cfg.mk
@@ -63,3 +63,5 @@ OMIT_GNULIB_MODULE_sys_time = true
 OMIT_GNULIB_MODULE_sys_types = true
 OMIT_GNULIB_MODULE_unistd = true
 OMIT_GNULIB_MODULE_canonicalize-lgpl = true
+OMIT_GNULIB_MODULE_fchmodat = true
+OMIT_GNULIB_MODULE_lchmod = true
diff --git a/nt/mingw-cfg.site b/nt/mingw-cfg.site
index dfdca39..5bd5b83 100644
--- a/nt/mingw-cfg.site
+++ b/nt/mingw-cfg.site
@@ -102,6 +102,9 @@ ac_cv_func_lstat=yes
 gl_cv_func_lstat_dereferences_slashed_symlink=yes
 ac_cv_func_fstatat=yes
 gl_cv_func_fstatat_zero_flag=yes
+ac_cv_func_fchmodat=yes
+gl_cv_func_fchmodat_works="not-needed-so-yes"
+ac_cv_func_lchmod=yes
 # Aliased to _commit in ms-w32.h
 ac_cv_func_fsync=yes
 ac_cv_func_fdatasync=yes
diff --git a/src/fileio.c b/src/fileio.c
index 6b56c47..2532f52 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -3332,50 +3332,60 @@ support.  */)
   return Qnil;
 }
 
-DEFUN ("file-modes", Ffile_modes, Sfile_modes, 1, 1, 0,
+static int
+symlink_nofollow_flag (Lisp_Object flag)
+{
+  /* For now, treat all non-nil FLAGs like 'nofollow'.  */
+  return !NILP (flag) ? AT_SYMLINK_NOFOLLOW : 0;
+}
+
+DEFUN ("file-modes", Ffile_modes, Sfile_modes, 1, 2, 0,
        doc: /* Return mode bits of file named FILENAME, as an integer.
-Return nil if FILENAME does not exist.  */)
-  (Lisp_Object filename)
+Return nil if FILENAME does not exist.  If optional FLAG is `nofollow',
+do not follow FILENAME if it is a symbolic link.  */)
+  (Lisp_Object filename, Lisp_Object flag)
 {
   struct stat st;
+  int nofollow = symlink_nofollow_flag (flag);
   Lisp_Object absname = expand_and_dir_to_file (filename);
 
   /* If the file name has special constructs in it,
      call the corresponding file name handler.  */
   Lisp_Object handler = Ffind_file_name_handler (absname, Qfile_modes);
   if (!NILP (handler))
-    return call2 (handler, Qfile_modes, absname);
+    return call3 (handler, Qfile_modes, absname, flag);
 
-  if (emacs_fstatat (AT_FDCWD, SSDATA (ENCODE_FILE (absname)), &st, 0) != 0)
+  char *fname = SSDATA (ENCODE_FILE (absname));
+  if (emacs_fstatat (AT_FDCWD, fname, &st, nofollow) != 0)
     return file_attribute_errno (absname, errno);
   return make_fixnum (st.st_mode & 07777);
 }
 
-DEFUN ("set-file-modes", Fset_file_modes, Sset_file_modes, 2, 2,
+DEFUN ("set-file-modes", Fset_file_modes, Sset_file_modes, 2, 3,
        "(let ((file (read-file-name \"File: \")))                      \
          (list file (read-file-modes nil file)))",
        doc: /* Set mode bits of file named FILENAME to MODE (an integer).
-Only the 12 low bits of MODE are used.
+Only the 12 low bits of MODE are used.  If optional FLAG is `nofollow',
+do not follow FILENAME if it is a symbolic link.
 
 Interactively, mode bits are read by `read-file-modes', which accepts
 symbolic notation, like the `chmod' command from GNU Coreutils.  */)
-  (Lisp_Object filename, Lisp_Object mode)
+  (Lisp_Object filename, Lisp_Object mode, Lisp_Object flag)
 {
-  Lisp_Object absname, encoded_absname;
-  Lisp_Object handler;
-
-  absname = Fexpand_file_name (filename, BVAR (current_buffer, directory));
   CHECK_FIXNUM (mode);
+  int nofollow = symlink_nofollow_flag (flag);
+  Lisp_Object absname = Fexpand_file_name (filename,
+                                          BVAR (current_buffer, directory));
 
   /* If the file name has special constructs in it,
      call the corresponding file name handler.  */
-  handler = Ffind_file_name_handler (absname, Qset_file_modes);
+  Lisp_Object handler = Ffind_file_name_handler (absname, Qset_file_modes);
   if (!NILP (handler))
-    return call3 (handler, Qset_file_modes, absname, mode);
-
-  encoded_absname = ENCODE_FILE (absname);
+    return call4 (handler, Qset_file_modes, absname, mode, flag);
 
-  if (chmod (SSDATA (encoded_absname), XFIXNUM (mode) & 07777) < 0)
+  char *fname = SSDATA (ENCODE_FILE (absname));
+  mode_t imode = XFIXNUM (mode) & 07777;
+  if (fchmodat (AT_FDCWD, fname, imode, nofollow) != 0)
     report_file_error ("Doing chmod", absname);
 
   return Qnil;
@@ -5740,7 +5750,7 @@ auto_save_1 (void)
          == 0)
        /* But make sure we can overwrite it later!  */
        auto_save_mode_bits = (st.st_mode | 0600) & 0777;
-      else if (modes = Ffile_modes (BVAR (current_buffer, filename)),
+      else if (modes = Ffile_modes (BVAR (current_buffer, filename), Qnil),
               FIXNUMP (modes))
        /* Remote files don't cooperate with fstatat.  */
        auto_save_mode_bits = (XFIXNUM (modes) | 0600) & 0777;
diff --git a/src/w32.c b/src/w32.c
index a3b9a56..cf1a3b3 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -4320,10 +4320,9 @@ sys_chdir (const char * path)
     }
 }
 
-int
-sys_chmod (const char * path, int mode)
+static int
+chmod_worker (const char * path, int mode)
 {
-  path = chase_symlinks (map_w32_filename (path, NULL));
   if (w32_unicode_filenames)
     {
       wchar_t path_w[MAX_PATH];
@@ -4341,6 +4340,20 @@ sys_chmod (const char * path, int mode)
 }
 
 int
+sys_chmod (const char * path, int mode)
+{
+  path = chase_symlinks (map_w32_filename (path, NULL));
+  return chmod_worker (path, mode);
+}
+
+int
+lchmod (const char * path, mode_t mode)
+{
+  path = map_w32_filename (path, NULL);
+  return chmod_worker (path, mode);
+}
+
+int
 sys_creat (const char * path, int mode)
 {
   path = map_w32_filename (path, NULL);
@@ -4619,6 +4632,28 @@ fchmod (int fd, mode_t mode)
 }
 
 int
+fchmodat (int fd, char const *path, mode_t mode, int flags)
+{
+  /* Rely on a hack: an open directory is modeled as file descriptor 0,
+     as in fstatat.  FIXME: Add proper support for fchmodat.  */
+  char fullname[MAX_UTF8_PATH];
+
+  if (fd != AT_FDCWD)
+    {
+      if (_snprintf (fullname, sizeof fullname, "%s/%s", dir_pathname, path)
+         < 0)
+       {
+         errno = ENAMETOOLONG;
+         return -1;
+       }
+      path = fullname;
+    }
+
+  return
+    flags == AT_SYMLINK_NOFOLLOW ? lchmod (path, mode) : sys_chmod (path, 
mode);
+}
+
+int
 sys_rename_replace (const char *oldname, const char *newname, BOOL force)
 {
   BOOL result;
diff --git a/src/w32.h b/src/w32.h
index f301b38..cf1dadf 100644
--- a/src/w32.h
+++ b/src/w32.h
@@ -222,6 +222,8 @@ extern void register_child (pid_t, int);
 extern void sys_sleep (int);
 extern int sys_link (const char *, const char *);
 extern int openat (int, const char *, int, int);
+extern int fchmodat (int, char const *, mode_t, int);
+extern int lchmod (char const *, mode_t);
 
 /* Return total and free memory info.  */
 extern int w32_memory_info (unsigned long long *, unsigned long long *,
diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el 
b/test/lisp/emacs-lisp/bytecomp-tests.el
index de11ae2..d4ceb47 100644
--- a/test/lisp/emacs-lisp/bytecomp-tests.el
+++ b/test/lisp/emacs-lisp/bytecomp-tests.el
@@ -347,7 +347,12 @@
                                 ((eq x 't) 99)
                                 (t 999))))
             '((a c) (b c) (7 c) (-3 c) (nil nil) (t c) (q c) (r c) (s c)
-              (t c) (x "a") (x "c") (x c) (x d) (x e))))
+              (t c) (x "a") (x "c") (x c) (x d) (x e)))
+
+    ;; `substring' bytecode generation (bug#39709).
+    (substring "abcdef")
+    (substring "abcdef" 2)
+    (substring "abcdef" 3 2))
   "List of expression for test.
 Each element will be executed by interpreter and with
 bytecompiled code, and their results compared.")
diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el
index 9409cc2..7b43d6f 100644
--- a/test/lisp/net/tramp-tests.el
+++ b/test/lisp/net/tramp-tests.el
@@ -3082,14 +3082,18 @@ This tests also `file-directory-p' and 
`file-accessible-directory-p'."
 ;; Method "smb" supports `make-symbolic-link' only if the remote host
 ;; has CIFS capabilities.  tramp-adb.el, tramp-gvfs.el and
 ;; tramp-rclone.el do not support symbolic links at all.
+;; We check also `set-file-modes' with nofollow flag.
 (defmacro tramp--test-ignore-make-symbolic-link-error (&rest body)
   "Run BODY, ignoring \"make-symbolic-link not supported\" file error."
   (declare (indent defun) (debug (body)))
   `(condition-case err
        (progn ,@body)
      (file-error
-      (unless (string-equal (error-message-string err)
-                           "make-symbolic-link not supported")
+      (unless (string-match-p
+              (concat
+               "^\\(make-symbolic-link not supported"
+               "\\|Cannot chmod .* with nofollow flag\\)$")
+              (error-message-string err))
        (signal (car err) (cdr err))))))
 
 (ert-deftest tramp-test18-file-attributes ()
@@ -3364,25 +3368,69 @@ This tests also `file-executable-p', `file-writable-p' 
and `set-file-modes'."
         "ftp" (file-remote-p tramp-test-temporary-file-directory 'method)))))
 
   (dolist (quoted (if (tramp--test-expensive-test) '(nil t) '(nil)))
-    (let ((tmp-name (tramp--test-make-temp-name nil quoted)))
+    (let ((tmp-name1 (tramp--test-make-temp-name nil quoted))
+         (tmp-name2 (tramp--test-make-temp-name nil quoted)))
+
       (unwind-protect
          (progn
-           (write-region "foo" nil tmp-name)
-           (should (file-exists-p tmp-name))
-           (set-file-modes tmp-name #o777)
-           (should (= (file-modes tmp-name) #o777))
-           (should (file-executable-p tmp-name))
-           (should (file-writable-p tmp-name))
-           (set-file-modes tmp-name #o444)
-           (should (= (file-modes tmp-name) #o444))
-           (should-not (file-executable-p tmp-name))
+           (write-region "foo" nil tmp-name1)
+           (should (file-exists-p tmp-name1))
+           (set-file-modes tmp-name1 #o777)
+           (should (= (file-modes tmp-name1) #o777))
+           (should (file-executable-p tmp-name1))
+           (should (file-writable-p tmp-name1))
+           (set-file-modes tmp-name1 #o444)
+           (should (= (file-modes tmp-name1) #o444))
+           (should-not (file-executable-p tmp-name1))
            ;; A file is always writable for user "root".
            (unless (zerop (tramp-compat-file-attribute-user-id
-                           (file-attributes tmp-name)))
-             (should-not (file-writable-p tmp-name))))
+                           (file-attributes tmp-name1)))
+             (should-not (file-writable-p tmp-name1))))
 
        ;; Cleanup.
-       (ignore-errors (delete-file tmp-name))))))
+       (ignore-errors (delete-file tmp-name1)))
+
+      ;; Check the NOFOLLOW arg.  It exists since Emacs 28.
+      (when (tramp--test-emacs28-p)
+       (unwind-protect
+           (tramp--test-ignore-make-symbolic-link-error
+             (write-region "foo" nil tmp-name1)
+             (should (file-exists-p tmp-name1))
+             (make-symbolic-link tmp-name1 tmp-name2)
+             (should
+              (string-equal
+               (funcall
+                (if quoted #'tramp-compat-file-name-unquote #'identity)
+                (file-remote-p tmp-name1 'localname))
+               (file-symlink-p tmp-name2)))
+             ;; Both report the modes of `tmp-name1'.
+             (should
+              (= (file-modes tmp-name1) (file-modes tmp-name2)))
+             ;; `tmp-name1' is a regular file.  NOFOLLOW doesn't matter.
+             (should
+              (= (file-modes tmp-name1) (file-modes tmp-name1 'nofollow)))
+             ;; `tmp-name2' is a symbolic link.  It has different permissions.
+             (should-not
+              (= (file-modes tmp-name2) (file-modes tmp-name2 'nofollow)))
+             (should-not
+              (= (file-modes tmp-name1 'nofollow)
+                 (file-modes tmp-name2 'nofollow)))
+             ;; Change permissions.
+             (set-file-modes tmp-name1 #o200)
+             (set-file-modes tmp-name2 #o200)
+             (should
+              (= (file-modes tmp-name1) (file-modes tmp-name2) #o200))
+             ;; Change permissions with NOFOLLOW.
+             (set-file-modes tmp-name1 #o300 'nofollow)
+             (set-file-modes tmp-name2 #o300 'nofollow)
+             (should
+              (= (file-modes tmp-name1 'nofollow)
+                 (file-modes tmp-name2 'nofollow)))
+             (should-not (= (file-modes tmp-name1) (file-modes tmp-name2))))
+
+         ;; Cleanup.
+         (ignore-errors (delete-file tmp-name1))
+         (ignore-errors (delete-file tmp-name2)))))))
 
 ;; Method "smb" could run into "NT_STATUS_REVISION_MISMATCH" error.
 (defmacro tramp--test-ignore-add-name-to-file-error (&rest body)
@@ -4358,7 +4406,7 @@ This tests also `make-symbolic-link', `file-truename' and 
`add-name-to-file'."
              (while (accept-process-output proc 0 nil t)))
            ;; We cannot use `string-equal', because tramp-adb.el
            ;; echoes also the sent string.  And a remote macOS sends
-           ;; a slightly modified string. On MS-Windows,
+           ;; a slightly modified string.  On MS Windows,
            ;; `delete-process' sends an unknown signal.
            (should
             (string-match
@@ -5344,6 +5392,12 @@ Some semantics has been changed for there, w/o new 
functions or
 variables, so we check the Emacs version directly."
   (>= emacs-major-version 27))
 
+(defun tramp--test-emacs28-p ()
+  "Check for Emacs version >= 28.1.
+Some semantics has been changed for there, w/o new functions or
+variables, so we check the Emacs version directly."
+  (>= emacs-major-version 28))
+
 (defun tramp--test-adb-p ()
   "Check, whether the remote host runs Android.
 This requires restrictions of file name syntax."



reply via email to

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