emacs-diffs
[Top][All Lists]
Advanced

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

feature/native-comp 5be335e 5/5: Merge remote-tracking branch 'savahnna/


From: Andrea Corallo
Subject: feature/native-comp 5be335e 5/5: Merge remote-tracking branch 'savahnna/master' into HEAD
Date: Mon, 13 Jul 2020 09:28:04 -0400 (EDT)

branch: feature/native-comp
commit 5be335e6b5d1a948a94206869d75c04684104203
Merge: eb091c8 46a0c11
Author: Andrea Corallo <akrl@sdf.org>
Commit: Andrea Corallo <akrl@sdf.org>

    Merge remote-tracking branch 'savahnna/master' into HEAD
---
 .gitignore                          |   1 +
 admin/merge-gnulib                  |   2 +-
 configure.ac                        |  59 +++--------
 doc/emacs/custom.texi               |   2 +-
 doc/emacs/modes.texi                |   2 +-
 doc/emacs/mule.texi                 |   8 +-
 doc/emacs/programs.texi             |   8 +-
 doc/lispref/display.texi            |  12 ++-
 doc/lispref/numbers.texi            |   3 +
 doc/lispref/strings.texi            |  13 ++-
 doc/misc/eudc.texi                  |  52 +++++++++
 doc/misc/flymake.texi               |   2 +-
 etc/NEWS                            |   7 ++
 etc/NEWS.22                         |   2 +-
 etc/NEWS.23                         |   2 +-
 lib/alloca.in.h                     |  15 +--
 lib/dup2.c                          | 100 +++++------------
 lib/getrandom.c                     |   2 +-
 lib/gnulib.mk.in                    |  38 +++++--
 lib/mini-gmp-gnulib.c               |  37 +++++++
 {src => lib}/mini-gmp.c             | 144 ++++++++++++++++---------
 {src => lib}/mini-gmp.h             |  10 +-
 lib/string.in.h                     |   5 -
 lib/sys_stat.in.h                   |  17 +++
 lib/unistd.in.h                     |   3 -
 lisp/autorevert.el                  |   2 +-
 lisp/descr-text.el                  |  18 +++-
 lisp/emacs-lisp/eldoc.el            | 132 +++++++++++++----------
 lisp/net/eudcb-macos-contacts.el    | 118 +++++++++++++++++++++
 lisp/net/tramp-adb.el               | 184 ++++++++++++++++++--------------
 lisp/net/tramp-cmds.el              |  14 ++-
 lisp/net/tramp-ftp.el               |   7 +-
 lisp/net/tramp-gvfs.el              |  78 +++++++-------
 lisp/net/tramp-sh.el                | 153 ++++++++++++--------------
 lisp/net/tramp-smb.el               |  54 ++++++----
 lisp/net/tramp-sudoedit.el          |  12 +--
 lisp/net/tramp.el                   |  43 ++++----
 lisp/progmodes/project.el           |  50 ++++++---
 lisp/progmodes/python.el            |   8 +-
 m4/dup2.m4                          | 181 +++++++++++++++----------------
 m4/getrandom.m4                     |   6 +-
 m4/gnulib-comp.m4                   |  12 ++-
 m4/lchmod.m4                        |   3 +-
 m4/libgmp.m4                        |  44 ++++++++
 m4/manywarnings.m4                  | 206 ++++++------------------------------
 m4/string_h.m4                      |   3 +-
 m4/sys_stat_h.m4                    |   8 +-
 m4/unistd_h.m4                      |   3 +-
 src/Makefile.in                     |   5 +-
 src/bignum.h                        |   7 +-
 src/gtkutil.c                       |   7 ++
 src/mini-gmp-emacs.c                |  32 ------
 src/xdisp.c                         |   2 +-
 test/Makefile.in                    |  11 +-
 test/data/emacs-module/mod-test.c   |   5 -
 test/lisp/net/tramp-tests.el        |  14 ++-
 test/lisp/progmodes/python-tests.el |   2 +-
 test/src/emacs-module-tests.el      |   3 +
 58 files changed, 1076 insertions(+), 897 deletions(-)

diff --git a/.gitignore b/.gitignore
index 52816e8..aebd507 100644
--- a/.gitignore
+++ b/.gitignore
@@ -60,6 +60,7 @@ lib/execinfo.h
 lib/fcntl.h
 lib/getopt.h
 lib/getopt-cdefs.h
+lib/gmp.h
 lib/ieee754.h
 lib/inttypes.h
 lib/libgnu.a
diff --git a/admin/merge-gnulib b/admin/merge-gnulib
index 5a78b05..3f32536 100755
--- a/admin/merge-gnulib
+++ b/admin/merge-gnulib
@@ -36,7 +36,7 @@ GNULIB_MODULES='
   fchmodat fcntl fcntl-h fdopendir
   filemode filename filevercmp flexmember fpieee fstatat fsusage fsync futimens
   getloadavg getopt-gnu getrandom gettime gettimeofday gitlog-to-changelog
-  ieee754-h ignore-value intprops largefile lstat
+  ieee754-h ignore-value intprops largefile libgmp lstat
   manywarnings memmem-simple mempcpy memrchr minmax mkostemp mktime nstrftime
   pathmax pipe2 pselect pthread_sigmask
   qcopy-acl readlink readlinkat regex
diff --git a/configure.ac b/configure.ac
index ac9f23e..2277f36 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1031,14 +1031,17 @@ AS_IF([test $gl_gcc_warnings = no],
        ;;
   esac
   AS_IF([test $gl_gcc_warnings = yes],
-    [WERROR_CFLAGS=-Werror])
+    [WERROR_CFLAGS=-Werror],
+    [# Use -fanalyzer and related options only if --enable-gcc-warnings,
+     # as they slow GCC considerably.
+     nw="$nw -fanalyzer -Wno-analyzer-double-free -Wno-analyzer-malloc-leak"
+     nw="$nw -Wno-analyzer-null-dereference -Wno-analyzer-use-after-free"])
 
-  nw="$nw -Wcast-align -Wcast-align=strict" # Emacs is tricky with pointers.
+  nw="$nw -Wcast-align=strict"      # Emacs is tricky with pointers.
   nw="$nw -Wduplicated-branches"    # Too many false alarms
   nw="$nw -Wformat-overflow=2"      # False alarms due to GCC bug 80776
   nw="$nw -Wsystem-headers"         # Don't let system headers trigger warnings
   nw="$nw -Woverlength-strings"     # Not a problem these days
-  nw="$nw -Wformat-nonliteral"      # we do this a lot
   nw="$nw -Wvla"                    # Emacs uses <vla.h>.
   nw="$nw -Wunused-const-variable=2" # lisp.h declares const objects.
   nw="$nw -Winline"                 # OK to ignore 'inline'
@@ -1047,7 +1050,6 @@ AS_IF([test $gl_gcc_warnings = no],
   nw="$nw -Wsync-nand"              # irrelevant here, and provokes ObjC 
warning
   nw="$nw -Wunsafe-loop-optimizations" # OK to suppress unsafe optimizations
   nw="$nw -Wbad-function-cast"      # These casts are no worse than others.
-  nw="$nw -Wabi"                    # Not useful, perceived as noise
 
   # Emacs doesn't care about shadowing; see
   # <https://lists.gnu.org/r/emacs-diffs/2011-11/msg00265.html>.
@@ -1067,26 +1069,12 @@ AS_IF([test $gl_gcc_warnings = no],
   # option problematic.
   nw="$nw -Wsuggest-attribute=pure"
 
-  # This part is merely for shortening the command line,
-  # since -Wall implies -Wswitch.
-  nw="$nw -Wswitch"
-
-  # This part is merely for shortening the command line,
-  # since -Wno-FOO needs to be added below regardless.
-  nw="$nw -Wmissing-field-initializers"
-  nw="$nw -Woverride-init"
-  nw="$nw -Wtype-limits"
-  nw="$nw -Wunused-parameter"
-
   if test "$emacs_cv_clang" = yes; then
-    nw="$nw -Wcast-align"
     nw="$nw -Wdouble-promotion"
-    nw="$nw -Wmissing-braces"
   fi
 
-  # These cause too much noise in the MinGW build
+  # This causes too much noise in the MinGW build.
   if test $opsys = mingw32; then
-    nw="$nw -Wpointer-sign"
     nw="$nw -Wsuggest-attribute=format"
   fi
 
@@ -4607,32 +4595,6 @@ AC_SUBST(KRB5LIB)
 AC_SUBST(DESLIB)
 AC_SUBST(KRB4LIB)
 
-AC_ARG_WITH([libgmp],
-  [AS_HELP_STRING([--without-libgmp],
-                 [don't use the GNU Multiple Precision (GMP) library;
-                  this is the default on systems lacking libgmp.])])
-GMP_LIB=
-GMP_OBJ=mini-gmp-emacs.o
-HAVE_GMP=no
-case $with_libgmp in
-  no) ;;
-  yes) HAVE_GMP=yes GMP_LIB=-lgmp;;
-  *) AC_CHECK_HEADERS([gmp.h],
-       [OLIBS=$LIBS
-       AC_SEARCH_LIBS([__gmpz_roinit_n], [gmp])
-       LIBS=$OLIBS
-       case $ac_cv_search___gmpz_roinit_n in
-         'none needed') HAVE_GMP=yes;;
-         -*) HAVE_GMP=yes GMP_LIB=$ac_cv_search___gmpz_roinit_n;;
-       esac]);;
-esac
-if test "$HAVE_GMP" = yes; then
-  GMP_OBJ=
-  AC_DEFINE([HAVE_GMP], 1, [Define to 1 if you have recent-enough GMP.])
-fi
-AC_SUBST([GMP_LIB])
-AC_SUBST([GMP_OBJ])
-
 AC_CHECK_HEADERS(valgrind/valgrind.h)
 
 AC_CHECK_MEMBERS([struct unipair.unicode], [], [], [[#include <linux/kd.h>]])
@@ -5800,6 +5762,11 @@ done
 AC_DEFINE_UNQUOTED(EMACS_CONFIG_FEATURES, "${emacs_config_features}",
   [Summary of some of the main features enabled by configure.])
 
+if test -z "$GMP_H"; then
+  HAVE_GMP=yes
+else
+  HAVE_GMP=no
+fi
 AS_ECHO(["  Does Emacs use -lXaw3d?                                 
${HAVE_XAW3D}
   Does Emacs use -lXpm?                                   ${HAVE_XPM}
   Does Emacs use -ljpeg?                                  ${HAVE_JPEG}
@@ -5828,7 +5795,7 @@ AS_ECHO(["  Does Emacs use -lXaw3d?                       
          ${HAVE_XAW3D
   Does Emacs use -lxft?                                   ${HAVE_XFT}
   Does Emacs use -lsystemd?                               ${HAVE_LIBSYSTEMD}
   Does Emacs use -ljansson?                               ${HAVE_JSON}
-  Does Emacs use -lgmp?                                   ${HAVE_GMP}
+  Does Emacs use the GMP library?                         ${HAVE_GMP}
   Does Emacs directly use zlib?                           ${HAVE_ZLIB}
   Does Emacs have dynamic modules support?                ${HAVE_MODULES}
   Does Emacs use toolkit scroll bars?                     
${USE_TOOLKIT_SCROLL_BARS}
diff --git a/doc/emacs/custom.texi b/doc/emacs/custom.texi
index d034a78..719e09e 100644
--- a/doc/emacs/custom.texi
+++ b/doc/emacs/custom.texi
@@ -1223,7 +1223,7 @@ other context has no special meaning.
 disable a minor mode in a local variables list, use the @code{eval}
 keyword with a Lisp expression that runs the mode command
 (@pxref{Minor Modes}).  For example, the following local variables
-list enables Eldoc mode (@pxref{Lisp Doc}) by calling
+list enables ElDoc mode (@pxref{Lisp Doc}) by calling
 @code{eldoc-mode} with no argument (calling it with an argument of 1
 would do the same), and disables Font Lock mode (@pxref{Font Lock}) by
 calling @code{font-lock-mode} with an argument of @minus{}1.
diff --git a/doc/emacs/modes.texi b/doc/emacs/modes.texi
index c1420ea..c9c175d 100644
--- a/doc/emacs/modes.texi
+++ b/doc/emacs/modes.texi
@@ -126,7 +126,7 @@ see which mode is actually being entered.
   Mode hooks are commonly used to enable minor modes (@pxref{Minor
 Modes}).  For example, you can put the following lines in your init
 file to enable Flyspell minor mode in all text-based major modes
-(@pxref{Spelling}), and Eldoc minor mode in Emacs Lisp mode
+(@pxref{Spelling}), and ElDoc minor mode in Emacs Lisp mode
 (@pxref{Lisp Doc}):
 
 @example
diff --git a/doc/emacs/mule.texi b/doc/emacs/mule.texi
index 373c7b5..0f07d28 100644
--- a/doc/emacs/mule.texi
+++ b/doc/emacs/mule.texi
@@ -192,7 +192,7 @@ What keys to type to input the character in the current 
input method
 
 @item
 The character's encodings, both internally in the buffer, and externally
-if you were to save the file.
+if you were to save the buffer to a file.
 
 @item
 If you are running Emacs on a graphical display, the font name and
@@ -200,6 +200,12 @@ glyph code for the character.  If you are running Emacs on 
a text
 terminal, the code(s) sent to the terminal.
 
 @item
+If the character was composed on display with any following characters
+to form one or more grapheme clusters, the composition information:
+the font glyphs if the frame is on a graphical display, else the
+characters that were composed.
+
+@item
 The character's text properties (@pxref{Text Properties,,,
 elisp, the Emacs Lisp Reference Manual}), including any non-default
 faces used to display the character, and any overlays containing it
diff --git a/doc/emacs/programs.texi b/doc/emacs/programs.texi
index 2757c84..1c33d7d 100644
--- a/doc/emacs/programs.texi
+++ b/doc/emacs/programs.texi
@@ -1260,16 +1260,16 @@ the WoMan Info manual, which is distributed with Emacs.
 to view the built-in documentation for the Lisp functions and
 variables that you want to use.  @xref{Name Help}.
 
-@cindex Eldoc mode
+@cindex ElDoc mode
 @findex eldoc-mode
 @findex global-eldoc-mode
-  Eldoc is a buffer-local minor mode that helps with looking up Lisp
+  ElDoc is a buffer-local minor mode that helps with looking up Lisp
 documentation.  When it is enabled, the echo area displays some useful
 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 whose
+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 whose
 major mode sets the variables described below.  Use @w{@kbd{M-x
 global-eldoc-mode}} to turn it off globally.
 
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index d7aab4a..25eabd6 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -4275,9 +4275,15 @@ a display specification has the form
 @var{fringe} is either the symbol @code{left-fringe} or
 @code{right-fringe}.  @var{bitmap} is a symbol identifying the bitmap
 to display.  The optional @var{face} names a face whose foreground and
-background colors are to be used to display the bitmap; this face is
-automatically merged with the @code{fringe} face.  If @var{face} is
-omitted, that means to use the @code{default} face.
+background colors are to be used to display the bitmap, using the
+attributes of the @code{fringe} face for colors that @var{face} didn't
+specify.  If @var{face} is omitted, that means to use the attributes
+of the @code{default} face for the colors which the @code{fringe} face
+didn't specify.  For predictable results that don't depend on the
+attributes of the @code{default} and @code{fringe} faces, we recommend
+you never omit @var{face}, but always provide a specific face.  In
+particular, if you want the bitmap to be always displayed in the
+@code{fringe} face, use @code{fringe} as @var{face}.
 
   For instance, to display an arrow in the left fringe, using the
 @code{warning} face, you could say something like:
diff --git a/doc/lispref/numbers.texi b/doc/lispref/numbers.texi
index 4002b36..f018ef4 100644
--- a/doc/lispref/numbers.texi
+++ b/doc/lispref/numbers.texi
@@ -227,6 +227,9 @@ you are using.  On all computers supported by Emacs, this is
 and is discussed further in David Goldberg's paper
 ``@url{https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html,
 What Every Computer Scientist Should Know About Floating-Point Arithmetic}''.
+On modern platforms, floating-point operations follow the IEEE-754
+standard closely; however, results are not always rounded correctly on
+some obsolescent platforms, notably 32-bit x86.
 
   The read syntax for floating-point numbers requires either a decimal
 point, an exponent, or both.  Optional signs (@samp{+} or @samp{-})
diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi
index 2ef88b9..8de6255 100644
--- a/doc/lispref/strings.texi
+++ b/doc/lispref/strings.texi
@@ -248,7 +248,7 @@ properties removed.
 @defun concat &rest sequences
 @cindex copying strings
 @cindex concatenating strings
-This function returns a new string consisting of the characters in the
+This function returns a string consisting of the characters in the
 arguments passed to it (along with their text properties, if any).  The
 arguments may be strings, lists of numbers, or vectors of numbers; they
 are not themselves changed.  If @code{concat} receives no arguments, it
@@ -269,9 +269,14 @@ returns an empty string.
 @end example
 
 @noindent
-This function always constructs a new string that is not @code{eq} to
-any existing string, except when the result is the empty string (to
-save space, Emacs makes only one empty multibyte string).
+This function does not always allocate a new string.  Callers are
+advised not rely on the result being a new string nor on it being
+@code{eq} to an existing string.
+
+In particular, mutating the returned value may inadvertently change
+another string, alter a constant string in the program, or even raise
+an error.  To obtain a string that you can safely mutate, use
+@code{copy-sequence} on the result.
 
 For information about other concatenation functions, see the
 description of @code{mapconcat} in @ref{Mapping Functions},
diff --git a/doc/misc/eudc.texi b/doc/misc/eudc.texi
index 701340e..4ead603 100644
--- a/doc/misc/eudc.texi
+++ b/doc/misc/eudc.texi
@@ -83,6 +83,8 @@ Currently supported back-ends are:
 LDAP, Lightweight Directory Access Protocol
 @item
 BBDB, Big Brother's Insidious Database
+@item
+macOS Contacts
 @end itemize
 
 The main features of the EUDC interface are:
@@ -107,6 +109,7 @@ Interface to BBDB to let you insert server records into 
your own BBDB database
 @menu
 * LDAP::                        What is LDAP ?
 * BBDB::                        What is BBDB ?
+* macOS Contacts::              What is macOS Contacts ?
 @end menu
 
 
@@ -159,6 +162,21 @@ queries on multiple servers.
 EUDC also offers a means to insert results from directory queries into
 your own local BBDB (@pxref{Creating BBDB Records})
 
+
+@node macOS Contacts
+@section macOS Contacts
+
+macOS Contacts is the rolodex-like application that ships with the
+macOS operating system@footnote{Apple have changed the names of their
+operating system and some applications over time.  macOS used to be
+called Mac OS X in the past, and the Contacts application was
+previously called Address Book.}.
+
+EUDC considers macOS Contacts as a directory server back end just like
+LDAP, though the macOS Contacts application always resides locally on
+your machine.
+
+
 @node Installation
 @chapter Installation
 
@@ -185,6 +203,7 @@ email composition buffers (@pxref{Inline Query Expansion})
 
 @menu
 * LDAP Configuration::           EUDC needs external support for LDAP
+* macOS Contacts Configuration:: Enable the macOS Contacts backend
 @end menu
 
 @node LDAP Configuration
@@ -379,6 +398,39 @@ The @command{ldapsearch} command is formatted such that it 
can be
 copied and pasted into a terminal.  Set the @command{ldapsearch} debug
 level to 5 by appending @code{-d 5} to the command line.
 
+
+@node macOS Contacts Configuration
+@section macOS Contacts Configuration
+
+macOS Contacts support is added by means of @file{eudcb-mab.el}, or
+@file{eudcb-macos-contacts.el} which are part of Emacs.
+
+To enable a macOS Contacts backend, first `require' the respective
+library to load it, and then set the `eudc-server' to localhost in
+your init file:
+@lisp
+(require 'eudcb-macos-contacts)
+(eudc-macos-contacts-set-server "localhost")
+@end lisp
+
+@file{eudcb-macos-contacts.el} uses the public scripting interfaces
+offered by the Contacts app via the macOS Open Scripting Architecture
+(OSA).  To accomplish this, @file{eudcb-macos-contacts.el} uses an
+external command line utility named osascript, which is included with
+all macOS versions since 10.0 (which was released 2001).
+@file{eudcb-macos-contacts.el} is hence recommended for all new
+configurations.
+
+@file{eudcb-mab.el} reverse engineers the format of the database file
+used by the macOS Contacts app, and accesses its contents directly.
+While this may promise some performance advantages, it comes at the
+cost of using an undocumented interface.  Hence, users of
+@file{eudcb-mab.el} are recommended to double check the compatibility
+of @file{eudcb-mab.el} before upgrading to a new version of macOS.
+@file{eudcb-mab.el} is retained for backwards compatibility with
+existing configurations, and may be removed in a future release.
+
+
 @node Usage
 @chapter Usage
 
diff --git a/doc/misc/flymake.texi b/doc/misc/flymake.texi
index 19dcb19..89d2265 100644
--- a/doc/misc/flymake.texi
+++ b/doc/misc/flymake.texi
@@ -684,7 +684,7 @@ Binding,,, elisp, The Emacs Lisp Reference Manual}) to be 
active.
                                                         msg)
                        into diags
                        finally (funcall report-fn diags)))
-                  (flymake-log :warning "Canceling obsolete check %s"
+                  (flymake-log :warning "Cancelling obsolete check %s"
                                proc))
               ;; Cleanup the temporary buffer used to hold the
               ;; check's output.
diff --git a/etc/NEWS b/etc/NEWS
index 07403f2..e55f57e 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -279,6 +279,13 @@ This allows users to use (define-key eshell-mode-map ...) 
as usual.
 Some modules have their own minor mode now to account for these
 changes.
 
+** EUDC
+
++++
+*** New macOS Contacts backend.
+This backend works on newer versions of macOS and is generally
+preferred over the eudcb-mab.el backend.
+
 ** Tramp
 
 +++
diff --git a/etc/NEWS.22 b/etc/NEWS.22
index 548a73a..4df1792 100644
--- a/etc/NEWS.22
+++ b/etc/NEWS.22
@@ -5239,7 +5239,7 @@ has no effect on systems with case-insensitive file names.
 hooks.  `run-mode-hooks' does this automatically.
 
 *** Major modes can define `eldoc-documentation-function'
-locally to provide Eldoc functionality by some method appropriate to
+locally to provide ElDoc functionality by some method appropriate to
 the language.
 
 *** Use the new function `run-mode-hooks' to run the major mode's mode hook.
diff --git a/etc/NEWS.23 b/etc/NEWS.23
index 9a49a7d..331ed28 100644
--- a/etc/NEWS.23
+++ b/etc/NEWS.23
@@ -1779,7 +1779,7 @@ to update it to the new VC.
 If `default-directory' is a remote file name, subprocesses are started
 on the corresponding remote system.
 
-*** Eldoc highlights the function argument under point
+*** ElDoc highlights the function argument under point
 with the face `eldoc-highlight-function-argument'.
 
 *** In Etags, the --members option is now the default.
diff --git a/lib/alloca.in.h b/lib/alloca.in.h
index c7187e6..5686b08 100644
--- a/lib/alloca.in.h
+++ b/lib/alloca.in.h
@@ -35,13 +35,16 @@
  */
 
 #ifndef alloca
+  /* Some version of mingw have an <alloca.h> that causes trouble when
+     included after 'alloca' gets defined as a macro.  As a workaround,
+     include this <alloca.h> first and define 'alloca' as a macro afterwards
+     if needed.  */
+# if defined __GNUC__ && (defined _WIN32 && ! defined __CYGWIN__) && 
@HAVE_ALLOCA_H@
+#  include_next <alloca.h>
+# endif
+#endif
+#ifndef alloca
 # ifdef __GNUC__
-   /* Some version of mingw have an <alloca.h> that causes trouble when
-      included after 'alloca' gets defined as a macro.  As a workaround, 
include
-      this <alloca.h> first and define 'alloca' as a macro afterwards.  */
-#  if (defined _WIN32 && ! defined __CYGWIN__) && @HAVE_ALLOCA_H@
-#   include_next <alloca.h>
-#  endif
 #  define alloca __builtin_alloca
 # elif defined _AIX
 #  define alloca __alloca
diff --git a/lib/dup2.c b/lib/dup2.c
index 88ef259..9bc3951 100644
--- a/lib/dup2.c
+++ b/lib/dup2.c
@@ -25,28 +25,26 @@
 #include <errno.h>
 #include <fcntl.h>
 
-#if HAVE_DUP2
+#undef dup2
 
-# undef dup2
-
-# if defined _WIN32 && ! defined __CYGWIN__
+#if defined _WIN32 && ! defined __CYGWIN__
 
 /* Get declarations of the native Windows API functions.  */
-#  define WIN32_LEAN_AND_MEAN
-#  include <windows.h>
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
 
-#  if HAVE_MSVC_INVALID_PARAMETER_HANDLER
-#   include "msvc-inval.h"
-#  endif
+# if HAVE_MSVC_INVALID_PARAMETER_HANDLER
+#  include "msvc-inval.h"
+# endif
 
 /* Get _get_osfhandle.  */
-#  if GNULIB_MSVC_NOTHROW
-#   include "msvc-nothrow.h"
-#  else
-#   include <io.h>
-#  endif
+# if GNULIB_MSVC_NOTHROW
+#  include "msvc-nothrow.h"
+# else
+#  include <io.h>
+# endif
 
-#  if HAVE_MSVC_INVALID_PARAMETER_HANDLER
+# if HAVE_MSVC_INVALID_PARAMETER_HANDLER
 static int
 dup2_nothrow (int fd, int desired_fd)
 {
@@ -65,9 +63,9 @@ dup2_nothrow (int fd, int desired_fd)
 
   return result;
 }
-#  else
-#   define dup2_nothrow dup2
-#  endif
+# else
+#  define dup2_nothrow dup2
+# endif
 
 static int
 ms_windows_dup2 (int fd, int desired_fd)
@@ -103,11 +101,11 @@ ms_windows_dup2 (int fd, int desired_fd)
   return result;
 }
 
-#  define dup2 ms_windows_dup2
+# define dup2 ms_windows_dup2
 
-# elif defined __KLIBC__
+#elif defined __KLIBC__
 
-#  include <InnoTekLIBC/backend.h>
+# include <InnoTekLIBC/backend.h>
 
 static int
 klibc_dup2dirfd (int fd, int desired_fd)
@@ -155,81 +153,37 @@ klibc_dup2 (int fd, int desired_fd)
   return dupfd;
 }
 
-#  define dup2 klibc_dup2
-# endif
+# define dup2 klibc_dup2
+#endif
 
 int
 rpl_dup2 (int fd, int desired_fd)
 {
   int result;
 
-# ifdef F_GETFL
+#ifdef F_GETFL
   /* On Linux kernels 2.6.26-2.6.29, dup2 (fd, fd) returns -EBADF.
      On Cygwin 1.5.x, dup2 (1, 1) returns 0.
      On Cygwin 1.7.17, dup2 (1, -1) dumps core.
      On Cygwin 1.7.25, dup2 (1, 256) can dump core.
      On Haiku, dup2 (fd, fd) mistakenly clears FD_CLOEXEC.  */
-#  if HAVE_SETDTABLESIZE
+# if HAVE_SETDTABLESIZE
   setdtablesize (desired_fd + 1);
-#  endif
+# endif
   if (desired_fd < 0)
     fd = desired_fd;
   if (fd == desired_fd)
     return fcntl (fd, F_GETFL) == -1 ? -1 : fd;
-# endif
+#endif
 
   result = dup2 (fd, desired_fd);
 
   /* Correct an errno value on FreeBSD 6.1 and Cygwin 1.5.x.  */
   if (result == -1 && errno == EMFILE)
     errno = EBADF;
-# if REPLACE_FCHDIR
+#if REPLACE_FCHDIR
   if (fd != desired_fd && result != -1)
     result = _gl_register_dup (fd, result);
-# endif
-  return result;
-}
-
-#else /* !HAVE_DUP2 */
-
-/* On older platforms, dup2 did not exist.  */
-
-# ifndef F_DUPFD
-static int
-dupfd (int fd, int desired_fd)
-{
-  int duplicated_fd = dup (fd);
-  if (duplicated_fd < 0 || duplicated_fd == desired_fd)
-    return duplicated_fd;
-  else
-    {
-      int r = dupfd (fd, desired_fd);
-      int e = errno;
-      close (duplicated_fd);
-      errno = e;
-      return r;
-    }
-}
-# endif
-
-int
-dup2 (int fd, int desired_fd)
-{
-  int result = fcntl (fd, F_GETFL) < 0 ? -1 : fd;
-  if (result == -1 || fd == desired_fd)
-    return result;
-  close (desired_fd);
-# ifdef F_DUPFD
-  result = fcntl (fd, F_DUPFD, desired_fd);
-#  if REPLACE_FCHDIR
-  if (0 <= result)
-    result = _gl_register_dup (fd, result);
-#  endif
-# else
-  result = dupfd (fd, desired_fd);
-# endif
-  if (result == -1 && (errno == EMFILE || errno == EINVAL))
-    errno = EBADF;
+#endif
   return result;
 }
-#endif /* !HAVE_DUP2 */
diff --git a/lib/getrandom.c b/lib/getrandom.c
index 030a78b..f8695ab 100644
--- a/lib/getrandom.c
+++ b/lib/getrandom.c
@@ -32,7 +32,7 @@
 # if HAVE_BCRYPT_H
 #  include <bcrypt.h>
 # else
-#  include <ntdef.h> /* NTSTATUS */
+#  define NTSTATUS LONG
 typedef void * BCRYPT_ALG_HANDLE;
 #  define BCRYPT_USE_SYSTEM_PREFERRED_RNG 0x00000002
 #  if HAVE_LIB_BCRYPT
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in
index 35d2db0..68cae8f 100644
--- a/lib/gnulib.mk.in
+++ b/lib/gnulib.mk.in
@@ -117,6 +117,7 @@
 #  ignore-value \
 #  intprops \
 #  largefile \
+#  libgmp \
 #  lstat \
 #  manywarnings \
 #  memmem-simple \
@@ -245,14 +246,14 @@ GL_GENERATE_ALLOCA_H = @GL_GENERATE_ALLOCA_H@
 GL_GENERATE_BYTESWAP_H = @GL_GENERATE_BYTESWAP_H@
 GL_GENERATE_ERRNO_H = @GL_GENERATE_ERRNO_H@
 GL_GENERATE_EXECINFO_H = @GL_GENERATE_EXECINFO_H@
+GL_GENERATE_GMP_H = @GL_GENERATE_GMP_H@
 GL_GENERATE_IEEE754_H = @GL_GENERATE_IEEE754_H@
 GL_GENERATE_LIMITS_H = @GL_GENERATE_LIMITS_H@
 GL_GENERATE_STDALIGN_H = @GL_GENERATE_STDALIGN_H@
 GL_GENERATE_STDDEF_H = @GL_GENERATE_STDDEF_H@
 GL_GENERATE_STDINT_H = @GL_GENERATE_STDINT_H@
 GMALLOC_OBJ = @GMALLOC_OBJ@
-GMP_LIB = @GMP_LIB@
-GMP_OBJ = @GMP_OBJ@
+GMP_H = @GMP_H@
 GNULIB_ACCESS = @GNULIB_ACCESS@
 GNULIB_ALPHASORT = @GNULIB_ALPHASORT@
 GNULIB_ATOLL = @GNULIB_ATOLL@
@@ -325,6 +326,7 @@ GNULIB_GETPASS = @GNULIB_GETPASS@
 GNULIB_GETRANDOM = @GNULIB_GETRANDOM@
 GNULIB_GETSUBOPT = @GNULIB_GETSUBOPT@
 GNULIB_GETTIMEOFDAY = @GNULIB_GETTIMEOFDAY@
+GNULIB_GETUMASK = @GNULIB_GETUMASK@
 GNULIB_GETUSERSHELL = @GNULIB_GETUSERSHELL@
 GNULIB_GL_UNISTD_H_GETOPT = @GNULIB_GL_UNISTD_H_GETOPT@
 GNULIB_GRANTPT = @GNULIB_GRANTPT@
@@ -548,7 +550,6 @@ HAVE_DECL_UNSETENV = @HAVE_DECL_UNSETENV@
 HAVE_DECL_VSNPRINTF = @HAVE_DECL_VSNPRINTF@
 HAVE_DIRENT_H = @HAVE_DIRENT_H@
 HAVE_DPRINTF = @HAVE_DPRINTF@
-HAVE_DUP2 = @HAVE_DUP2@
 HAVE_DUP3 = @HAVE_DUP3@
 HAVE_EUIDACCESS = @HAVE_EUIDACCESS@
 HAVE_EXPLICIT_BZERO = @HAVE_EXPLICIT_BZERO@
@@ -578,6 +579,7 @@ HAVE_GETPASS = @HAVE_GETPASS@
 HAVE_GETRANDOM = @HAVE_GETRANDOM@
 HAVE_GETSUBOPT = @HAVE_GETSUBOPT@
 HAVE_GETTIMEOFDAY = @HAVE_GETTIMEOFDAY@
+HAVE_GETUMASK = @HAVE_GETUMASK@
 HAVE_GRANTPT = @HAVE_GRANTPT@
 HAVE_GROUP_MEMBER = @HAVE_GROUP_MEMBER@
 HAVE_IMAXDIV_T = @HAVE_IMAXDIV_T@
@@ -592,7 +594,6 @@ HAVE_MAKEINFO = @HAVE_MAKEINFO@
 HAVE_MAX_ALIGN_T = @HAVE_MAX_ALIGN_T@
 HAVE_MBSLEN = @HAVE_MBSLEN@
 HAVE_MBTOWC = @HAVE_MBTOWC@
-HAVE_MEMCHR = @HAVE_MEMCHR@
 HAVE_MEMPCPY = @HAVE_MEMPCPY@
 HAVE_MKDIRAT = @HAVE_MKDIRAT@
 HAVE_MKDTEMP = @HAVE_MKDTEMP@
@@ -760,6 +761,7 @@ LIB_CLOCK_GETTIME = @LIB_CLOCK_GETTIME@
 LIB_EACCESS = @LIB_EACCESS@
 LIB_EXECINFO = @LIB_EXECINFO@
 LIB_GETRANDOM = @LIB_GETRANDOM@
+LIB_GMP = @LIB_GMP@
 LIB_MATH = @LIB_MATH@
 LIB_PTHREAD = @LIB_PTHREAD@
 LIB_PTHREAD_SIGMASK = @LIB_PTHREAD_SIGMASK@
@@ -1132,7 +1134,6 @@ pdfdir = @pdfdir@
 prefix = @prefix@
 program_transform_name = @program_transform_name@
 psdir = @psdir@
-runstatedir = @runstatedir@
 sbindir = @sbindir@
 sharedstatedir = @sharedstatedir@
 srcdir = @srcdir@
@@ -2015,6 +2016,29 @@ EXTRA_DIST += cdefs.h libc-config.h
 endif
 ## end   gnulib module libc-config
 
+## begin gnulib module libgmp
+ifeq (,$(OMIT_GNULIB_MODULE_libgmp))
+
+BUILT_SOURCES += $(GMP_H)
+
+# Build gmp.h as a wrapper for mini-gmp.h when using mini-gmp.
+ifneq (,$(GL_GENERATE_GMP_H))
+gmp.h: $(top_builddir)/config.status
+       echo '#include "mini-gmp.h"' >$@-t
+       mv $@-t $@
+else
+gmp.h: $(top_builddir)/config.status
+       rm -f $@
+endif
+MOSTLYCLEANFILES += gmp.h gmp.h-t
+
+EXTRA_DIST += mini-gmp-gnulib.c mini-gmp.c mini-gmp.h
+
+EXTRA_libgnu_a_SOURCES += mini-gmp-gnulib.c mini-gmp.c
+
+endif
+## end   gnulib module libgmp
+
 ## begin gnulib module limits-h
 ifeq (,$(OMIT_GNULIB_MODULE_limits-h))
 
@@ -2833,7 +2857,6 @@ string.h: string.in.h $(top_builddir)/config.status 
$(CXXDEFS_H) $(ARG_NONNULL_H
              -e 's|@''HAVE_FFSL''@|$(HAVE_FFSL)|g' \
              -e 's|@''HAVE_FFSLL''@|$(HAVE_FFSLL)|g' \
              -e 's|@''HAVE_MBSLEN''@|$(HAVE_MBSLEN)|g' \
-             -e 's|@''HAVE_MEMCHR''@|$(HAVE_MEMCHR)|g' \
              -e 's|@''HAVE_DECL_MEMMEM''@|$(HAVE_DECL_MEMMEM)|g' \
              -e 's|@''HAVE_MEMPCPY''@|$(HAVE_MEMPCPY)|g' \
              -e 's|@''HAVE_DECL_MEMRCHR''@|$(HAVE_DECL_MEMRCHR)|g' \
@@ -3017,6 +3040,7 @@ sys/stat.h: sys_stat.in.h $(top_builddir)/config.status 
$(CXXDEFS_H) $(ARG_NONNU
              -e 's/@''GNULIB_FSTAT''@/$(GNULIB_FSTAT)/g' \
              -e 's/@''GNULIB_FSTATAT''@/$(GNULIB_FSTATAT)/g' \
              -e 's/@''GNULIB_FUTIMENS''@/$(GNULIB_FUTIMENS)/g' \
+             -e 's/@''GNULIB_GETUMASK''@/$(GNULIB_GETUMASK)/g' \
              -e 's/@''GNULIB_LCHMOD''@/$(GNULIB_LCHMOD)/g' \
              -e 's/@''GNULIB_LSTAT''@/$(GNULIB_LSTAT)/g' \
              -e 's/@''GNULIB_MKDIRAT''@/$(GNULIB_MKDIRAT)/g' \
@@ -3030,6 +3054,7 @@ sys/stat.h: sys_stat.in.h $(top_builddir)/config.status 
$(CXXDEFS_H) $(ARG_NONNU
              -e 's|@''HAVE_FCHMODAT''@|$(HAVE_FCHMODAT)|g' \
              -e 's|@''HAVE_FSTATAT''@|$(HAVE_FSTATAT)|g' \
              -e 's|@''HAVE_FUTIMENS''@|$(HAVE_FUTIMENS)|g' \
+             -e 's|@''HAVE_GETUMASK''@|$(HAVE_GETUMASK)|g' \
              -e 's|@''HAVE_LCHMOD''@|$(HAVE_LCHMOD)|g' \
              -e 's|@''HAVE_LSTAT''@|$(HAVE_LSTAT)|g' \
              -e 's|@''HAVE_MKDIRAT''@|$(HAVE_MKDIRAT)|g' \
@@ -3338,7 +3363,6 @@ unistd.h: unistd.in.h $(top_builddir)/config.status 
$(CXXDEFS_H) $(ARG_NONNULL_H
              < $(srcdir)/unistd.in.h | \
          sed -e 's|@''HAVE_CHOWN''@|$(HAVE_CHOWN)|g' \
              -e 's|@''HAVE_COPY_FILE_RANGE''@|$(HAVE_COPY_FILE_RANGE)|g' \
-             -e 's|@''HAVE_DUP2''@|$(HAVE_DUP2)|g' \
              -e 's|@''HAVE_DUP3''@|$(HAVE_DUP3)|g' \
              -e 's|@''HAVE_EUIDACCESS''@|$(HAVE_EUIDACCESS)|g' \
              -e 's|@''HAVE_FACCESSAT''@|$(HAVE_FACCESSAT)|g' \
diff --git a/lib/mini-gmp-gnulib.c b/lib/mini-gmp-gnulib.c
new file mode 100644
index 0000000..5019be5
--- /dev/null
+++ b/lib/mini-gmp-gnulib.c
@@ -0,0 +1,37 @@
+/* Tailor mini-gmp.c for Gnulib-using applications.
+
+   Copyright 2018-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/>.  */
+
+#include <config.h>
+
+#include <stddef.h>
+#include <stdio.h>
+
+#include "mini-gmp.h"
+
+/* Pacify GCC -Wsuggest-attribute=const, malloc, pure.  */
+#if 4 < __GNUC__ + (6 <= __GNUC_MINOR__)
+# pragma GCC diagnostic ignored "-Wsuggest-attribute=const"
+# pragma GCC diagnostic ignored "-Wsuggest-attribute=malloc"
+# pragma GCC diagnostic ignored "-Wsuggest-attribute=pure"
+#endif
+
+/* Pacify GCC -Wunused-variable for variables used only in 'assert' calls.  */
+#if defined NDEBUG && 4 < __GNUC__ + (6 <= __GNUC_MINOR__)
+# pragma GCC diagnostic ignored "-Wunused-variable"
+#endif
+
+#include "mini-gmp.c"
diff --git a/src/mini-gmp.c b/lib/mini-gmp.c
similarity index 97%
rename from src/mini-gmp.c
rename to lib/mini-gmp.c
index 2e789a2..2e0301b 100644
--- a/src/mini-gmp.c
+++ b/lib/mini-gmp.c
@@ -2,21 +2,21 @@
 
    Contributed to the GNU project by Niels Möller
 
-Copyright 1991-1997, 1999-2019 Free Software Foundation, Inc.
+Copyright 1991-1997, 1999-2020 Free Software Foundation, Inc.
 
 This file is part of the GNU MP Library.
 
 The GNU MP Library is free software; you can redistribute it and/or modify
 it under the terms of either:
 
-  * the GNU Lesser General Public License as published by the Free
+  * 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.
 
 or
 
   * the GNU General Public License as published by the Free Software
-    Foundation; either version 2 of the License, or (at your option) any
+    Foundation; either version 3 of the License, or (at your option) any
     later version.
 
 or both in parallel, as here.
@@ -27,7 +27,7 @@ or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General 
Public License
 for more details.
 
 You should have received copies of the GNU General Public License and the
-GNU Lesser General Public License along with the GNU MP Library.  If not,
+GNU General Public License along with the GNU MP Library.  If not,
 see https://www.gnu.org/licenses/.  */
 
 /* NOTE: All functions in this file which are not declared in
@@ -351,20 +351,27 @@ mp_set_memory_functions (void *(*alloc_func) (size_t),
   gmp_free_func = free_func;
 }
 
-#define gmp_xalloc(size) ((*gmp_allocate_func)((size)))
-#define gmp_free(p) ((*gmp_free_func) ((p), 0))
+#define gmp_alloc(size) ((*gmp_allocate_func)((size)))
+#define gmp_free(p, size) ((*gmp_free_func) ((p), (size)))
+#define gmp_realloc(ptr, old_size, size) ((*gmp_reallocate_func)(ptr, 
old_size, size))
 
 static mp_ptr
-gmp_xalloc_limbs (mp_size_t size)
+gmp_alloc_limbs (mp_size_t size)
 {
-  return (mp_ptr) gmp_xalloc (size * sizeof (mp_limb_t));
+  return (mp_ptr) gmp_alloc (size * sizeof (mp_limb_t));
 }
 
 static mp_ptr
-gmp_xrealloc_limbs (mp_ptr old, mp_size_t size)
+gmp_realloc_limbs (mp_ptr old, mp_size_t old_size, mp_size_t size)
 {
   assert (size > 0);
-  return (mp_ptr) (*gmp_reallocate_func) (old, 0, size * sizeof (mp_limb_t));
+  return (mp_ptr) gmp_realloc (old, old_size * sizeof (mp_limb_t), size * 
sizeof (mp_limb_t));
+}
+
+static void
+gmp_free_limbs (mp_ptr old, mp_size_t size)
+{
+  gmp_free (old, size * sizeof (mp_limb_t));
 }
 
 
@@ -956,11 +963,17 @@ mpn_div_qr_1_preinv (mp_ptr qp, mp_srcptr np, mp_size_t 
nn,
   mp_limb_t d, di;
   mp_limb_t r;
   mp_ptr tp = NULL;
+  mp_size_t tn = 0;
 
   if (inv->shift > 0)
     {
       /* Shift, reusing qp area if possible. In-place shift if qp == np. */
-      tp = qp ? qp : gmp_xalloc_limbs (nn);
+      tp = qp;
+      if (!tp)
+        {
+          tn = nn;
+          tp = gmp_alloc_limbs (tn);
+        }
       r = mpn_lshift (tp, np, nn, inv->shift);
       np = tp;
     }
@@ -977,8 +990,8 @@ mpn_div_qr_1_preinv (mp_ptr qp, mp_srcptr np, mp_size_t nn,
       if (qp)
        qp[nn] = q;
     }
-  if ((inv->shift > 0) && (tp != qp))
-    gmp_free (tp);
+  if (tn)
+    gmp_free_limbs (tp, tn);
 
   return r >> inv->shift;
 }
@@ -1136,13 +1149,13 @@ mpn_div_qr (mp_ptr qp, mp_ptr np, mp_size_t nn, 
mp_srcptr dp, mp_size_t dn)
   mpn_div_qr_invert (&inv, dp, dn);
   if (dn > 2 && inv.shift > 0)
     {
-      tp = gmp_xalloc_limbs (dn);
+      tp = gmp_alloc_limbs (dn);
       gmp_assert_nocarry (mpn_lshift (tp, dp, dn, inv.shift));
       dp = tp;
     }
   mpn_div_qr_preinv (qp, np, nn, dp, dn, &inv);
   if (tp)
-    gmp_free (tp);
+    gmp_free_limbs (tp, dn);
 }
 
 
@@ -1428,14 +1441,14 @@ mpz_init2 (mpz_t r, mp_bitcnt_t bits)
 
   r->_mp_alloc = rn;
   r->_mp_size = 0;
-  r->_mp_d = gmp_xalloc_limbs (rn);
+  r->_mp_d = gmp_alloc_limbs (rn);
 }
 
 void
 mpz_clear (mpz_t r)
 {
   if (r->_mp_alloc)
-    gmp_free (r->_mp_d);
+    gmp_free_limbs (r->_mp_d, r->_mp_alloc);
 }
 
 static mp_ptr
@@ -1444,9 +1457,9 @@ mpz_realloc (mpz_t r, mp_size_t size)
   size = GMP_MAX (size, 1);
 
   if (r->_mp_alloc)
-    r->_mp_d = gmp_xrealloc_limbs (r->_mp_d, size);
+    r->_mp_d = gmp_realloc_limbs (r->_mp_d, r->_mp_alloc, size);
   else
-    r->_mp_d = gmp_xalloc_limbs (size);
+    r->_mp_d = gmp_alloc_limbs (size);
   r->_mp_alloc = size;
 
   if (GMP_ABS (r->_mp_size) > size)
@@ -1541,8 +1554,7 @@ mpz_init_set (mpz_t r, const mpz_t x)
 int
 mpz_fits_slong_p (const mpz_t u)
 {
-  return (LONG_MAX + LONG_MIN == 0 || mpz_cmp_ui (u, LONG_MAX) <= 0) &&
-    mpz_cmpabs_ui (u, GMP_NEG_CAST (unsigned long int, LONG_MIN)) <= 0;
+  return mpz_cmp_si (u, LONG_MAX) <= 0 && mpz_cmp_si (u, LONG_MIN) >= 0;
 }
 
 static int
@@ -1565,6 +1577,30 @@ mpz_fits_ulong_p (const mpz_t u)
   return us >= 0 && mpn_absfits_ulong_p (u->_mp_d, us);
 }
 
+int
+mpz_fits_sint_p (const mpz_t u)
+{
+  return mpz_cmp_si (u, INT_MAX) <= 0 && mpz_cmp_si (u, INT_MIN) >= 0;
+}
+
+int
+mpz_fits_uint_p (const mpz_t u)
+{
+  return u->_mp_size >= 0 && mpz_cmpabs_ui (u, UINT_MAX) <= 0;
+}
+
+int
+mpz_fits_sshort_p (const mpz_t u)
+{
+  return mpz_cmp_si (u, SHRT_MAX) <= 0 && mpz_cmp_si (u, SHRT_MIN) >= 0;
+}
+
+int
+mpz_fits_ushort_p (const mpz_t u)
+{
+  return u->_mp_size >= 0 && mpz_cmpabs_ui (u, USHRT_MAX) <= 0;
+}
+
 long int
 mpz_get_si (const mpz_t u)
 {
@@ -3073,7 +3109,7 @@ mpz_powm (mpz_t r, const mpz_t b, const mpz_t e, const 
mpz_t m)
         one, using a *normalized* m. */
       minv.shift = 0;
 
-      tp = gmp_xalloc_limbs (mn);
+      tp = gmp_alloc_limbs (mn);
       gmp_assert_nocarry (mpn_lshift (tp, mp, mn, shift));
       mp = tp;
     }
@@ -3139,7 +3175,7 @@ mpz_powm (mpz_t r, const mpz_t b, const mpz_t e, const 
mpz_t m)
       tr->_mp_size = mpn_normalized_size (tr->_mp_d, mn);
     }
   if (tp)
-    gmp_free (tp);
+    gmp_free_limbs (tp, mn);
 
   mpz_swap (r, tr);
   mpz_clear (tr);
@@ -3350,13 +3386,15 @@ gmp_jacobi_coprime (mp_limb_t a, mp_limb_t b)
   gmp_ctz(c, a);
   a >>= 1;
 
-  do
+  for (;;)
     {
       a >>= c;
       /* (2/b) = -1 if b = 3 or 5 mod 8 */
       bit ^= c & (b ^ (b >> 1));
       if (a < b)
        {
+         if (a == 0)
+           return bit & 1 ? -1 : 1;
          bit ^= a & b;
          a = b - a;
          b -= a;
@@ -3370,9 +3408,6 @@ gmp_jacobi_coprime (mp_limb_t a, mp_limb_t b)
       gmp_ctz(c, a);
       ++c;
     }
-  while (b > 0);
-
-  return bit & 1 ? -1 : 1;
 }
 
 static void
@@ -4144,7 +4179,7 @@ mpz_scan0 (const mpz_t u, mp_bitcnt_t starting_bit)
 size_t
 mpz_sizeinbase (const mpz_t u, int base)
 {
-  mp_size_t un;
+  mp_size_t un, tn;
   mp_srcptr up;
   mp_ptr tp;
   mp_bitcnt_t bits;
@@ -4177,20 +4212,21 @@ mpz_sizeinbase (const mpz_t u, int base)
         10. */
     }
 
-  tp = gmp_xalloc_limbs (un);
+  tp = gmp_alloc_limbs (un);
   mpn_copyi (tp, up, un);
   mpn_div_qr_1_invert (&bi, base);
 
+  tn = un;
   ndigits = 0;
   do
     {
       ndigits++;
-      mpn_div_qr_1_preinv (tp, tp, un, &bi);
-      un -= (tp[un-1] == 0);
+      mpn_div_qr_1_preinv (tp, tp, tn, &bi);
+      tn -= (tp[tn-1] == 0);
     }
-  while (un > 0);
+  while (tn > 0);
 
-  gmp_free (tp);
+  gmp_free_limbs (tp, un);
   return ndigits;
 }
 
@@ -4200,7 +4236,7 @@ mpz_get_str (char *sp, int base, const mpz_t u)
   unsigned bits;
   const char *digits;
   mp_size_t un;
-  size_t i, sn;
+  size_t i, sn, osn;
 
   digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
   if (base > 1)
@@ -4221,15 +4257,19 @@ mpz_get_str (char *sp, int base, const mpz_t u)
 
   sn = 1 + mpz_sizeinbase (u, base);
   if (!sp)
-    sp = (char *) gmp_xalloc (1 + sn);
-
+    {
+      osn = 1 + sn;
+      sp = (char *) gmp_alloc (osn);
+    }
+  else
+    osn = 0;
   un = GMP_ABS (u->_mp_size);
 
   if (un == 0)
     {
       sp[0] = '0';
-      sp[1] = '\0';
-      return sp;
+      sn = 1;
+      goto ret;
     }
 
   i = 0;
@@ -4248,17 +4288,20 @@ mpz_get_str (char *sp, int base, const mpz_t u)
       mp_ptr tp;
 
       mpn_get_base_info (&info, base);
-      tp = gmp_xalloc_limbs (un);
+      tp = gmp_alloc_limbs (un);
       mpn_copyi (tp, u->_mp_d, un);
 
       sn = i + mpn_get_str_other ((unsigned char *) sp + i, base, &info, tp, 
un);
-      gmp_free (tp);
+      gmp_free_limbs (tp, un);
     }
 
   for (; i < sn; i++)
     sp[i] = digits[(unsigned char) sp[i]];
 
+ret:
   sp[sn] = '\0';
+  if (osn && osn != sn + 1)
+    sp = gmp_realloc(sp, osn, sn + 1);
   return sp;
 }
 
@@ -4268,7 +4311,7 @@ mpz_set_str (mpz_t r, const char *sp, int base)
   unsigned bits, value_of_a;
   mp_size_t rn, alloc;
   mp_ptr rp;
-  size_t dn;
+  size_t dn, sn;
   int sign;
   unsigned char *dp;
 
@@ -4306,7 +4349,8 @@ mpz_set_str (mpz_t r, const char *sp, int base)
       r->_mp_size = 0;
       return -1;
     }
-  dp = (unsigned char *) gmp_xalloc (strlen (sp));
+  sn = strlen(sp);
+  dp = (unsigned char *) gmp_alloc (sn);
 
   value_of_a = (base > 36) ? 36 : 10;
   for (dn = 0; *sp; sp++)
@@ -4326,7 +4370,7 @@ mpz_set_str (mpz_t r, const char *sp, int base)
 
       if (digit >= (unsigned) base)
        {
-         gmp_free (dp);
+         gmp_free (dp, sn);
          r->_mp_size = 0;
          return -1;
        }
@@ -4336,7 +4380,7 @@ mpz_set_str (mpz_t r, const char *sp, int base)
 
   if (!dn)
     {
-      gmp_free (dp);
+      gmp_free (dp, sn);
       r->_mp_size = 0;
       return -1;
     }
@@ -4360,7 +4404,7 @@ mpz_set_str (mpz_t r, const char *sp, int base)
       rn -= rp[rn-1] == 0;
     }
   assert (rn <= alloc);
-  gmp_free (dp);
+  gmp_free (dp, sn);
 
   r->_mp_size = sign ? - rn : rn;
 
@@ -4378,13 +4422,13 @@ size_t
 mpz_out_str (FILE *stream, int base, const mpz_t x)
 {
   char *str;
-  size_t len;
+  size_t len, n;
 
   str = mpz_get_str (NULL, base, x);
   len = strlen (str);
-  len = fwrite (str, 1, len, stream);
-  gmp_free (str);
-  return len;
+  n = fwrite (str, 1, len, stream);
+  gmp_free (str, len + 1);
+  return n;
 }
 
 
@@ -4512,7 +4556,7 @@ mpz_export (void *r, size_t *countp, int order, size_t 
size, int endian,
       count = (k + (un-1) * sizeof (mp_limb_t) + size - 1) / size;
 
       if (!r)
-       r = gmp_xalloc (count * size);
+       r = gmp_alloc (count * size);
 
       if (endian == 0)
        endian = gmp_detect_endian ();
diff --git a/src/mini-gmp.h b/lib/mini-gmp.h
similarity index 97%
rename from src/mini-gmp.h
rename to lib/mini-gmp.h
index 7cce3f7..c00568c 100644
--- a/src/mini-gmp.h
+++ b/lib/mini-gmp.h
@@ -7,14 +7,14 @@ This file is part of the GNU MP Library.
 The GNU MP Library is free software; you can redistribute it and/or modify
 it under the terms of either:
 
-  * the GNU Lesser General Public License as published by the Free
+  * 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.
 
 or
 
   * the GNU General Public License as published by the Free Software
-    Foundation; either version 2 of the License, or (at your option) any
+    Foundation; either version 3 of the License, or (at your option) any
     later version.
 
 or both in parallel, as here.
@@ -25,7 +25,7 @@ or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General 
Public License
 for more details.
 
 You should have received copies of the GNU General Public License and the
-GNU Lesser General Public License along with the GNU MP Library.  If not,
+GNU General Public License along with the GNU MP Library.  If not,
 see https://www.gnu.org/licenses/.  */
 
 /* About mini-gmp: This is a minimal implementation of a subset of the
@@ -244,6 +244,10 @@ mp_bitcnt_t mpz_scan1 (const mpz_t, mp_bitcnt_t);
 
 int mpz_fits_slong_p (const mpz_t);
 int mpz_fits_ulong_p (const mpz_t);
+int mpz_fits_sint_p (const mpz_t);
+int mpz_fits_uint_p (const mpz_t);
+int mpz_fits_sshort_p (const mpz_t);
+int mpz_fits_ushort_p (const mpz_t);
 long int mpz_get_si (const mpz_t);
 unsigned long int mpz_get_ui (const mpz_t);
 double mpz_get_d (const mpz_t);
diff --git a/lib/string.in.h b/lib/string.in.h
index a08e705..aa98027 100644
--- a/lib/string.in.h
+++ b/lib/string.in.h
@@ -134,11 +134,6 @@ _GL_FUNCDECL_RPL (memchr, void *, (void const *__s, int 
__c, size_t __n)
                                   _GL_ARG_NONNULL ((1)));
 _GL_CXXALIAS_RPL (memchr, void *, (void const *__s, int __c, size_t __n));
 # else
-#  if ! @HAVE_MEMCHR@
-_GL_FUNCDECL_SYS (memchr, void *, (void const *__s, int __c, size_t __n)
-                                  _GL_ATTRIBUTE_PURE
-                                  _GL_ARG_NONNULL ((1)));
-#  endif
   /* On some systems, this function is defined as an overloaded function:
        extern "C" { const void * std::memchr (const void *, int, size_t); }
        extern "C++" { void * std::memchr (void *, int, size_t); }  */
diff --git a/lib/sys_stat.in.h b/lib/sys_stat.in.h
index 4494607..89e167f 100644
--- a/lib/sys_stat.in.h
+++ b/lib/sys_stat.in.h
@@ -515,6 +515,23 @@ _GL_WARN_ON_USE (futimens, "futimens is not portable - "
 #endif
 
 
+#if @GNULIB_GETUMASK@
+# if !@HAVE_GETUMASK@
+_GL_FUNCDECL_SYS (getumask, mode_t, (void));
+# endif
+_GL_CXXALIAS_SYS (getumask, mode_t, (void));
+# if @HAVE_GETUMASK@
+_GL_CXXALIASWARN (getumask);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# undef getumask
+# if HAVE_RAW_DECL_GETUMASK
+_GL_WARN_ON_USE (getumask, "getumask is not portable - "
+                 "use gnulib module getumask for portability");
+# endif
+#endif
+
+
 #if @GNULIB_LCHMOD@
 /* Change the mode of FILENAME to MODE, without dereferencing it if FILENAME
    denotes a symbolic link.  */
diff --git a/lib/unistd.in.h b/lib/unistd.in.h
index b211e4d..a81a14f 100644
--- a/lib/unistd.in.h
+++ b/lib/unistd.in.h
@@ -408,9 +408,6 @@ _GL_WARN_ON_USE (dup, "dup is unportable - "
 _GL_FUNCDECL_RPL (dup2, int, (int oldfd, int newfd));
 _GL_CXXALIAS_RPL (dup2, int, (int oldfd, int newfd));
 # else
-#  if !@HAVE_DUP2@
-_GL_FUNCDECL_SYS (dup2, int, (int oldfd, int newfd));
-#  endif
 _GL_CXXALIAS_SYS (dup2, int, (int oldfd, int newfd));
 # endif
 _GL_CXXALIASWARN (dup2);
diff --git a/lisp/autorevert.el b/lisp/autorevert.el
index e023c8f..6e08176 100644
--- a/lisp/autorevert.el
+++ b/lisp/autorevert.el
@@ -545,7 +545,7 @@ specifies in the mode line."
                       ;; we wouldn't know when to revert it otherwise.
                       (not (eq buffer-stale-function
                                #'buffer-stale--default-function))))
-             (not (memq 'major-mode global-auto-revert-ignore-modes))
+             (not (memq major-mode global-auto-revert-ignore-modes))
              (or (null global-auto-revert-ignore-buffer)
                  (if (functionp global-auto-revert-ignore-buffer)
                      (not (funcall global-auto-revert-ignore-buffer
diff --git a/lisp/descr-text.el b/lisp/descr-text.el
index 776ce76..4de1a7b 100644
--- a/lisp/descr-text.el
+++ b/lisp/descr-text.el
@@ -763,6 +763,8 @@ The character information includes:
                        (to (nth 4 composition))
                        glyph)
                   (if (fontp font)
+                      ;; GUI frame: show composition in terms of
+                      ;; font glyphs and characters.
                       (progn
                         (insert " using this font:\n  "
                                 (symbol-name (font-get font :type))
@@ -772,12 +774,22 @@ The character information includes:
                         (while (and (<= from to)
                                     (setq glyph (lgstring-glyph gstring from)))
                           (insert (format "  %S\n" glyph))
-                          (setq from (1+ from))))
+                          (setq from (1+ from)))
+                        (insert "from these character(s):\n")
+                        (dotimes (i (lgstring-char-len gstring))
+                          (let ((char (lgstring-char gstring i)))
+                            (insert (format "  %c (#x%x) %s\n"
+                                            char char
+                                            (get-char-code-property
+                                             char 'name))))))
+                    ;; TTY frame: show composition in terms of characters.
                     (insert " by these characters:\n")
                     (while (and (<= from to)
                                 (setq glyph (lgstring-glyph gstring from)))
-                      (insert (format " %c (#x%x)\n"
-                                      (lglyph-char glyph) (lglyph-char glyph)))
+                      (insert (format " %c (#x%x) %s\n"
+                                      (lglyph-char glyph) (lglyph-char glyph)
+                                      (get-char-code-property
+                                       (lglyph-char glyph) 'name)))
                       (setq from (1+ from)))))
               (insert " by the rule:\n\t(")
               (let ((first t))
diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el
index 9efd770..1dd0ea2 100644
--- a/lisp/emacs-lisp/eldoc.el
+++ b/lisp/emacs-lisp/eldoc.el
@@ -5,7 +5,7 @@
 ;; Author: Noah Friedman <friedman@splode.com>
 ;; Keywords: extensions
 ;; Created: 1995-10-06
-;; Version: 1.1.0
+;; Version: 1.5.0
 ;; Package-Requires: ((emacs "26.3"))
 
 ;; This is a GNU ELPA :core package.  Avoid functionality that is not
@@ -372,7 +372,7 @@ about the context around point.
 
 - If that decision can be taken quickly, the hook function may
   call CALLBACK immediately following the protocol described
-  berlow.  Alternatively it may ignore CALLBACK entirely and
+  below.  Alternatively it may ignore CALLBACK entirely and
   return either the doc string, or nil if there's no doc
   appropriate for the context.
 
@@ -459,42 +459,46 @@ Honor most of `eldoc-echo-area-use-multiline-p'."
       ;; top-section of the `*eldoc' buffer.  I'm pretty sure nicer
       ;; strategies can be used here, probably by splitting this
       ;; function into some `eldoc-display-functions' special hook.
-      (if (and (eq 'truncate-sym-name-if-fit eldoc-echo-area-use-multiline-p)
-               (null (cdr docs))
-               (setq single-sym-name
-                     (format "%s" (plist-get (cdar docs) :thing)))
-               (> (+ (length (caar docs)) (length single-sym-name) 2) width))
-          (eldoc--message (caar docs))
-        (with-current-buffer (eldoc-doc-buffer)
-          (goto-char (point-min))
-          (cond
-           ;; Potentially truncate a long message into less lines,
-           ;; then display it in the echo area;
-           ((> available 1)
-            (cl-loop
-             initially (goto-char (line-end-position (1+ available)))
-             for truncated = nil then t
-             for needed
-             = (let ((truncate-lines message-truncate-lines))
-                 (count-screen-lines (point-min) (point) t 
(minibuffer-window)))
-             while (> needed (if truncated (1- available) available))
-             do (goto-char (line-end-position (if truncated 0 -1)))
-             (while (bolp) (goto-char (line-end-position 0)))
-             finally
-             (unless (and truncated
-                          eldoc-prefer-doc-buffer
-                          (get-buffer-window eldoc--doc-buffer))
-               (eldoc--message
-                (concat (buffer-substring (point-min) (point))
-                        (and truncated
-                             (format
-                              "\n(Documentation truncated. Use `%s' to see 
rest)"
-                              (substitute-command-keys 
"\\[eldoc-doc-buffer]"))))))))
-           ((= available 1)
-            ;; Truncate "brutally." ; FIXME: use `eldoc-prefer-doc-buffer' too?
-            (eldoc--message
-             (truncate-string-to-width
-              (buffer-substring (point-min) (line-end-position 1)) 
width)))))))))
+      (let ((echo-area-message
+             (cond
+              ((and
+                (eq 'truncate-sym-name-if-fit eldoc-echo-area-use-multiline-p)
+                (null (cdr docs))
+                (setq single-sym-name
+                      (format "%s" (plist-get (cdar docs) :thing)))
+                (> (+ (length (caar docs)) (length single-sym-name) 2) width))
+               (caar docs))
+              ((> available 1)
+               (with-current-buffer (eldoc-doc-buffer)
+                 (cl-loop
+                  initially
+                  (goto-char (point-min))
+                  (goto-char (line-end-position (1+ available)))
+                  for truncated = nil then t
+                  for needed
+                  = (let ((truncate-lines message-truncate-lines))
+                      (count-screen-lines (point-min) (point) t
+                                          (minibuffer-window)))
+                  while (> needed (if truncated (1- available) available))
+                  do (goto-char (line-end-position (if truncated 0 -1)))
+                  (while (and (not (bobp)) (bolp)) (goto-char 
(line-end-position 0)))
+                  finally
+                  (unless (and truncated
+                               eldoc-prefer-doc-buffer
+                               (get-buffer-window eldoc--doc-buffer))
+                    (cl-return
+                     (concat
+                      (buffer-substring (point-min) (point))
+                      (and truncated
+                           (format
+                            "\n(Documentation truncated. Use `%s' to see rest)"
+                            (substitute-command-keys 
"\\[eldoc-doc-buffer]")))))))))
+              ((= available 1)
+               ;; Truncate "brutally." ; FIXME: use `eldoc-prefer-doc-buffer' 
too?
+               (truncate-string-to-width
+                (buffer-substring (point-min) (line-end-position 1)) width)))))
+        (when echo-area-message
+          (eldoc--message echo-area-message))))))
 
 (defun eldoc-documentation-default ()
   "Show first doc string for item at point.
@@ -535,10 +539,27 @@ Meant as a value for `eldoc-documentation-strategy'."
                         (if (stringp str) (funcall callback str))
                         nil))))
 
-(define-obsolete-variable-alias 'eldoc-documentation-function
-  'eldoc-documentation-strategy "eldoc-1.1.0")
-
-(defcustom eldoc-documentation-strategy #'eldoc-documentation-default
+;; JT@2020-07-10: Eldoc is pre-loaded, so in in Emacs < 28 we can't
+;; make the "old" `eldoc-documentation-function' point to the new
+;; `eldoc-documentation-strategy', so we do the reverse.  This allows
+;; for Eldoc to be loaded in those older Emacs versions and work with
+;; whomever (major-modes, extensions, ueser) sets one of the other
+;; variable.
+(defmacro eldoc--documentation-strategy-defcustom
+    (main secondary value docstring &rest more)
+  "Defcustom helper macro for sorting `eldoc-documentation-strategy'."
+  (declare (indent 2))
+  `(if (< emacs-major-version 28)
+       (progn
+         (defcustom ,secondary ,value ,docstring ,@more)
+         (define-obsolete-variable-alias ',main ',secondary "eldoc-1.1.0"))
+       (progn
+         (defcustom ,main ,value ,docstring  ,@more)
+         (defvaralias ',secondary ',main ,docstring))))
+
+(eldoc--documentation-strategy-defcustom eldoc-documentation-strategy
+    eldoc-documentation-function
+  #'eldoc-documentation-default
   "How to collect and organize results of `eldoc-documentation-functions'.
 
 This variable controls how `eldoc-documentation-functions', which
@@ -712,19 +733,22 @@ endeavour to display the docstrings given to them."
                     (;; New protocol: trust callback will be called;
                      t))))))
 
-(defun eldoc-print-current-symbol-info ()
+(defun eldoc-print-current-symbol-info (&optional interactive)
   "Document thing at point."
-  (interactive)
-  (if (not (eldoc-display-message-p))
-      ;; Erase the last message if we won't display a new one.
-      (when eldoc-last-message
-        (eldoc--message nil))
-    (let ((non-essential t))
-      ;; 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--invoke-strategy)))))
+  (interactive '(t))
+  (cond (interactive
+         (eldoc--invoke-strategy))
+        (t
+         (if (not (eldoc-display-message-p))
+             ;; Erase the last message if we won't display a new one.
+             (when eldoc-last-message
+               (eldoc--message nil))
+           (let ((non-essential t))
+             ;; 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--invoke-strategy)))))))
 
 ;; When point is in a sexp, the function args are not reprinted in the echo
 ;; area after every possible interactive command because some of them print
diff --git a/lisp/net/eudcb-macos-contacts.el b/lisp/net/eudcb-macos-contacts.el
new file mode 100644
index 0000000..f258d5c
--- /dev/null
+++ b/lisp/net/eudcb-macos-contacts.el
@@ -0,0 +1,118 @@
+;;; eudcb-macos-contacts.el --- EUDC - macOS Contacts backend
+
+;; Copyright (C) 2020 condition-alpha.com
+
+;; 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/>.
+
+;;; Commentary:
+;;    This library provides an interface to the macOS Contacts app as
+;;    an EUDC data source.  It uses AppleScript to interface with the
+;;    Contacts app on localhost, so no 3rd party tools are needed.
+
+;;; Usage:
+;;    (require 'eudcb-macos-contacts)
+;;    (eudc-macos-contacts-set-server "localhost")
+
+;;; Code:
+
+(require 'eudc)
+(require 'executable)
+
+;;{{{      Internal cooking
+
+(defvar eudc-macos-contacts-conversion-alist nil)
+
+;; hook ourselves into the EUDC framework
+(eudc-protocol-set 'eudc-query-function
+                  'eudc-macos-contacts-query-internal
+                  'macos-contacts)
+(eudc-protocol-set 'eudc-list-attributes-function
+                  nil
+                  'macos-contacts)
+(eudc-protocol-set 'eudc-macos-contacts-conversion-alist
+                  nil
+                  'macos-contacts)
+(eudc-protocol-set 'eudc-protocol-has-default-query-attributes
+                  nil
+                  'macos-contacts)
+
+(defun eudc-macos-contacts-search-helper (str)
+  "Helper function to query the Contacts app via AppleScript.
+Searches for all persons with a case-insensitive substring match
+of STR in any of their name fields (first, middle, or last)."
+  (if (executable-find "osascript")
+      (call-process "osascript" nil t nil
+                   "-e"
+                   (format "
+set results to {}
+tell application \"Address Book\"
+       set pList to every person whose (name contains \"%s\")
+       repeat with pers in pList
+               repeat with emailAddr in emails of pers
+                       set results to results & {name of pers & \":\" & value ¬
+                       of emailAddr & \"\n\"}
+               end repeat
+       end repeat
+       get results as text
+end tell" str))
+    (message (concat "[eudc] Error in macOS Contacts backend: "
+                    "`osascript' executable not found. "
+                    "Is this is a macOS 10.0 or later system?"))))
+
+(defun eudc-macos-contacts-query-internal (query &optional return-attrs)
+  "Query macOS Contacts with QUERY.
+QUERY is a list of cons cells (ATTR . VALUE) where ATTRs should be valid
+macOS Contacts attribute names.
+RETURN-ATTRS is a list of attributes to return, defaulting to
+`eudc-default-return-attributes'."
+  (let ((macos-contacts-buffer (get-buffer-create " *macOS Contacts*"))
+       result)
+    (with-current-buffer macos-contacts-buffer
+      (erase-buffer)
+      (dolist (term query)
+       (eudc-macos-contacts-search-helper (cdr term)))
+      (delete-duplicate-lines (point-min) (point-max))
+      (goto-char (point-min))
+      (while (not (eobp))
+       (if (not (equal (line-beginning-position) (line-end-position)))
+           (let* ((args (split-string (buffer-substring
+                                       (point) (line-end-position))
+                                      ":"))
+                  (name (nth 0 args))
+                  (email (nth 1 args)))
+             (setq result (cons `((name . ,name)
+                                  (email . ,email)) result))))
+       (forward-line))
+      result)))
+
+;;}}}
+
+;;{{{      High-level interfaces (interactive functions)
+
+(defun eudc-macos-contacts-set-server (dummy)
+  "Set the EUDC server to macOS Contacts app.
+The server in DUMMY is not actually used, since this backend
+always and implicitly connetcs to an instance of the Contacts app
+running on the local host."
+  (interactive)
+  (eudc-set-server dummy 'macos-contacts)
+  (message "[eudc] macOS Contacts app server selected"))
+
+;;}}}
+
+(eudc-register-protocol 'macos-contacts)
+
+(provide 'eudcb-macos-contacts)
+
+;;; eudcb-macos-contacts.el ends here
diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el
index a7a5047..25e4097 100644
--- a/lisp/net/tramp-adb.el
+++ b/lisp/net/tramp-adb.el
@@ -55,15 +55,27 @@ It is used for TCP/IP devices."
   "When this method name is used, forward all calls to Android Debug Bridge.")
 
 ;;;###tramp-autoload
-(defcustom tramp-adb-prompt
-  "^[[:digit:]]*|?[[:alnum:]\e;[]*@?[[:alnum:]]*[^#\\$]*[#\\$][[:space:]]"
+(defcustom tramp-adb-prompt "^[^#\\$]*[#\\$][[:space:]]"
   "Regexp used as prompt in almquist shell."
   :type 'regexp
-  :version "24.4"
+  :version "28.1"
   :group 'tramp)
 
+(eval-and-compile
+  (defconst tramp-adb-ls-date-year-regexp
+    "[[:digit:]]\\{4\\}-[[:digit:]]\\{2\\}-[[:digit:]]\\{2\\}"
+    "Regexp for date year format in ls output."))
+
+(eval-and-compile
+  (defconst tramp-adb-ls-date-time-regexp
+    "[[:digit:]]\\{2\\}:[[:digit:]]\\{2\\}"
+  "Regexp for date time format in ls output."))
+
 (defconst tramp-adb-ls-date-regexp
-  
"[[:space:]][0-9]\\{4\\}-[0-9][0-9]-[0-9][0-9][[:space:]][0-9][0-9]:[0-9][0-9][[:space:]]"
+  (concat
+   "[[:space:]]" tramp-adb-ls-date-year-regexp
+   "[[:space:]]" tramp-adb-ls-date-time-regexp
+   "[[:space:]]")
   "Regexp for date format in ls output.")
 
 (defconst tramp-adb-ls-toolbox-regexp
@@ -73,7 +85,8 @@ It is used for TCP/IP devices."
    "[[:space:]]*\\([^[:space:]]+\\)"   ; \2 username
    "[[:space:]]+\\([^[:space:]]+\\)"   ; \3 group
    "[[:space:]]+\\([[:digit:]]+\\)"    ; \4 size
-   "[[:space:]]+\\([-[:digit:]]+[[:space:]][:[:digit:]]+\\)" ; \5 date
+   "[[:space:]]+\\(" tramp-adb-ls-date-year-regexp
+   "[[:space:]]" tramp-adb-ls-date-time-regexp "\\)" ; \5 date
    "[[:space:]]\\(.*\\)$")             ; \6 filename
   "Regexp for ls output.")
 
@@ -215,11 +228,10 @@ ARGUMENTS to pass to the OPERATION."
        (goto-char (point-min))
        (forward-line)
        (when (looking-at
-              (eval-when-compile
-                (concat "[[:space:]]*[^[:space:]]+"
-                        "[[:space:]]+\\([[:digit:]]+\\)"
-                        "[[:space:]]+\\([[:digit:]]+\\)"
-                        "[[:space:]]+\\([[:digit:]]+\\)")))
+              (concat "[[:space:]]*[^[:space:]]+"
+                      "[[:space:]]+\\([[:digit:]]+\\)"
+                      "[[:space:]]+\\([[:digit:]]+\\)"
+                      "[[:space:]]+\\([[:digit:]]+\\)"))
          ;; The values are given as 1k numbers, so we must change
          ;; them to number of bytes.
          (list (* 1024 (string-to-number (match-string 1)))
@@ -272,7 +284,9 @@ ARGUMENTS to pass to the OPERATION."
                 (if (eq id-format 'integer) 0 uid)
                 (if (eq id-format 'integer) 0 gid)
                 tramp-time-dont-know   ; atime
-                (date-to-time date)    ; mtime
+                ;; `date-to-time' checks `iso8601-parse', which might fail.
+                (let (signal-hook-function)
+                  (date-to-time date)) ; mtime
                 tramp-time-dont-know   ; ctime
                 size
                 mod-string
@@ -351,21 +365,6 @@ ARGUMENTS to pass to the OPERATION."
       "ls --color=never")
      (t "ls"))))
 
-(defun tramp-adb--gnu-switches-to-ash (switches)
-  "Almquist shell can't handle multiple arguments.
-Convert (\"-al\") to (\"-a\" \"-l\").  Remove arguments like \"--dired\"."
-  (split-string
-   (apply #'concat
-         (mapcar (lambda (s)
-                   (replace-regexp-in-string
-                    "\\(.\\)" " -\\1" (replace-regexp-in-string "^-" "" s)))
-                 ;; FIXME: Warning about removed switches (long and non-dash).
-                 (delq nil
-                       (mapcar
-                        (lambda (s)
-                          (and (not (string-match-p "\\(^--\\|^[^-]\\)" s)) s))
-                        switches))))))
-
 (defun tramp-adb-sh-fix-ls-output (&optional sort-by-time)
   "Insert dummy 0 in empty size columns.
 Android's \"ls\" command doesn't insert size column for directories:
@@ -375,10 +374,16 @@ Emacs dired can't find files."
     (goto-char (point-min))
     (while
        (search-forward-regexp
-        
"[[:space:]]\\([[:space:]][0-9]\\{4\\}-[0-9][0-9]-[0-9][0-9][[:space:]]\\)" nil 
t)
+        (eval-when-compile
+          (concat
+           "[[:space:]]"
+           "\\([[:space:]]" tramp-adb-ls-date-year-regexp "[[:space:]]\\)"))
+        nil t)
       (replace-match "0\\1" "\\1" nil)
       ;; Insert missing "/".
-      (when (looking-at-p "[0-9][0-9]:[0-9][0-9][[:space:]]+$")
+      (when (looking-at-p
+            (eval-when-compile
+              (concat tramp-adb-ls-date-time-regexp "[[:space:]]+$")))
        (end-of-line)
        (insert "/")))
     ;; Sort entries.
@@ -489,9 +494,10 @@ Emacs dired can't find files."
       (with-tramp-progress-reporter
          v 3 (format "Fetching %s to tmp file %s" filename tmpfile)
        ;; "adb pull ..." does not always return an error code.
-       (when (or (tramp-adb-execute-adb-command
-                  v "pull" (tramp-compat-file-name-unquote localname) tmpfile)
-                 (not (file-exists-p tmpfile)))
+       (unless
+           (and (tramp-adb-execute-adb-command
+                 v "pull" (tramp-compat-file-name-unquote localname) tmpfile)
+                (file-exists-p tmpfile))
          (ignore-errors (delete-file tmpfile))
          (tramp-error
           v 'file-error "Cannot make local copy of file `%s'" filename))
@@ -544,8 +550,8 @@ But handle the case, if the \"test\" command is not 
available."
         v 3 (format-message
              "Moving tmp file `%s' to `%s'" tmpfile filename)
        (unwind-protect
-           (when (tramp-adb-execute-adb-command
-                  v "push" tmpfile (tramp-compat-file-name-unquote localname))
+           (unless (tramp-adb-execute-adb-command
+                    v "push" tmpfile (tramp-compat-file-name-unquote 
localname))
              (tramp-error v 'file-error "Cannot write: `%s'" filename))
          (delete-file tmpfile)))
 
@@ -577,7 +583,7 @@ But handle the case, if the \"test\" command is not 
available."
     (unless (and (eq flag 'nofollow) (file-symlink-p filename))
       (tramp-flush-file-properties v localname)
       (tramp-adb-send-command-and-check
-       v (format "chmod %o %s" mode localname)))))
+       v (format "chmod %o %s" mode (tramp-shell-quote-argument localname))))))
 
 (defun tramp-adb-handle-set-file-times (filename &optional time flag)
   "Like `set-file-times' for Tramp files."
@@ -595,15 +601,16 @@ But handle the case, if the \"test\" command is not 
available."
       ;; fails.  Also, fall back on old POSIX 'touch -t' if 'touch -d'
       ;; (introduced in POSIX.1-2008) fails.
       (tramp-adb-send-command-and-check
-       v (format (concat "touch -d %s %s %s 2>/dev/null || "
-                        "touch -d %s %s %s 2>/dev/null || "
-                        "touch -t %s %s %s")
-                (format-time-string "%Y-%m-%dT%H:%M:%S.%NZ" time t)
-                nofollow quoted-name
-                (format-time-string "%Y-%m-%dT%H:%M:%S" time t)
-                nofollow quoted-name
-                (format-time-string "%Y%m%d%H%M.%S" time t)
-                nofollow quoted-name)))))
+       v (format
+         (concat "touch -d %s %s %s 2>/dev/null || "
+                 "touch -d %s %s %s 2>/dev/null || "
+                 "touch -t %s %s %s")
+         (format-time-string "%Y-%m-%dT%H:%M:%S.%NZ" time t)
+         nofollow quoted-name
+         (format-time-string "%Y-%m-%dT%H:%M:%S" time t)
+         nofollow quoted-name
+         (format-time-string "%Y%m%d%H%M.%S" time t)
+         nofollow quoted-name)))))
 
 (defun tramp-adb-handle-copy-file
   (filename newname &optional ok-if-already-exists keep-date
@@ -670,10 +677,10 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
                ;; because `file-attributes' reads the values from
                ;; there.
                (tramp-flush-file-properties v localname)
-               (when (tramp-adb-execute-adb-command
-                      v "push"
-                      (tramp-compat-file-name-unquote filename)
-                      (tramp-compat-file-name-unquote localname))
+               (unless (tramp-adb-execute-adb-command
+                        v "push"
+                        (tramp-compat-file-name-unquote filename)
+                        (tramp-compat-file-name-unquote localname))
                  (tramp-error
                   v 'file-error
                   "Cannot copy `%s' `%s'" filename newname))))))))
@@ -1039,10 +1046,10 @@ E.g. a host name \"192.168.1.1#5555\" returns 
\"192.168.1.1:5555\"
             ;; Try to connect device.
             ((and tramp-adb-connect-if-not-connected
                   (not (zerop (length host)))
-                  (not (tramp-adb-execute-adb-command
-                         vec "connect"
-                         (replace-regexp-in-string
-                          tramp-prefix-port-format ":" host))))
+                  (tramp-adb-execute-adb-command
+                    vec "connect"
+                    (replace-regexp-in-string
+                    tramp-prefix-port-format ":" host)))
              ;; When new device connected, running other adb command (e.g.
              ;; adb shell) immediately will fail.  To get around this
              ;; problem, add sleep 0.1 second here.
@@ -1052,18 +1059,18 @@ E.g. a host name \"192.168.1.1#5555\" returns 
\"192.168.1.1:5555\"
                 vec 'file-error "Could not find device %s" host)))))))
 
 (defun tramp-adb-execute-adb-command (vec &rest args)
-  "Return nil on success error-output on failure."
+  "Execute an adb command.
+Insert the result into the connection buffer.  Return nil on
+error and non-nil on success."
   (when (and (> (length (tramp-file-name-host vec)) 0)
             ;; The -s switch is only available for ADB device commands.
             (not (member (car args) '("connect" "disconnect"))))
     (setq args (append (list "-s" (tramp-adb-get-device vec)) args)))
-  (with-temp-buffer
-    (prog1
-       (unless
-           (zerop
-            (apply #'tramp-call-process vec tramp-adb-program nil t nil args))
-         (buffer-string))
-      (tramp-message vec 6 "%s" (buffer-string)))))
+  (with-current-buffer (tramp-get-connection-buffer vec)
+    ;; Clean up the buffer.  We cannot call `erase-buffer' because
+    ;; narrowing might be in effect.
+    (let ((inhibit-read-only t)) (delete-region (point-min) (point-max)))
+    (zerop (apply #'tramp-call-process vec tramp-adb-program nil t nil args))))
 
 (defun tramp-adb-find-test-command (vec)
   "Check whether the ash has a builtin \"test\" command.
@@ -1075,25 +1082,30 @@ This happens for Android >= 4.0."
 
 (defun tramp-adb-send-command (vec command &optional neveropen nooutput)
   "Send the COMMAND to connection VEC."
-  (unless neveropen (tramp-adb-maybe-open-connection vec))
-  (tramp-message vec 6 "%s" command)
-  (tramp-send-string vec command)
-  (unless nooutput
-    ;; FIXME: Race condition.
-    (tramp-adb-wait-for-output (tramp-get-connection-process vec))
-    (with-current-buffer (tramp-get-connection-buffer vec)
-      (save-excursion
-       (goto-char (point-min))
-       ;; We can't use stty to disable echo of command.  stty is said
-       ;; to be added to toybox 0.7.6.  busybox shall have it, but this
-       ;; isn't used any longer for Android.
-       (delete-matching-lines (regexp-quote command))
-       ;; When the local machine is W32, there are still trailing ^M.
-       ;; There must be a better solution by setting the correct coding
-       ;; system, but this requires changes in core Tramp.
-       (goto-char (point-min))
-       (while (re-search-forward "\r+$" nil t)
-         (replace-match "" nil nil))))))
+  (if (string-match-p "[[:multibyte:]]" command)
+      ;; Multibyte codepoints with four bytes are not supported at
+      ;; least by toybox.
+      (tramp-adb-execute-adb-command vec "shell" command)
+
+    (unless neveropen (tramp-adb-maybe-open-connection vec))
+    (tramp-message vec 6 "%s" command)
+    (tramp-send-string vec command)
+    (unless nooutput
+      ;; FIXME: Race condition.
+      (tramp-adb-wait-for-output (tramp-get-connection-process vec))
+      (with-current-buffer (tramp-get-connection-buffer vec)
+       (save-excursion
+         (goto-char (point-min))
+         ;; We can't use stty to disable echo of command.  stty is said
+         ;; to be added to toybox 0.7.6.  busybox shall have it, but this
+         ;; isn't used any longer for Android.
+         (delete-matching-lines (regexp-quote command))
+         ;; When the local machine is W32, there are still trailing ^M.
+         ;; There must be a better solution by setting the correct coding
+         ;; system, but this requires changes in core Tramp.
+         (goto-char (point-min))
+         (while (re-search-forward "\r+$" nil t)
+           (replace-match "" nil nil)))))))
 
 (defun tramp-adb-send-command-and-check (vec command &optional exit-status)
   "Run COMMAND and check its exit status.
@@ -1108,7 +1120,7 @@ the exit status."
           (format "%s; echo tramp_exit_status $?" command)
         "echo tramp_exit_status $?"))
   (with-current-buffer (tramp-get-connection-buffer vec)
-    (unless (tramp-search-regexp "tramp_exit_status [0-9]+")
+    (unless (tramp-search-regexp "tramp_exit_status [[:digit:]]+")
       (tramp-error
        vec 'file-error "Couldn't find exit status of `%s'" command))
     (skip-chars-forward "^ ")
@@ -1217,7 +1229,11 @@ connection if a previous connection has died for some 
reason."
            ;; connection properties.  We start again.
            (tramp-message vec 5 "Checking system information")
            (tramp-adb-send-command
-            vec "echo \\\"`getprop ro.product.model` `getprop 
ro.product.version` `getprop ro.build.version.release`\\\"")
+            vec
+            (concat
+             "echo \\\"`getprop ro.product.model` "
+             "`getprop ro.product.version` "
+             "`getprop ro.build.version.release`\\\""))
            (let ((old-getprop
                   (tramp-get-connection-property vec "getprop" nil))
                  (new-getprop
@@ -1241,7 +1257,8 @@ connection if a previous connection has died for some 
reason."
              (tramp-adb-send-command vec (format "su %s" user))
              (unless (tramp-adb-send-command-and-check vec nil)
                (delete-process p)
-               (tramp-flush-file-property vec "" "su-command-p")
+               ;; Do not flush, we need the nil value.
+               (tramp-set-file-property vec "" "su-command-p" nil)
                (tramp-error
                 vec 'file-error "Cannot switch to user `%s'" user)))
 
@@ -1275,4 +1292,9 @@ connection if a previous connection has died for some 
reason."
 
 (provide 'tramp-adb)
 
+;;; TODO:
+;;
+;; * Support file names with multibyte codepoints.  Use as fallback
+;;   "adb shell COMMAND".
+;;
 ;;; tramp-adb.el ends here
diff --git a/lisp/net/tramp-cmds.el b/lisp/net/tramp-cmds.el
index 2805f66..52cc186 100644
--- a/lisp/net/tramp-cmds.el
+++ b/lisp/net/tramp-cmds.el
@@ -359,9 +359,8 @@ The remote connection identified by SOURCE is flushed by
     (or (setq target (tramp-default-rename-file source))
        (tramp-user-error
         nil
-        (eval-when-compile
-          (concat "There is no target specified.  "
-                  "Check `tramp-default-rename-alist' for a proper entry.")))))
+        (concat "There is no target specified.  "
+                "Check `tramp-default-rename-alist' for a proper entry."))))
   (when (tramp-equal-remote source target)
     (tramp-user-error nil "Source and target must have different remote."))
 
@@ -566,11 +565,10 @@ buffer in your bug report.
       ;; Remove string quotation.
       (forward-line -1)
       (when (looking-at
-            (eval-when-compile
-              (concat "\\(^.*\\)" "\""                       ;; \1 "
-                      "\\((base64-decode-string \\)" "\\\\"  ;; \2 \
-                      "\\(\".*\\)" "\\\\"                    ;; \3 \
-                      "\\(\")\\)" "\"$")))                   ;; \4 "
+            (concat "\\(^.*\\)" "\""                       ;; \1 "
+                    "\\((base64-decode-string \\)" "\\\\"  ;; \2 \
+                    "\\(\".*\\)" "\\\\"                    ;; \3 \
+                    "\\(\")\\)" "\"$"))                    ;; \4 "
        (replace-match "\\1\\2\\3\\4")
        (beginning-of-line)
        (insert " ;; Variable encoded due to non-printable characters.\n"))
diff --git a/lisp/net/tramp-ftp.el b/lisp/net/tramp-ftp.el
index 95ae156..996a924 100644
--- a/lisp/net/tramp-ftp.el
+++ b/lisp/net/tramp-ftp.el
@@ -31,8 +31,7 @@
 (require 'tramp)
 
 ;; Pacify byte-compiler.
-(eval-when-compile
-  (require 'custom))
+(eval-when-compile (require 'custom))
 (defvar ange-ftp-ftp-name-arg)
 (defvar ange-ftp-ftp-name-res)
 (defvar ange-ftp-name-format)
@@ -79,9 +78,9 @@ present for backward compatibility."
   ;;; This regexp recognizes absolute filenames with only one component
   ;;; on Windows, for the sake of hostname completion.
   (and (memq system-type '(ms-dos windows-nt))
-       (or (assoc "^[a-zA-Z]:/[^/:]*\\'" file-name-handler-alist)
+       (or (assoc "^[[:alpha:]]:/[^/:]*\\'" file-name-handler-alist)
           (setq file-name-handler-alist
-                (cons '("^[a-zA-Z]:/[^/:]*\\'" .
+                (cons '("^[:alpha:]]:/[^/:]*\\'" .
                         ange-ftp-completion-hook-function)
                       file-name-handler-alist)))))
 
diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el
index dce6edd..6467d8f 100644
--- a/lisp/net/tramp-gvfs.el
+++ b/lisp/net/tramp-gvfs.el
@@ -108,8 +108,7 @@
 (require 'url-util)
 
 ;; Pacify byte-compiler.
-(eval-when-compile
-  (require 'custom))
+(eval-when-compile (require 'custom))
 
 (declare-function zeroconf-init "zeroconf")
 (declare-function zeroconf-list-service-types "zeroconf")
@@ -697,32 +696,34 @@ It has been changed in GVFS 1.14.")
   "List of cons cells, mapping \"gvfs-<command>\" to \"gio <command>\".")
 
 ;; <http://www.pygtk.org/docs/pygobject/gio-constants.html>
-(defconst tramp-gvfs-file-attributes
-  '("name"
-    "type"
-    "standard::display-name"
-    "standard::symlink-target"
-    "standard::is-volatile"
-    "unix::nlink"
-    "unix::uid"
-    "owner::user"
-    "unix::gid"
-    "owner::group"
-    "time::access"
-    "time::modified"
-    "time::changed"
-    "standard::size"
-    "unix::mode"
-    "access::can-read"
-    "access::can-write"
-    "access::can-execute"
-    "unix::inode"
-    "unix::device")
-  "GVFS file attributes.")
-
-(defconst tramp-gvfs-file-attributes-with-gvfs-ls-regexp
-  (concat "[[:blank:]]" (regexp-opt tramp-gvfs-file-attributes t) "=\\(.+?\\)")
-  "Regexp to parse GVFS file attributes with `gvfs-ls'.")
+(eval-and-compile
+  (defconst tramp-gvfs-file-attributes
+    '("name"
+      "type"
+      "standard::display-name"
+      "standard::symlink-target"
+      "standard::is-volatile"
+      "unix::nlink"
+      "unix::uid"
+      "owner::user"
+      "unix::gid"
+      "owner::group"
+      "time::access"
+      "time::modified"
+      "time::changed"
+      "standard::size"
+      "unix::mode"
+      "access::can-read"
+      "access::can-write"
+      "access::can-execute"
+      "unix::inode"
+      "unix::device")
+    "GVFS file attributes."))
+
+(eval-and-compile
+  (defconst tramp-gvfs-file-attributes-with-gvfs-ls-regexp
+    (concat "[[:blank:]]" (regexp-opt tramp-gvfs-file-attributes t) 
"=\\(.+?\\)")
+    "Regexp to parse GVFS file attributes with `gvfs-ls'."))
 
 (defconst tramp-gvfs-file-attributes-with-gvfs-info-regexp
   (concat "^[[:blank:]]*"
@@ -864,7 +865,7 @@ pass to the OPERATION."
 (defun tramp-gvfs-dbus-string-to-byte-array (string)
   "Like `dbus-string-to-byte-array' but add trailing \\0 if needed."
   (dbus-string-to-byte-array
-   (if (string-match "^(aya{sv})" tramp-gvfs-mountlocation-signature)
+   (if (string-match-p "^(aya{sv})" tramp-gvfs-mountlocation-signature)
        (concat string (string 0)) string)))
 
 (defun tramp-gvfs-dbus-byte-array-to-string (byte-array)
@@ -1181,10 +1182,11 @@ file names."
        (with-current-buffer (tramp-get-connection-buffer v)
          (goto-char (point-min))
          (while (looking-at
-                 (concat "^\\(.+\\)[[:blank:]]"
-                         "\\([[:digit:]]+\\)[[:blank:]]"
-                         "(\\(.+?\\))"
-                         tramp-gvfs-file-attributes-with-gvfs-ls-regexp))
+                 (eval-when-compile
+                   (concat "^\\(.+\\)[[:blank:]]"
+                           "\\([[:digit:]]+\\)[[:blank:]]"
+                           "(\\(.+?\\))"
+                           tramp-gvfs-file-attributes-with-gvfs-ls-regexp)))
            (let ((item (list (cons "type" (match-string 3))
                              (cons "standard::size" (match-string 2))
                              (cons "name" (match-string 1)))))
@@ -1285,8 +1287,7 @@ If FILE-SYSTEM is non-nil, return file system attributes."
            (if (eq id-format 'integer)
                (string-to-number
                 (or (cdr (assoc "unix::uid" attributes))
-                    (eval-when-compile
-                      (format "%s" tramp-unknown-id-integer))))
+                    (eval-when-compile (format "%s" 
tramp-unknown-id-integer))))
              (or (cdr (assoc "owner::user" attributes))
                  (cdr (assoc "unix::uid" attributes))
                  tramp-unknown-id-string)))
@@ -1294,8 +1295,7 @@ If FILE-SYSTEM is non-nil, return file system attributes."
            (if (eq id-format 'integer)
                (string-to-number
                 (or (cdr (assoc "unix::gid" attributes))
-                    (eval-when-compile
-                      (format "%s" tramp-unknown-id-integer))))
+                    (eval-when-compile (format "%s" 
tramp-unknown-id-integer))))
              (or (cdr (assoc "owner::group" attributes))
                  (cdr (assoc "unix::gid" attributes))
                  tramp-unknown-id-string)))
@@ -1475,11 +1475,11 @@ If FILE-SYSTEM is non-nil, return file system 
attributes."
        ;; File names are returned as URL paths.  We must convert them.
        (when (string-match ddu file)
          (setq file (replace-match dd nil nil file)))
-       (while (string-match-p "%\\([0-9A-F]\\{2\\}\\)" file)
+       (while (string-match-p "%\\([[:xdigit:]]\\{2\\}\\)" file)
          (setq file (url-unhex-string file)))
        (when (string-match ddu (or file1 ""))
          (setq file1 (replace-match dd nil nil file1)))
-       (while (string-match-p "%\\([0-9A-F]\\{2\\}\\)" (or file1 ""))
+       (while (string-match-p "%\\([[:xdigit:]]\\{2\\}\\)" (or file1 ""))
          (setq file1 (url-unhex-string file1)))
        ;; Remove watch when file or directory to be watched is deleted.
        (when (and (member action '(moved deleted))
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index 89e5dc9..0e55d60 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -90,10 +90,10 @@ the default storage location, e.g. \"$HOME/.sh_history\"."
                  (string :tag "Redirect to a file")))
 
 ;;;###tramp-autoload
-(defconst tramp-display-escape-sequence-regexp "\e[[;0-9]+m"
+(defconst tramp-display-escape-sequence-regexp "\e[[:digit:];[]+m"
   "Terminal control escape sequences for display attributes.")
 
-(defconst tramp-device-escape-sequence-regexp "\e[[0-9]+n"
+(defconst tramp-device-escape-sequence-regexp "\e[[:digit:][]+n"
   "Terminal control escape sequences for device status.")
 
 ;; ksh on OpenBSD 4.5 requires that $PS1 contains a `#' character for
@@ -1329,13 +1329,12 @@ component is used as the target of the symlink."
   (tramp-send-command-and-read
    vec
    (format
-    (eval-when-compile
-      (concat
-       ;; Apostrophes in the stat output are masked as
-       ;; `tramp-stat-marker', in order to make a proper shell escape
-       ;; of them in file names.
-       "(%s -c '((%s%%N%s) %%h %s %s %%X %%Y %%Z %%s %s%%A%s t %%i -1)' %s |"
-       " sed -e 's/\"/\\\\\"/g' -e 's/%s/\"/g')"))
+    (concat
+     ;; Apostrophes in the stat output are masked as
+     ;; `tramp-stat-marker', in order to make a proper shell escape of
+     ;; them in file names.
+     "(%s -c '((%s%%N%s) %%h %s %s %%X %%Y %%Z %%s %s%%A%s t %%i -1)' %s |"
+     " sed -e 's/\"/\\\\\"/g' -e 's/%s/\"/g')")
     (tramp-get-remote-stat vec)
     tramp-stat-marker tramp-stat-marker
     (if (eq id-format 'integer)
@@ -1514,9 +1513,8 @@ ID-FORMAT valid values are `string' and `integer'."
   (with-parsed-tramp-file-name filename nil
     (with-tramp-file-property v localname "file-selinux-context"
       (let ((context '(nil nil nil nil))
-           (regexp (eval-when-compile
-                     (concat "\\([a-z0-9_]+\\):" "\\([a-z0-9_]+\\):"
-                             "\\([a-z0-9_]+\\):" "\\([a-z0-9_]+\\)"))))
+           (regexp (concat "\\([[:alnum:]_]+\\):" "\\([[:alnum:]_]+\\):"
+                           "\\([[:alnum:]_]+\\):" "\\([[:alnum:]_]+\\)")))
        (when (and (tramp-remote-selinux-p v)
                   (tramp-send-command-and-check
                    v (format
@@ -1766,21 +1764,19 @@ ID-FORMAT valid values are `string' and `integer'."
   (tramp-send-command-and-read
    vec
    (format
-    (eval-when-compile
-      (concat
-       ;; We must care about file names with spaces, or starting with
-       ;; "-"; this would confuse xargs.  "ls -aQ" might be a
-       ;; solution, but it does not work on all remote systems.
-       ;; Therefore, we use \000 as file separator.
-       ;; `tramp-sh--quoting-style-options' do not work for file names
-       ;; with spaces piped to "xargs".
-       ;; Apostrophes in the stat output are masked as
-       ;; `tramp-stat-marker', in order to make a proper shell escape
-       ;; of them in file names.
-       "cd %s && echo \"(\"; (%s %s -a | tr '\\n\\r' '\\000\\000' | "
-       "xargs -0 %s -c "
-       "'(%s%%n%s (%s%%N%s) %%h %s %s %%X %%Y %%Z %%s %s%%A%s t %%i -1)' "
-       "-- 2>/dev/null | sed -e 's/\"/\\\\\"/g' -e 's/%s/\"/g'); echo \")\""))
+    (concat
+     ;; We must care about file names with spaces, or starting with
+     ;; "-"; this would confuse xargs.  "ls -aQ" might be a solution,
+     ;; but it does not work on all remote systems.  Therefore, we use
+     ;; \000 as file separator.  `tramp-sh--quoting-style-options' do
+     ;; not work for file names with spaces piped to "xargs".
+     ;; Apostrophes in the stat output are masked as
+     ;; `tramp-stat-marker', in order to make a proper shell escape of
+     ;; them in file names.
+     "cd %s && echo \"(\"; (%s %s -a | tr '\\n\\r' '\\000\\000' | "
+     "xargs -0 %s -c "
+     "'(%s%%n%s (%s%%N%s) %%h %s %s %%X %%Y %%Z %%s %s%%A%s t %%i -1)' "
+     "-- 2>/dev/null | sed -e 's/\"/\\\\\"/g' -e 's/%s/\"/g'); echo \")\"")
     (tramp-shell-quote-argument localname)
     (tramp-get-ls-command vec)
     ;; On systems which have no quoting style, file names with special
@@ -1821,13 +1817,12 @@ ID-FORMAT valid values are `string' and `integer'."
                  (format "tramp_perl_file_name_all_completions %s"
                          (tramp-shell-quote-argument localname)))
 
-             (format (eval-when-compile
-                       (concat
-                        "(cd %s 2>&1 && %s -a 2>/dev/null"
-                        " | while IFS= read f; do"
-                        " if %s -d \"$f\" 2>/dev/null;"
-                        " then \\echo \"$f/\"; else \\echo \"$f\"; fi; done"
-                        " && \\echo ok) || \\echo fail"))
+             (format (concat
+                      "(cd %s 2>&1 && %s -a 2>/dev/null"
+                      " | while IFS= read f; do"
+                      " if %s -d \"$f\" 2>/dev/null;"
+                      " then \\echo \"$f/\"; else \\echo \"$f\"; fi; done"
+                      " && \\echo ok) || \\echo fail")
                      (tramp-shell-quote-argument localname)
                      (tramp-get-ls-command v)
                      (tramp-get-test-command v))))
@@ -3387,9 +3382,8 @@ STDERR can also be a file name."
                                        loc-enc tmpfile t))
                          (tramp-error
                           v 'file-error
-                          (eval-when-compile
-                            (concat "Cannot write to `%s', "
-                                    "local encoding command `%s' failed"))
+                          (concat "Cannot write to `%s', "
+                                  "local encoding command `%s' failed")
                           filename loc-enc))))
 
                    ;; Send buffer into remote decoding command which
@@ -3434,9 +3428,8 @@ STDERR can also be a file name."
                             (buffer-string))))
                         (tramp-error
                          v 'file-error
-                         (eval-when-compile
-                           (concat "Couldn't write region to `%s',"
-                                   " decode using `%s' failed"))
+                         (concat "Couldn't write region to `%s',"
+                                 " decode using `%s' failed")
                          filename rem-dec)))))
 
                ;; Save exit.
@@ -3446,9 +3439,8 @@ STDERR can also be a file name."
             (t
              (tramp-error
               v 'file-error
-              (eval-when-compile
-                (concat "Method `%s' should specify both encoding and "
-                        "decoding command or an scp program"))
+              (concat "Method `%s' should specify both encoding and "
+                      "decoding command or an scp program")
               method))))
 
          ;; Make `last-coding-system-used' have the right value.
@@ -3648,13 +3640,11 @@ Fall back to normal file name handler if no Tramp 
handler exists."
              events
              (cond
               ((and (memq 'change flags) (memq 'attribute-change flags))
-               (eval-when-compile
-                 (concat "create,modify,move,moved_from,moved_to,move_self,"
-                         "delete,delete_self,attrib,ignored")))
+               (concat "create,modify,move,moved_from,moved_to,move_self,"
+                       "delete,delete_self,attrib,ignored"))
               ((memq 'change flags)
-               (eval-when-compile
-                 (concat "create,modify,move,moved_from,moved_to,move_self,"
-                         "delete,delete_self,ignored")))
+               (concat "create,modify,move,moved_from,moved_to,move_self,"
+                       "delete,delete_self,ignored"))
               ((memq 'attribute-change flags) "attrib,ignored"))
              sequence `(,command "-mq" "-e" ,events ,localname)
              ;; Make events a list of symbols.
@@ -3796,12 +3786,11 @@ Fall back to normal file name handler if no Tramp 
handler exists."
                  "ATTRIB CHANGED" "ATTRIBUTE_CHANGED" string))
 
     (while (string-match
-           (eval-when-compile
-             (concat "^[\n\r]*"
-                     "Directory Monitor Event:[\n\r]+"
-                     "Child = \\([^\n\r]+\\)[\n\r]+"
-                     "\\(Other = \\([^\n\r]+\\)[\n\r]+\\)?"
-                     "Event = \\([^[:blank:]]+\\)[\n\r]+"))
+           (concat "^[\n\r]*"
+                   "Directory Monitor Event:[\n\r]+"
+                   "Child = \\([^\n\r]+\\)[\n\r]+"
+                   "\\(Other = \\([^\n\r]+\\)[\n\r]+\\)?"
+                   "Event = \\([^[:blank:]]+\\)[\n\r]+")
            string)
       (let* ((file (match-string 1 string))
             (file1 (match-string 3 string))
@@ -3837,10 +3826,9 @@ Fall back to normal file name handler if no Tramp 
handler exists."
     (dolist (line (split-string string "[\n\r]+" 'omit))
       ;; Check, whether there is a problem.
       (unless (string-match
-              (eval-when-compile
-                (concat "^[^[:blank:]]+"
-                        "[[:blank:]]+\\([^[:blank:]]+\\)"
-                        "\\([[:blank:]]+\\([^\n\r]+\\)\\)?"))
+              (concat "^[^[:blank:]]+"
+                      "[[:blank:]]+\\([^[:blank:]]+\\)"
+                      "\\([[:blank:]]+\\([^\n\r]+\\)\\)?")
               line)
        (tramp-error proc 'file-notify-error "%s" line))
 
@@ -3876,11 +3864,10 @@ Fall back to normal file name handler if no Tramp 
handler exists."
          (goto-char (point-min))
          (forward-line)
          (when (looking-at
-                (eval-when-compile
-                  (concat "\\(?:^/[^[:space:]]*[[:space:]]\\)?"
-                          "[[:space:]]*\\([[:digit:]]+\\)"
-                          "[[:space:]]+\\([[:digit:]]+\\)"
-                          "[[:space:]]+\\([[:digit:]]+\\)")))
+                (concat "\\(?:^/[^[:space:]]*[[:space:]]\\)?"
+                        "[[:space:]]*\\([[:digit:]]+\\)"
+                        "[[:space:]]+\\([[:digit:]]+\\)"
+                        "[[:space:]]+\\([[:digit:]]+\\)"))
            (mapcar
             (lambda (d)
               (* d (tramp-get-connection-property v "df-blocksize" 0)))
@@ -3949,6 +3936,9 @@ hosts, or files, disagree."
               (tramp-shell-quote-argument v1-localname)
               (tramp-shell-quote-argument v2-localname))))))
 
+(defconst tramp-sunos-unames (regexp-opt '("SunOS 5.10" "SunOS 5.11"))
+  "Regexp to determine remote SunOS.")
+
 (defun tramp-find-executable
   (vec progname dirlist &optional ignore-tilde ignore-path)
   "Search for PROGNAME in $PATH and all directories mentioned in DIRLIST.
@@ -3970,7 +3960,7 @@ This function expects to be in the right *tramp* buffer."
       ;; therefore.
       (unless (or ignore-path
                  (string-match-p
-                  (eval-when-compile (regexp-opt '("SunOS 5.10" "SunOS 5.11")))
+                  tramp-sunos-unames
                   (tramp-get-connection-property vec "uname" "")))
        (tramp-send-command vec (format "which \\%s | wc -w" progname))
        (goto-char (point-min))
@@ -3988,12 +3978,11 @@ This function expects to be in the right *tramp* 
buffer."
            (setq dirlist (nreverse newdl))))
        (tramp-send-command
         vec
-        (format (eval-when-compile
-                  (concat "while read d; "
-                          "do if test -x $d/%s && test -f $d/%s; "
-                          "then echo tramp_executable $d/%s; "
-                          "break; fi; done <<'%s'\n"
-                          "%s\n%s"))
+        (format (concat "while read d; "
+                        "do if test -x $d/%s && test -f $d/%s; "
+                        "then echo tramp_executable $d/%s; "
+                        "break; fi; done <<'%s'\n"
+                        "%s\n%s")
                 progname progname progname
                 tramp-end-of-heredoc
                 (string-join dirlist "\n")
@@ -4146,10 +4135,9 @@ file exists and nonzero exit status otherwise."
       ;; initial probes to ensure the remote shell is usable.)
       (tramp-send-command
        vec (format
-           (eval-when-compile
-             (concat
-              "exec env TERM='%s' INSIDE_EMACS='%s,tramp:%s' "
-              "ENV=%s %s PROMPT_COMMAND='' PS1=%s PS2='' PS3='' %s %s"))
+           (concat
+            "exec env TERM='%s' INSIDE_EMACS='%s,tramp:%s' "
+            "ENV=%s %s PROMPT_COMMAND='' PS1=%s PS2='' PS3='' %s %s")
             tramp-terminal-type
             (or (getenv "INSIDE_EMACS") emacs-version) tramp-version
             (or (getenv-internal "ENV" tramp-remote-process-environment) "")
@@ -4199,8 +4187,7 @@ file exists and nonzero exit status otherwise."
                        ;; and Solaris is buggy.  We've got reports
                        ;; for "SunOS 5.10" and "SunOS 5.11" so far.
                        (string-match-p
-                        (eval-when-compile
-                          (regexp-opt '("SunOS 5.10" "SunOS 5.11")))
+                        tramp-sunos-unames
                         (tramp-get-connection-property vec "uname" "")))
 
                    (or (tramp-find-executable
@@ -4212,10 +4199,9 @@ file exists and nonzero exit status otherwise."
                            default-shell
                          (tramp-message
                           vec 2
-                          (eval-when-compile
-                            (concat
-                             "Couldn't find a remote shell which groks tilde "
-                             "expansion, using `%s'"))
+                          (concat
+                           "Couldn't find a remote shell which groks tilde "
+                           "expansion, using `%s'")
                           default-shell)))
 
                  default-shell)))
@@ -5223,7 +5209,7 @@ the exit status."
           "echo tramp_exit_status $?"
           (if subshell " )" "")))
   (with-current-buffer (tramp-get-connection-buffer vec)
-    (unless (tramp-search-regexp "tramp_exit_status [0-9]+")
+    (unless (tramp-search-regexp "tramp_exit_status [[:digit:]]+")
       (tramp-error
        vec 'file-error "Couldn't find exit status of `%s'" command))
     (skip-chars-forward "^ ")
@@ -5627,8 +5613,7 @@ Nonexistent directories are removed from spec."
     ;; stat on Solaris is buggy.  We've got reports for "SunOS 5.10"
     ;; and "SunOS 5.11" so far.
     (unless (string-match-p
-            (eval-when-compile (regexp-opt '("SunOS 5.10" "SunOS 5.11")))
-            (tramp-get-connection-property vec "uname" ""))
+            tramp-sunos-unames (tramp-get-connection-property vec "uname" ""))
       (tramp-message vec 5 "Finding a suitable `stat' command")
       (let ((result (tramp-find-executable
                     vec "stat" (tramp-get-remote-path vec)))
diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el
index 947e6a7..1b6af2a 100644
--- a/lisp/net/tramp-smb.el
+++ b/lisp/net/tramp-smb.el
@@ -875,23 +875,31 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
          (while (not (eobp))
            (cond
             ((looking-at
-              "Size:\\s-+\\([0-9]+\\)\\s-+Blocks:\\s-+[0-9]+\\s-+\\(\\w+\\)")
+              (concat
+               "Size:\\s-+\\([[:digit:]]+\\)\\s-+"
+               "Blocks:\\s-+[[:digit:]]+\\s-+\\(\\w+\\)"))
              (setq size (string-to-number (match-string 1))
                    id (if (string-equal "directory" (match-string 2)) t
                         (if (string-equal "symbolic" (match-string 2)) ""))))
             ((looking-at
-              "Inode:\\s-+\\([0-9]+\\)\\s-+Links:\\s-+\\([0-9]+\\)")
+              
"Inode:\\s-+\\([[:digit:]]+\\)\\s-+Links:\\s-+\\([[:digit:]]+\\)")
              (setq inode (string-to-number (match-string 1))
                    link (string-to-number (match-string 2))))
             ((looking-at
-              
"Access:\\s-+([0-9]+/\\(\\S-+\\))\\s-+Uid:\\s-+\\([0-9]+\\)\\s-+Gid:\\s-+\\([0-9]+\\)")
+              (concat
+               "Access:\\s-+([[:digit:]]+/\\(\\S-+\\))\\s-+"
+               "Uid:\\s-+\\([[:digit:]]+\\)\\s-+"
+               "Gid:\\s-+\\([[:digit:]]+\\)"))
              (setq mode (match-string 1)
                    uid (if (equal id-format 'string) (match-string 2)
                          (string-to-number (match-string 2)))
                    gid (if (equal id-format 'string) (match-string 3)
                          (string-to-number (match-string 3)))))
             ((looking-at
-              
"Access:\\s-+\\([0-9]+\\)-\\([0-9]+\\)-\\([0-9]+\\)\\s-+\\([0-9]+\\):\\([0-9]+\\):\\([0-9]+\\)")
+              (concat
+               "Access:\\s-+"
+               "\\([[:digit:]]+\\)-\\([[:digit:]]+\\)-\\([[:digit:]]+\\)\\s-+"
+               "\\([[:digit:]]+\\):\\([[:digit:]]+\\):\\([[:digit:]]+\\)"))
              (setq atime
                    (encode-time
                     (string-to-number (match-string 6)) ;; sec
@@ -901,7 +909,10 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
                     (string-to-number (match-string 2)) ;; month
                     (string-to-number (match-string 1))))) ;; year
             ((looking-at
-              
"Modify:\\s-+\\([0-9]+\\)-\\([0-9]+\\)-\\([0-9]+\\)\\s-+\\([0-9]+\\):\\([0-9]+\\):\\([0-9]+\\)")
+              (concat
+               "Modify:\\s-+"
+               "\\([[:digit:]]+\\)-\\([[:digit:]]+\\)-\\([[:digit:]]+\\)\\s-+"
+               "\\([[:digit:]]+\\):\\([[:digit:]]+\\):\\([[:digit:]]+\\)"))
              (setq mtime
                    (encode-time
                     (string-to-number (match-string 6)) ;; sec
@@ -911,7 +922,10 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
                     (string-to-number (match-string 2)) ;; month
                     (string-to-number (match-string 1))))) ;; year
             ((looking-at
-              
"Change:\\s-+\\([0-9]+\\)-\\([0-9]+\\)-\\([0-9]+\\)\\s-+\\([0-9]+\\):\\([0-9]+\\):\\([0-9]+\\)")
+              (concat
+               "Change:\\s-+"
+               "\\([[:digit:]]+\\)-\\([[:digit:]]+\\)-\\([[:digit:]]+\\)\\s-+"
+               "\\([[:digit:]]+\\):\\([[:digit:]]+\\):\\([[:digit:]]+\\)"))
              (setq ctime
                    (encode-time
                     (string-to-number (match-string 6)) ;; sec
@@ -987,10 +1001,9 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are 
completely ignored."
            (goto-char (point-min))
            (forward-line)
            (when (looking-at
-                  (eval-when-compile
-                    (concat "[[:space:]]*\\([[:digit:]]+\\)"
-                            " blocks of size \\([[:digit:]]+\\)"
-                            "\\. \\([[:digit:]]+\\) blocks available")))
+                  (concat "[[:space:]]*\\([[:digit:]]+\\)"
+                          " blocks of size \\([[:digit:]]+\\)"
+                          "\\. \\([[:digit:]]+\\) blocks available"))
              (setq blocksize (string-to-number (match-string 2))
                    total (* blocksize (string-to-number (match-string 1)))
                    avail (* blocksize (string-to-number (match-string 3)))))
@@ -1474,7 +1487,7 @@ component is used as the target of the symlink."
                  ;; This is meant for traces, and returning from the
                  ;; function.  No error is propagated outside, due to
                  ;; the `ignore-errors' closure.
-                 (unless (tramp-search-regexp "tramp_exit_status [0-9]+")
+                 (unless (tramp-search-regexp "tramp_exit_status [[:digit:]]+")
                    (tramp-error
                     v 'file-error
                     "Couldn't find exit status of `%s'" tramp-smb-acl-program))
@@ -1719,21 +1732,21 @@ Result is a list of (LOCALNAME MODE SIZE MONTH DAY TIME 
YEAR)."
 ;; Entries provided by smbclient DIR aren't fully regular.
 ;; They should have the format
 ;;
-;; \s-\{2,2}                              - leading spaces
+;; \s-\{2,2\}                             - leading spaces
 ;; \S-\(.*\S-\)\s-*                       - file name, 30 chars, left bound
 ;; \s-+[ADHRSV]*                          - permissions, 7 chars, right bound
 ;; \s-                                    - space delimiter
-;; \s-+[0-9]+                             - size, 8 chars, right bound
+;; \s-+[[:digit:]]+                       - size, 8 chars, right bound
 ;; \s-\{2,2\}                             - space delimiter
 ;; \w\{3,3\}                              - weekday
 ;; \s-                                    - space delimiter
 ;; \w\{3,3\}                              - month
 ;; \s-                                    - space delimiter
-;; [ 12][0-9]                             - day
+;; [ 12][[:digit:]]                       - day
 ;; \s-                                    - space delimiter
-;; [0-9]\{2,2\}:[0-9]\{2,2\}:[0-9]\{2,2\} - time
+;; [[:digit:]]\{2,2\}:[[:digit:]]\{2,2\}:[[:digit:]]\{2,2\} - time
 ;; \s-                                    - space delimiter
-;; [0-9]\{4,4\}                           - year
+;; [[:digit:]]\{4,4\}                     - year
 ;;
 ;; samba/src/client.c (http://samba.org/doxygen/samba/client_8c-source.html)
 ;; has function display_finfo:
@@ -1781,13 +1794,14 @@ are listed.  Result is the list (LOCALNAME MODE SIZE 
MTIME)."
       (cl-block nil
 
        ;; year.
-       (if (string-match "\\([0-9]+\\)$" line)
+       (if (string-match "\\([[:digit:]]+\\)$" line)
            (setq year (string-to-number (match-string 1 line))
                  line (substring line 0 -5))
          (cl-return))
 
        ;; time.
-       (if (string-match "\\([0-9]+\\):\\([0-9]+\\):\\([0-9]+\\)$" line)
+       (if (string-match
+            "\\([[:digit:]]+\\):\\([[:digit:]]+\\):\\([[:digit:]]+\\)$" line)
            (setq hour (string-to-number (match-string 1 line))
                  min  (string-to-number (match-string 2 line))
                  sec  (string-to-number (match-string 3 line))
@@ -1795,7 +1809,7 @@ are listed.  Result is the list (LOCALNAME MODE SIZE 
MTIME)."
          (cl-return))
 
        ;; day.
-       (if (string-match "\\([0-9]+\\)$" line)
+       (if (string-match "\\([[:digit:]]+\\)$" line)
            (setq day  (string-to-number (match-string 1 line))
                  line (substring line 0 -3))
          (cl-return))
@@ -1812,7 +1826,7 @@ are listed.  Result is the list (LOCALNAME MODE SIZE 
MTIME)."
          (cl-return))
 
        ;; size.
-       (if (string-match "\\([0-9]+\\)$" line)
+       (if (string-match "\\([[:digit:]]+\\)$" line)
            (let ((length (- (max 10 (1+ (length (match-string 1 line)))))))
              (setq size (string-to-number (match-string 1 line)))
              (when (string-match
diff --git a/lisp/net/tramp-sudoedit.el b/lisp/net/tramp-sudoedit.el
index 05242ff..98727dc 100644
--- a/lisp/net/tramp-sudoedit.el
+++ b/lisp/net/tramp-sudoedit.el
@@ -488,9 +488,8 @@ the result will be a local, non-Tramp, file name."
   (with-parsed-tramp-file-name filename nil
     (with-tramp-file-property v localname "file-selinux-context"
       (let ((context '(nil nil nil nil))
-           (regexp (eval-when-compile
-                     (concat "\\([a-z0-9_]+\\):" "\\([a-z0-9_]+\\):"
-                             "\\([a-z0-9_]+\\):" "\\([a-z0-9_]+\\)"))))
+           (regexp (concat "\\([[:alnum:]_]+\\):" "\\([[:alnum:]_]+\\):"
+                           "\\([[:alnum:]_]+\\):" "\\([[:alnum:]_]+\\)")))
        (when (and (tramp-sudoedit-remote-selinux-p v)
                   (tramp-sudoedit-send-command
                    v "ls" "-d" "-Z"
@@ -515,10 +514,9 @@ the result will be a local, non-Tramp, file name."
          (goto-char (point-min))
          (forward-line)
          (when (looking-at
-                (eval-when-compile
-                  (concat "[[:space:]]*\\([[:digit:]]+\\)"
-                          "[[:space:]]+\\([[:digit:]]+\\)"
-                          "[[:space:]]+\\([[:digit:]]+\\)")))
+                (concat "[[:space:]]*\\([[:digit:]]+\\)"
+                        "[[:space:]]+\\([[:digit:]]+\\)"
+                        "[[:space:]]+\\([[:digit:]]+\\)"))
            (list (string-to-number (match-string 1))
                  ;; The second value is the used size.  We need the
                  ;; free size.
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 1566162..cd35e3f 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -560,7 +560,7 @@ Sometimes the prompt is reported to look like \"login 
as:\"."
   ;; Allow also [] style prompts.  They can appear only during
   ;; connection initialization; Tramp redefines the prompt afterwards.
   (concat "\\(?:^\\|\r\\)"
-         "[^]#$%>\n]*#?[]#$%>] *\\(\e\\[[0-9;]*[a-zA-Z] *\\)*")
+         "[^]#$%>\n]*#?[]#$%>] *\\(\e\\[[[:digit:];]*[[:alpha:]] *\\)*")
   "Regexp to match prompts from remote shell.
 Normally, Tramp expects you to configure `shell-prompt-pattern'
 correctly, but sometimes it happens that you are connecting to a
@@ -601,7 +601,7 @@ The `sudo' program appears to insert a `^@' character into 
the prompt."
          "\\|"
          "^.*\\("
          ;; Here comes a list of regexes, separated by \\|
-         "Received signal [0-9]+"
+         "Received signal [[:digit:]]+"
          "\\).*")
   "Regexp matching a `login failed' message.
 The regexp should match at end of buffer."
@@ -797,9 +797,9 @@ Used in `tramp-make-tramp-file-name'.")
 Should always start with \"^\". Derived from `tramp-prefix-format'.")
 
 (defconst tramp-method-regexp-alist
-  '((default    . "[a-zA-Z0-9-]+")
+  '((default    . "[[:alnum:]-]+")
     (simplified . "")
-    (separate   . "[a-zA-Z0-9-]*"))
+    (separate   . "[[:alnum:]-]*"))
   "Alist mapping Tramp syntax to regexps matching methods identifiers.")
 
 (defun tramp-build-method-regexp ()
@@ -843,7 +843,7 @@ Derived from `tramp-postfix-method-format'.")
   "Regexp matching delimiter between user and domain names.
 Derived from `tramp-prefix-domain-format'.")
 
-(defconst tramp-domain-regexp "[a-zA-Z0-9_.-]+"
+(defconst tramp-domain-regexp "[[:alnum:]_.-]+"
   "Regexp matching domain names.")
 
 (defconst tramp-user-with-domain-regexp
@@ -860,7 +860,7 @@ Used in `tramp-make-tramp-file-name'.")
   "Regexp matching delimiter between user and host names.
 Derived from `tramp-postfix-user-format'.")
 
-(defconst tramp-host-regexp "[a-zA-Z0-9_.%-]+"
+(defconst tramp-host-regexp "[[:alnum:]_.%-]+"
   "Regexp matching host names.")
 
 (defconst tramp-prefix-ipv6-format-alist
@@ -888,7 +888,7 @@ Derived from `tramp-prefix-ipv6-format'.")
 ;; The following regexp is a bit sloppy.  But it shall serve our
 ;; purposes.  It covers also IPv4 mapped IPv6 addresses, like in
 ;; "::ffff:192.168.0.1".
-(defconst tramp-ipv6-regexp "\\(?:[a-zA-Z0-9]*:\\)+[a-zA-Z0-9.]+"
+(defconst tramp-ipv6-regexp "\\(?:[[:alnum:]]*:\\)+[[:alnum:].]+"
   "Regexp matching IPv6 addresses.")
 
 (defconst tramp-postfix-ipv6-format-alist
@@ -920,7 +920,7 @@ Derived from `tramp-postfix-ipv6-format'.")
   "Regexp matching delimiter between host names and port numbers.
 Derived from `tramp-prefix-port-format'.")
 
-(defconst tramp-port-regexp "[0-9]+"
+(defconst tramp-port-regexp "[[:digit:]]+"
   "Regexp matching port numbers.")
 
 (defconst tramp-host-with-port-regexp
@@ -1684,11 +1684,10 @@ version, the function does nothing."
       (format "*debug tramp/%s %s*" method host-port))))
 
 (defconst tramp-debug-outline-regexp
-  (eval-when-compile
-    (concat
-     "[0-9]+:[0-9]+:[0-9]+\\.[0-9]+ " ;; Timestamp.
-     "\\(?:\\(#<thread .+>\\) \\)?"   ;; Thread.
-     "[a-z0-9-]+ (\\([0-9]+\\)) #"))  ;; Function name, verbosity.
+  (concat
+   "[[:digit:]]+:[[:digit:]]+:[[:digit:]]+\\.[[:digit:]]+ " ;; Timestamp.
+   "\\(?:\\(#<thread .+>\\) \\)?" ;; Thread.
+   "[[:alnum:]-]+ (\\([[:digit:]]+\\)) #") ;; Function name, verbosity.
   "Used for highlighting Tramp debug buffers in `outline-mode'.")
 
 (defconst tramp-debug-font-lock-keywords
@@ -2074,7 +2073,7 @@ letter into the file name.  This function removes it."
   (save-match-data
     (let ((quoted (tramp-compat-file-name-quoted-p name 'top))
          (result (tramp-compat-file-name-unquote name 'top)))
-      (setq result (if (string-match "\\`[a-zA-Z]:/" result)
+      (setq result (if (string-match "\\`[[:alpha:]]:/" result)
                     (replace-match "/" nil t result) result))
       (if quoted (tramp-compat-file-name-quote result 'top) result))))
 
@@ -2938,7 +2937,7 @@ User is always nil."
   "Return a list of (user host) tuples allowed to access.
 User is always nil."
   (tramp-parse-shostkeys-sknownhosts
-   dirname (concat "^key_[0-9]+_\\(" tramp-host-regexp "\\)\\.pub$")))
+   dirname (concat "^key_[[:digit:]]+_\\(" tramp-host-regexp "\\)\\.pub$")))
 
 (defun tramp-parse-sknownhosts (dirname)
   "Return a list of (user host) tuples allowed to access.
@@ -3255,12 +3254,13 @@ User is always nil."
                (let ((candidate
                       (tramp-compat-file-name-unquote
                        (directory-file-name filename)))
+                     case-fold-search
                      tmpfile)
                  ;; Check, whether we find an existing file with
                  ;; lower case letters.  This avoids us to create a
                  ;; temporary file.
                  (while (and (string-match-p
-                              "[a-z]" (tramp-file-local-name candidate))
+                              "[[:lower:]]" (tramp-file-local-name candidate))
                              (not (file-exists-p candidate)))
                    (setq candidate
                          (directory-file-name
@@ -3269,8 +3269,8 @@ User is always nil."
                  ;; for comparison.  `make-nearby-temp-file' is added
                  ;; to Emacs 26+ like `file-name-case-insensitive-p',
                  ;; so there is no compatibility problem calling it.
-                 (unless
-                     (string-match-p "[a-z]" (tramp-file-local-name candidate))
+                 (unless (string-match-p
+                          "[[:lower:]]" (tramp-file-local-name candidate))
                    (setq tmpfile
                          (let ((default-directory
                                  (file-name-directory filename)))
@@ -4225,10 +4225,9 @@ performed successfully.  Any other value means an error."
              (tramp-get-connection-buffer vec)))
            ((eq exit 'process-died)
              (substitute-command-keys
-             (eval-when-compile
-               (concat
-                "Tramp failed to connect.  If this happens repeatedly, try\n"
-                "    `\\[tramp-cleanup-this-connection]'"))))
+             (concat
+              "Tramp failed to connect.  If this happens repeatedly, try\n"
+              "    `\\[tramp-cleanup-this-connection]'")))
            ((eq exit 'timeout)
             (format-message
              "Timeout reached, see buffer `%s' for details"
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index 08798d8..67ce3dc 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -101,30 +101,46 @@
 (defvar project-find-functions (list #'project-try-vc)
   "Special hook to find the project containing a given directory.
 Each functions on this hook is called in turn with one
-argument (the directory) and should return either nil to mean
-that it is not applicable, or a project instance.")
+argument, the directory in which to look, and should return
+either nil to mean that it is not applicable, or a project instance.
+The exact form of the project instance is up to each respective
+function; the only practical limitation is to use values that
+`cl-defmethod' can dispatch on, like a cons cell, or a list, or a
+CL struct.")
 
 (defvar project-current-inhibit-prompt nil
   "Non-nil to skip prompting the user in `project-current'.")
 
 ;;;###autoload
-(defun project-current (&optional maybe-prompt dir)
-  "Return the project instance in DIR or `default-directory'.
-When no project found in DIR, and MAYBE-PROMPT is non-nil, ask
-the user for a different project to look in."
-  (unless dir (setq dir default-directory))
-  (let ((pr (project--find-in-directory dir)))
+(defun project-current (&optional maybe-prompt directory)
+  "Return the project instance in DIRECTORY, defaulting to `default-directory'.
+
+When no project is found in that directory, the result depends on
+the value of MAYBE-PROMPT: if it is nil or omitted, return nil,
+else ask the user for a directory in which to look for the
+project, and if no project is found there, return a \"transient\"
+project instance.
+
+The \"transient\" project instance is a special kind of value
+which denotes a project rooted in that directory and includes all
+the files under the directory except for those that should be
+ignored (per `project-ignores').
+
+See the doc string of `project-find-functions' for the general form
+of the project instance object."
+  (unless directory (setq directory default-directory))
+  (let ((pr (project--find-in-directory directory)))
     (cond
      (pr)
      ((unless project-current-inhibit-prompt
         maybe-prompt)
-      (setq dir (project-prompt-project-dir)
-            pr (project--find-in-directory dir))))
+      (setq directory (project-prompt-project-dir)
+            pr (project--find-in-directory directory))))
     (when maybe-prompt
       (if pr
           (project--add-to-project-list-front pr)
-        (project--remove-from-project-list dir)
-        (setq pr (cons 'transient dir))))
+        (project--remove-from-project-list directory)
+        (setq pr (cons 'transient directory))))
     pr))
 
 (defun project--find-in-directory (dir)
@@ -802,9 +818,11 @@ Arguments the same as in `compile'."
 
 ;;;###autoload
 (defun project-switch-to-buffer ()
-  "Switch to another buffer that is related to the current project.
-A buffer is related to a project if `project-current' returns the
-same (equal) value when called in that buffer."
+  "Switch to another buffer belonging to the current project.
+This function prompts for another buffer, offering as candidates
+buffers that belong to the same project as the current buffer.
+Two buffers belong to the same project if their project instances,
+as reported by `project-current' in each buffer, are identical."
   (interactive)
   (let* ((pr (project-current t))
          (current-buffer (current-buffer))
@@ -849,6 +867,8 @@ any of the conditions will not be killed."
 ;;;###autoload
 (defun project-kill-buffers ()
   "Kill all live buffers belonging to the current project.
+Two buffers belong to the same project if their project instances,
+as reported by `project-current' in each buffer, are identical.
 Certain buffers may be \"spared\", see `project-kill-buffers-ignores'."
   (interactive)
   (let ((pr (project-current t)) bufs)
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 165463a..3af55be 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -34,7 +34,7 @@
 ;; Implements Syntax highlighting, Indentation, Movement, Shell
 ;; interaction, Shell completion, Shell virtualenv support, Shell
 ;; package support, Shell syntax highlighting, Pdb tracking, Symbol
-;; completion, Skeletons, FFAP, Code Check, Eldoc, Imenu.
+;; completion, Skeletons, FFAP, Code Check, ElDoc, Imenu.
 
 ;; Syntax highlighting: Fontification of code is provided and supports
 ;; python's triple quoted strings properly.
@@ -216,7 +216,7 @@
 ;; Code check: Check the current file for errors with `python-check'
 ;; using the program defined in `python-check-command'.
 
-;; Eldoc: returns documentation for object at point by using the
+;; ElDoc: returns documentation for object at point by using the
 ;; inferior python subprocess to inspect its documentation.  As you
 ;; might guessed you should run `python-shell-send-buffer' from time
 ;; to time to get better results too.
@@ -4474,7 +4474,7 @@ See `python-check-command' for the default."
                          (format python-check-buffer-name command)))))
 
 
-;;; Eldoc
+;;; ElDoc
 
 (defcustom python-eldoc-setup-code
   "def __PYDOC_get_help(obj):
@@ -4591,7 +4591,7 @@ fetching."
     (with-timeout (python-eldoc-function-timeout
                    (if python-eldoc-function-timeout-permanent
                        (progn
-                         (message "Eldoc echo-area display muted in this 
buffer, see `python-eldoc-function'")
+                         (message "ElDoc echo-area display muted in this 
buffer, see `python-eldoc-function'")
                          (setq python-eldoc-get-doc nil))
                      (message "`python-eldoc-function' timed out, see 
`python-eldoc-function-timeout'")))
       (python-eldoc--get-doc-at-point))))
diff --git a/m4/dup2.m4 b/m4/dup2.m4
index 21b1ecc..462bfd0 100644
--- a/m4/dup2.m4
+++ b/m4/dup2.m4
@@ -1,4 +1,4 @@
-#serial 25
+#serial 26
 dnl Copyright (C) 2002, 2005, 2007, 2009-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,
@@ -8,107 +8,94 @@ AC_DEFUN([gl_FUNC_DUP2],
 [
   AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
   AC_REQUIRE([AC_CANONICAL_HOST])
-  m4_ifdef([gl_FUNC_DUP2_OBSOLETE], [
-    AC_CHECK_FUNCS_ONCE([dup2])
-    if test $ac_cv_func_dup2 = no; then
-      HAVE_DUP2=0
-    fi
-  ], [
-    AC_DEFINE([HAVE_DUP2], [1], [Define to 1 if you have the 'dup2' function.])
-  ])
-  if test $HAVE_DUP2 = 1; then
-    AC_CACHE_CHECK([whether dup2 works], [gl_cv_func_dup2_works],
-      [AC_RUN_IFELSE([
-         AC_LANG_PROGRAM(
-           [[#include <errno.h>
-             #include <fcntl.h>
-             #include <limits.h>
-             #include <sys/resource.h>
-             #include <unistd.h>
-             #ifndef RLIM_SAVED_CUR
-             # define RLIM_SAVED_CUR RLIM_INFINITY
-             #endif
-             #ifndef RLIM_SAVED_MAX
-             # define RLIM_SAVED_MAX RLIM_INFINITY
-             #endif
-           ]],
-           [[int result = 0;
-             int bad_fd = INT_MAX;
-             struct rlimit rlim;
-             if (getrlimit (RLIMIT_NOFILE, &rlim) == 0
-                 && 0 <= rlim.rlim_cur && rlim.rlim_cur <= INT_MAX
-                 && rlim.rlim_cur != RLIM_INFINITY
-                 && rlim.rlim_cur != RLIM_SAVED_MAX
-                 && rlim.rlim_cur != RLIM_SAVED_CUR)
-               bad_fd = rlim.rlim_cur;
-             #ifdef FD_CLOEXEC
-               if (fcntl (1, F_SETFD, FD_CLOEXEC) == -1)
-                 result |= 1;
-             #endif
-             if (dup2 (1, 1) != 1)
-               result |= 2;
-             #ifdef FD_CLOEXEC
-               if (fcntl (1, F_GETFD) != FD_CLOEXEC)
-                 result |= 4;
-             #endif
-             close (0);
-             if (dup2 (0, 0) != -1)
-               result |= 8;
-             /* Many gnulib modules require POSIX conformance of EBADF.  */
-             if (dup2 (2, bad_fd) == -1 && errno != EBADF)
-               result |= 16;
-             /* Flush out some cygwin core dumps.  */
-             if (dup2 (2, -1) != -1 || errno != EBADF)
-               result |= 32;
-             dup2 (2, 255);
-             dup2 (2, 256);
-             /* On OS/2 kLIBC, dup2() does not work on a directory fd.  */
-             {
-               int fd = open (".", O_RDONLY);
-               if (fd == -1)
-                 result |= 64;
-               else if (dup2 (fd, fd + 1) == -1)
-                 result |= 128;
-
-               close (fd);
-             }
-             return result;]])
-        ],
-        [gl_cv_func_dup2_works=yes], [gl_cv_func_dup2_works=no],
-        [case "$host_os" in
-           mingw*) # on this platform, dup2 always returns 0 for success
-             gl_cv_func_dup2_works="guessing no" ;;
-           cygwin*) # on cygwin 1.5.x, dup2(1,1) returns 0
-             gl_cv_func_dup2_works="guessing no" ;;
-           aix* | freebsd*)
-                   # on AIX 7.1 and FreeBSD 6.1, dup2 (1,toobig) gives EMFILE,
-                   # not EBADF.
-             gl_cv_func_dup2_works="guessing no" ;;
-           haiku*) # on Haiku alpha 2, dup2(1, 1) resets FD_CLOEXEC.
-             gl_cv_func_dup2_works="guessing no" ;;
-           *-android*) # implemented using dup3(), which fails if oldfd == 
newfd
-             gl_cv_func_dup2_works="guessing no" ;;
-           os2*) # on OS/2 kLIBC, dup2() does not work on a directory fd.
-             gl_cv_func_dup2_works="guessing no" ;;
-           *) gl_cv_func_dup2_works="guessing yes" ;;
-         esac])
-      ])
-    case "$gl_cv_func_dup2_works" in
-      *yes) ;;
-      *)
-        REPLACE_DUP2=1
-        AC_CHECK_FUNCS([setdtablesize])
-        ;;
-    esac
-  fi
+  AC_CACHE_CHECK([whether dup2 works], [gl_cv_func_dup2_works],
+    [AC_RUN_IFELSE([
+       AC_LANG_PROGRAM(
+         [[#include <errno.h>
+           #include <fcntl.h>
+           #include <limits.h>
+           #include <sys/resource.h>
+           #include <unistd.h>
+           #ifndef RLIM_SAVED_CUR
+           # define RLIM_SAVED_CUR RLIM_INFINITY
+           #endif
+           #ifndef RLIM_SAVED_MAX
+           # define RLIM_SAVED_MAX RLIM_INFINITY
+           #endif
+         ]],
+         [[int result = 0;
+           int bad_fd = INT_MAX;
+           struct rlimit rlim;
+           if (getrlimit (RLIMIT_NOFILE, &rlim) == 0
+               && 0 <= rlim.rlim_cur && rlim.rlim_cur <= INT_MAX
+               && rlim.rlim_cur != RLIM_INFINITY
+               && rlim.rlim_cur != RLIM_SAVED_MAX
+               && rlim.rlim_cur != RLIM_SAVED_CUR)
+             bad_fd = rlim.rlim_cur;
+           #ifdef FD_CLOEXEC
+             if (fcntl (1, F_SETFD, FD_CLOEXEC) == -1)
+               result |= 1;
+           #endif
+           if (dup2 (1, 1) != 1)
+             result |= 2;
+           #ifdef FD_CLOEXEC
+             if (fcntl (1, F_GETFD) != FD_CLOEXEC)
+               result |= 4;
+           #endif
+           close (0);
+           if (dup2 (0, 0) != -1)
+             result |= 8;
+           /* Many gnulib modules require POSIX conformance of EBADF.  */
+           if (dup2 (2, bad_fd) == -1 && errno != EBADF)
+             result |= 16;
+           /* Flush out some cygwin core dumps.  */
+           if (dup2 (2, -1) != -1 || errno != EBADF)
+             result |= 32;
+           dup2 (2, 255);
+           dup2 (2, 256);
+           /* On OS/2 kLIBC, dup2() does not work on a directory fd.  */
+           {
+             int fd = open (".", O_RDONLY);
+             if (fd == -1)
+               result |= 64;
+             else if (dup2 (fd, fd + 1) == -1)
+               result |= 128;
+             close (fd);
+           }
+           return result;]])
+      ],
+      [gl_cv_func_dup2_works=yes], [gl_cv_func_dup2_works=no],
+      [case "$host_os" in
+         mingw*) # on this platform, dup2 always returns 0 for success
+           gl_cv_func_dup2_works="guessing no" ;;
+         cygwin*) # on cygwin 1.5.x, dup2(1,1) returns 0
+           gl_cv_func_dup2_works="guessing no" ;;
+         aix* | freebsd*)
+                 # on AIX 7.1 and FreeBSD 6.1, dup2 (1,toobig) gives EMFILE,
+                 # not EBADF.
+           gl_cv_func_dup2_works="guessing no" ;;
+         haiku*) # on Haiku alpha 2, dup2(1, 1) resets FD_CLOEXEC.
+           gl_cv_func_dup2_works="guessing no" ;;
+         *-android*) # implemented using dup3(), which fails if oldfd == newfd
+           gl_cv_func_dup2_works="guessing no" ;;
+         os2*) # on OS/2 kLIBC, dup2() does not work on a directory fd.
+           gl_cv_func_dup2_works="guessing no" ;;
+         *) gl_cv_func_dup2_works="guessing yes" ;;
+       esac])
+    ])
+  case "$gl_cv_func_dup2_works" in
+    *yes) ;;
+    *)
+      REPLACE_DUP2=1
+      AC_CHECK_FUNCS([setdtablesize])
+      ;;
+  esac
   dnl Replace dup2() for supporting the gnulib-defined fchdir() function,
   dnl to keep fchdir's bookkeeping up-to-date.
   m4_ifdef([gl_FUNC_FCHDIR], [
     gl_TEST_FCHDIR
     if test $HAVE_FCHDIR = 0; then
-      if test $HAVE_DUP2 = 1; then
-        REPLACE_DUP2=1
-      fi
+      REPLACE_DUP2=1
     fi
   ])
 ])
diff --git a/m4/getrandom.m4 b/m4/getrandom.m4
index 2a0034b..424c2fa 100644
--- a/m4/getrandom.m4
+++ b/m4/getrandom.m4
@@ -1,4 +1,4 @@
-# getrandom.m4 serial 6
+# getrandom.m4 serial 7
 dnl Copyright 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,
@@ -36,7 +36,9 @@ AC_DEFUN([gl_FUNC_GETRANDOM],
 
   case "$host_os" in
     mingw*)
-      AC_CHECK_HEADERS([bcrypt.h])
+      AC_CHECK_HEADERS([bcrypt.h], [], [],
+        [[#include <windows.h>
+        ]])
       AC_CACHE_CHECK([whether the bcrypt library is guaranteed to be present],
         [gl_cv_lib_assume_bcrypt],
         [AC_COMPILE_IFELSE(
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
index 5c92a07..f577a6f 100644
--- a/m4/gnulib-comp.m4
+++ b/m4/gnulib-comp.m4
@@ -118,6 +118,7 @@ AC_DEFUN([gl_EARLY],
   AC_REQUIRE([AC_SYS_LARGEFILE])
   # Code from module lchmod:
   # Code from module libc-config:
+  # Code from module libgmp:
   # Code from module limits-h:
   # Code from module localtime-buffer:
   # Code from module lstat:
@@ -240,7 +241,7 @@ AC_DEFUN([gl_INIT],
   gl_DIRENT_H
   gl_DOUBLE_SLASH_ROOT
   gl_FUNC_DUP2
-  if test $HAVE_DUP2 = 0 || test $REPLACE_DUP2 = 1; then
+  if test $REPLACE_DUP2 = 1; then
     AC_LIBOBJ([dup2])
     gl_PREREQ_DUP2
   fi
@@ -345,6 +346,10 @@ AC_DEFUN([gl_INIT],
   gl_INTTYPES_INCOMPLETE
   AC_REQUIRE([gl_LARGEFILE])
   gl___INLINE
+  gl_LIBGMP
+  if test -n "$GMP_H"; then
+    AC_LIBOBJ([mini-gmp-gnulib])
+  fi
   gl_LIMITS_H
   gl_FUNC_LSTAT
   if test $REPLACE_LSTAT = 1; then
@@ -465,6 +470,7 @@ AC_DEFUN([gl_INIT],
   gl_SYS_TYPES_H
   AC_PROG_MKDIR_P
   gl_FUNC_GEN_TEMPNAME
+  gl_MODULE_INDICATOR([tempname])
   gl_HEADER_TIME_H
   gl_TIME_R
   if test $HAVE_LOCALTIME_R = 0 || test $REPLACE_LOCALTIME_R = 1; then
@@ -1034,6 +1040,9 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/memmem.c
   lib/mempcpy.c
   lib/memrchr.c
+  lib/mini-gmp-gnulib.c
+  lib/mini-gmp.c
+  lib/mini-gmp.h
   lib/minmax.h
   lib/mkostemp.c
   lib/mktime-internal.h
@@ -1165,6 +1174,7 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/inttypes.m4
   m4/largefile.m4
   m4/lchmod.m4
+  m4/libgmp.m4
   m4/limits-h.m4
   m4/localtime-buffer.m4
   m4/lstat.m4
diff --git a/m4/lchmod.m4 b/m4/lchmod.m4
index b9e8a97..a86a304 100644
--- a/m4/lchmod.m4
+++ b/m4/lchmod.m4
@@ -1,4 +1,4 @@
-#serial 7
+#serial 8
 
 dnl Copyright (C) 2005-2006, 2008-2020 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
@@ -26,6 +26,5 @@ AC_DEFUN([gl_FUNC_LCHMOD],
 # Prerequisites of lib/lchmod.c.
 AC_DEFUN([gl_PREREQ_LCHMOD],
 [
-  AC_REQUIRE([AC_C_INLINE])
   :
 ])
diff --git a/m4/libgmp.m4 b/m4/libgmp.m4
new file mode 100644
index 0000000..b569bb7
--- /dev/null
+++ b/m4/libgmp.m4
@@ -0,0 +1,44 @@
+# Configure the GMP library or a replacement.
+
+dnl Copyright 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.
+
+AC_DEFUN([gl_LIBGMP],
+[
+  AC_ARG_WITH([libgmp],
+    [AS_HELP_STRING([--without-libgmp],
+       [do not use the GNU Multiple Precision (GMP) library;
+        this is the default on systems lacking libgmp.])])
+
+  AC_CHECK_HEADERS_ONCE([gmp.h])
+  GMP_H=gmp.h
+  LIB_GMP=
+
+  case $with_libgmp in
+    no) ;;
+    yes) GMP_H= LIB_GMP=-lgmp;;
+    *) if test "$ac_cv_header_gmp_h" = yes; then
+         gl_saved_LIBS=$LIBS
+         AC_SEARCH_LIBS([__gmpz_roinit_n], [gmp])
+         LIBS=$gl_saved_LIBS
+         case $ac_cv_search___gmpz_roinit_n in
+           'none needed')
+             GMP_H=;;
+           -*)
+             GMP_H= LIB_GMP=$ac_cv_search___gmpz_roinit_n;;
+         esac
+       fi;;
+  esac
+
+  if test -z "$GMP_H"; then
+    AC_DEFINE([HAVE_GMP], 1,
+      [Define to 1 if you have the GMP library instead of just the
+       mini-gmp replacement.])
+  fi
+
+  AC_SUBST([LIB_GMP])
+  AC_SUBST([GMP_H])
+  AM_CONDITIONAL([GL_GENERATE_GMP_H], [test -n "$GMP_H"])
+])
diff --git a/m4/manywarnings.m4 b/m4/manywarnings.m4
index 719bafb..d18da04 100644
--- a/m4/manywarnings.m4
+++ b/m4/manywarnings.m4
@@ -1,4 +1,4 @@
-# manywarnings.m4 serial 19
+# manywarnings.m4 serial 20
 dnl Copyright (C) 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,
@@ -21,7 +21,7 @@ AC_DEFUN([gl_MANYWARN_COMPLEMENT],
       *" $gl_warn_item "*)
         ;;
       *)
-        gl_warn_set="$gl_warn_set $gl_warn_item"
+        gl_AS_VAR_APPEND([gl_warn_set], [" $gl_warn_item"])
         ;;
     esac
   done
@@ -49,12 +49,12 @@ m4_defun([gl_MANYWARN_ALL_GCC(C)],
   AC_REQUIRE([AC_PROG_CC])
   if test -n "$GCC"; then
 
-    dnl Check if -W -Werror -Wno-missing-field-initializers is supported
+    dnl Check if -Wextra -Werror -Wno-missing-field-initializers is supported
     dnl with the current $CC $CFLAGS $CPPFLAGS.
     AC_CACHE_CHECK([whether -Wno-missing-field-initializers is supported],
       [gl_cv_cc_nomfi_supported],
       [gl_save_CFLAGS="$CFLAGS"
-       CFLAGS="$CFLAGS -W -Werror -Wno-missing-field-initializers"
+       CFLAGS="$CFLAGS -Wextra -Werror -Wno-missing-field-initializers"
        AC_COMPILE_IFELSE(
          [AC_LANG_PROGRAM([[]], [[]])],
          [gl_cv_cc_nomfi_supported=yes],
@@ -68,7 +68,7 @@ m4_defun([gl_MANYWARN_ALL_GCC(C)],
       AC_CACHE_CHECK([whether -Wno-missing-field-initializers is needed],
         [gl_cv_cc_nomfi_needed],
         [gl_save_CFLAGS="$CFLAGS"
-         CFLAGS="$CFLAGS -W -Werror"
+         CFLAGS="$CFLAGS -Wextra -Werror"
          AC_COMPILE_IFELSE(
            [AC_LANG_PROGRAM(
               [[int f (void)
@@ -105,153 +105,41 @@ m4_defun([gl_MANYWARN_ALL_GCC(C)],
   # To compare this list to your installed GCC's, run this Bash command:
   #
   # comm -3 \
-  #  <((sed -n 's/^  *\(-[^ 0-9][^ ]*\) .*/\1/p' manywarnings.m4; \
+  #  <((sed -n 's/^  *\(-[^ 0-9][^ ]*\).*/\1/p' manywarnings.m4; \
   #     awk '/^[^#]/ {print $1}' ../build-aux/gcc-warning.spec) | sort) \
   #  <(LC_ALL=C gcc --help=warnings | sed -n 's/^  \(-[^ ]*\) .*/\1/p' | sort)
 
-  gl_manywarn_set=
-  for gl_manywarn_item in -fno-common \
-    -W \
-    -Wabsolute-value \
-    -Waddress \
-    -Waddress-of-packed-member \
-    -Waggressive-loop-optimizations \
+  $1=
+  for gl_manywarn_item in -fanalyzer -fno-common \
     -Wall \
-    -Wanalyzer-double-fclose \
-    -Wanalyzer-double-free \
-    -Wanalyzer-exposure-through-output-file \
-    -Wanalyzer-file-leak \
-    -Wanalyzer-free-of-non-heap \
-    -Wanalyzer-malloc-leak \
-    -Wanalyzer-null-argument \
-    -Wanalyzer-null-dereference \
-    -Wanalyzer-possible-null-argument \
-    -Wanalyzer-possible-null-dereference \
-    -Wanalyzer-stale-setjmp-buffer \
-    -Wanalyzer-tainted-array-index \
-    -Wanalyzer-too-complex \
-    -Wanalyzer-unsafe-call-within-signal-handler \
-    -Wanalyzer-use-after-free \
-    -Wanalyzer-use-of-pointer-in-stale-stack-frame \
     -Warith-conversion \
-    -Wattribute-warning \
-    -Wattributes \
     -Wbad-function-cast \
-    -Wbool-compare \
-    -Wbool-operation \
-    -Wbuiltin-declaration-mismatch \
-    -Wbuiltin-macro-redefined \
-    -Wcannot-profile \
-    -Wcast-align \
     -Wcast-align=strict \
-    -Wcast-function-type \
-    -Wchar-subscripts \
-    -Wclobbered \
-    -Wcomment \
-    -Wcomments \
-    -Wcoverage-mismatch \
-    -Wcpp \
-    -Wdangling-else \
     -Wdate-time \
-    -Wdeprecated \
-    -Wdeprecated-declarations \
-    -Wdesignated-init \
     -Wdisabled-optimization \
-    -Wdiscarded-array-qualifiers \
-    -Wdiscarded-qualifiers \
-    -Wdiv-by-zero \
     -Wdouble-promotion \
     -Wduplicated-branches \
     -Wduplicated-cond \
-    -Wduplicate-decl-specifier \
-    -Wempty-body \
-    -Wendif-labels \
-    -Wenum-compare \
-    -Wenum-conversion \
-    -Wexpansion-to-defined \
     -Wextra \
-    -Wformat-contains-nul \
-    -Wformat-diag \
-    -Wformat-extra-args \
-    -Wformat-nonliteral \
-    -Wformat-security \
     -Wformat-signedness \
-    -Wformat-y2k \
-    -Wformat-zero-length \
-    -Wframe-address \
-    -Wfree-nonheap-object \
-    -Whsa \
-    -Wif-not-aligned \
-    -Wignored-attributes \
-    -Wignored-qualifiers \
-    -Wimplicit \
-    -Wimplicit-function-declaration \
-    -Wimplicit-int \
-    -Wincompatible-pointer-types \
     -Winit-self \
     -Winline \
-    -Wint-conversion \
-    -Wint-in-bool-context \
-    -Wint-to-pointer-cast \
-    -Winvalid-memory-model \
     -Winvalid-pch \
-    -Wlogical-not-parentheses \
     -Wlogical-op \
-    -Wmain \
-    -Wmaybe-uninitialized \
-    -Wmemset-elt-size \
-    -Wmemset-transposed-args \
-    -Wmisleading-indentation \
-    -Wmissing-attributes \
-    -Wmissing-braces \
     -Wmissing-declarations \
-    -Wmissing-field-initializers \
     -Wmissing-include-dirs \
-    -Wmissing-parameter-type \
-    -Wmissing-profile \
     -Wmissing-prototypes \
-    -Wmultichar \
-    -Wmultistatement-macros \
-    -Wnarrowing \
     -Wnested-externs \
-    -Wnonnull \
-    -Wnonnull-compare \
     -Wnull-dereference \
-    -Wodr \
-    -Wold-style-declaration \
     -Wold-style-definition \
     -Wopenmp-simd \
-    -Woverflow \
     -Woverlength-strings \
-    -Woverride-init \
     -Wpacked \
-    -Wpacked-bitfield-compat \
-    -Wpacked-not-aligned \
-    -Wparentheses \
     -Wpointer-arith \
-    -Wpointer-compare \
-    -Wpointer-sign \
-    -Wpointer-to-int-cast \
-    -Wpragmas \
-    -Wpsabi \
-    -Wrestrict \
-    -Wreturn-local-addr \
-    -Wreturn-type \
-    -Wscalar-storage-order \
-    -Wsequence-point \
     -Wshadow \
-    -Wshift-count-negative \
-    -Wshift-count-overflow \
-    -Wshift-negative-value \
-    -Wsizeof-array-argument \
-    -Wsizeof-pointer-div \
-    -Wsizeof-pointer-memaccess \
     -Wstack-protector \
-    -Wstrict-aliasing \
     -Wstrict-overflow \
     -Wstrict-prototypes \
-    -Wstring-compare \
-    -Wstringop-truncation \
     -Wsuggest-attribute=cold \
     -Wsuggest-attribute=const \
     -Wsuggest-attribute=format \
@@ -260,95 +148,63 @@ m4_defun([gl_MANYWARN_ALL_GCC(C)],
     -Wsuggest-attribute=pure \
     -Wsuggest-final-methods \
     -Wsuggest-final-types \
-    -Wswitch \
-    -Wswitch-bool \
-    -Wswitch-outside-range \
-    -Wswitch-unreachable \
     -Wsync-nand \
     -Wsystem-headers \
-    -Wtautological-compare \
     -Wtrampolines \
-    -Wtrigraphs \
-    -Wtype-limits \
     -Wuninitialized \
     -Wunknown-pragmas \
     -Wunsafe-loop-optimizations \
-    -Wunused \
-    -Wunused-but-set-parameter \
-    -Wunused-but-set-variable \
-    -Wunused-function \
-    -Wunused-label \
-    -Wunused-local-typedefs \
     -Wunused-macros \
-    -Wunused-parameter \
-    -Wunused-result \
-    -Wunused-value \
-    -Wunused-variable \
-    -Wvarargs \
     -Wvariadic-macros \
     -Wvector-operation-performance \
     -Wvla \
-    -Wvolatile-register-var \
     -Wwrite-strings \
-    -Wzero-length-bounds \
     \
     ; do
-    gl_manywarn_set="$gl_manywarn_set $gl_manywarn_item"
+    gl_AS_VAR_APPEND([$1], [" $gl_manywarn_item"])
   done
 
   # gcc --help=warnings outputs an unusual form for these options; list
   # them here so that the above 'comm' command doesn't report a false match.
-  # Would prefer "min (PTRDIFF_MAX, SIZE_MAX)", but it must be a literal.
-  # Also, AC_COMPUTE_INT requires it to fit in a long; it is 2**63 on
-  # the only platforms where it does not fit in a long, so make that
-  # a special case.
-  AC_MSG_CHECKING([max safe object size])
-  AC_COMPUTE_INT([gl_alloc_max],
-    [LONG_MAX < (PTRDIFF_MAX < (size_t) -1 ? PTRDIFF_MAX : (size_t) -1)
-     ? -1
-     : PTRDIFF_MAX < (size_t) -1 ? (long) PTRDIFF_MAX : (long) (size_t) -1],
-    [[#include <limits.h>
-      #include <stddef.h>
-      #include <stdint.h>
-    ]],
-    [gl_alloc_max=2147483647])
-  case $gl_alloc_max in
-    -1) gl_alloc_max=9223372036854775807;;
-  esac
-  AC_MSG_RESULT([$gl_alloc_max])
-  gl_manywarn_set="$gl_manywarn_set -Walloc-size-larger-than=$gl_alloc_max"
-  gl_manywarn_set="$gl_manywarn_set -Warray-bounds=2"
-  gl_manywarn_set="$gl_manywarn_set -Wattribute-alias=2"
-  gl_manywarn_set="$gl_manywarn_set -Wformat-overflow=2"
-  gl_manywarn_set="$gl_manywarn_set -Wformat-truncation=2"
-  gl_manywarn_set="$gl_manywarn_set -Wimplicit-fallthrough=5"
-  gl_manywarn_set="$gl_manywarn_set -Wnormalized=nfc"
-  gl_manywarn_set="$gl_manywarn_set -Wshift-overflow=2"
-  gl_manywarn_set="$gl_manywarn_set -Wstringop-overflow=2"
-  gl_manywarn_set="$gl_manywarn_set -Wunused-const-variable=2"
-  gl_manywarn_set="$gl_manywarn_set -Wvla-larger-than=4031"
+  gl_AS_VAR_APPEND([$1], [' -Warray-bounds=2'])
+  gl_AS_VAR_APPEND([$1], [' -Wattribute-alias=2'])
+  gl_AS_VAR_APPEND([$1], [' -Wformat-overflow=2'])
+  gl_AS_VAR_APPEND([$1], [' -Wformat=2'])
+  gl_AS_VAR_APPEND([$1], [' -Wformat-truncation=2'])
+  gl_AS_VAR_APPEND([$1], [' -Wimplicit-fallthrough=5'])
+  gl_AS_VAR_APPEND([$1], [' -Wshift-overflow=2'])
+  gl_AS_VAR_APPEND([$1], [' -Wunused-const-variable=2'])
+  gl_AS_VAR_APPEND([$1], [' -Wvla-larger-than=4031'])
 
   # These are needed for older GCC versions.
   if test -n "$GCC"; then
     case `($CC --version) 2>/dev/null` in
       'gcc (GCC) '[[0-3]].* | \
       'gcc (GCC) '4.[[0-7]].*)
-        gl_manywarn_set="$gl_manywarn_set -fdiagnostics-show-option"
-        gl_manywarn_set="$gl_manywarn_set -funit-at-a-time"
+        gl_AS_VAR_APPEND([$1], [' -fdiagnostics-show-option'])
+        gl_AS_VAR_APPEND([$1], [' -funit-at-a-time'])
           ;;
     esac
   fi
 
   # Disable specific options as needed.
   if test "$gl_cv_cc_nomfi_needed" = yes; then
-    gl_manywarn_set="$gl_manywarn_set -Wno-missing-field-initializers"
+    gl_AS_VAR_APPEND([$1], [' -Wno-missing-field-initializers'])
   fi
 
   if test "$gl_cv_cc_uninitialized_supported" = no; then
-    gl_manywarn_set="$gl_manywarn_set -Wno-uninitialized"
+    gl_AS_VAR_APPEND([$1], [' -Wno-uninitialized'])
   fi
 
-  $1=$gl_manywarn_set
+  # Some warnings have too many false alarms in GCC 10.1.
+  # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93695
+  gl_AS_VAR_APPEND([$1], [' -Wno-analyzer-double-free'])
+  # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94458
+  gl_AS_VAR_APPEND([$1], [' -Wno-analyzer-malloc-leak'])
+  # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94851
+  gl_AS_VAR_APPEND([$1], [' -Wno-analyzer-null-dereference'])
+  # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95758
+  gl_AS_VAR_APPEND([$1], [' -Wno-analyzer-use-after-free'])
 
   AC_LANG_POP([C])
 ])
diff --git a/m4/string_h.m4 b/m4/string_h.m4
index cc51337..516b346 100644
--- a/m4/string_h.m4
+++ b/m4/string_h.m4
@@ -5,7 +5,7 @@
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# serial 23
+# serial 24
 
 # Written by Paul Eggert.
 
@@ -87,7 +87,6 @@ AC_DEFUN([gl_HEADER_STRING_H_DEFAULTS],
   HAVE_EXPLICIT_BZERO=1;        AC_SUBST([HAVE_EXPLICIT_BZERO])
   HAVE_FFSL=1;                  AC_SUBST([HAVE_FFSL])
   HAVE_FFSLL=1;                 AC_SUBST([HAVE_FFSLL])
-  HAVE_MEMCHR=1;                AC_SUBST([HAVE_MEMCHR])
   HAVE_DECL_MEMMEM=1;           AC_SUBST([HAVE_DECL_MEMMEM])
   HAVE_MEMPCPY=1;               AC_SUBST([HAVE_MEMPCPY])
   HAVE_DECL_MEMRCHR=1;          AC_SUBST([HAVE_DECL_MEMRCHR])
diff --git a/m4/sys_stat_h.m4 b/m4/sys_stat_h.m4
index 3efba5a..929144d 100644
--- a/m4/sys_stat_h.m4
+++ b/m4/sys_stat_h.m4
@@ -1,4 +1,4 @@
-# sys_stat_h.m4 serial 33   -*- Autoconf -*-
+# sys_stat_h.m4 serial 34   -*- Autoconf -*-
 dnl Copyright (C) 2006-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,
@@ -46,8 +46,8 @@ AC_DEFUN([gl_HEADER_SYS_STAT_H],
   dnl Check for declarations of anything we want to poison if the
   dnl corresponding gnulib module is not in use.
   gl_WARN_ON_USE_PREPARE([[#include <sys/stat.h>
-    ]], [fchmodat fstat fstatat futimens lchmod lstat mkdirat mkfifo mkfifoat
-    mknod mknodat stat utimensat])
+    ]], [fchmodat fstat fstatat futimens getumask lchmod lstat
+    mkdirat mkfifo mkfifoat mknod mknodat stat utimensat])
 
   AC_REQUIRE([AC_C_RESTRICT])
 ])
@@ -68,6 +68,7 @@ AC_DEFUN([gl_SYS_STAT_H_DEFAULTS],
   GNULIB_FSTAT=0;       AC_SUBST([GNULIB_FSTAT])
   GNULIB_FSTATAT=0;     AC_SUBST([GNULIB_FSTATAT])
   GNULIB_FUTIMENS=0;    AC_SUBST([GNULIB_FUTIMENS])
+  GNULIB_GETUMASK=0;    AC_SUBST([GNULIB_GETUMASK])
   GNULIB_LCHMOD=0;      AC_SUBST([GNULIB_LCHMOD])
   GNULIB_LSTAT=0;       AC_SUBST([GNULIB_LSTAT])
   GNULIB_MKDIRAT=0;     AC_SUBST([GNULIB_MKDIRAT])
@@ -82,6 +83,7 @@ AC_DEFUN([gl_SYS_STAT_H_DEFAULTS],
   HAVE_FCHMODAT=1;      AC_SUBST([HAVE_FCHMODAT])
   HAVE_FSTATAT=1;       AC_SUBST([HAVE_FSTATAT])
   HAVE_FUTIMENS=1;      AC_SUBST([HAVE_FUTIMENS])
+  HAVE_GETUMASK=1;      AC_SUBST([HAVE_GETUMASK])
   HAVE_LCHMOD=1;        AC_SUBST([HAVE_LCHMOD])
   HAVE_LSTAT=1;         AC_SUBST([HAVE_LSTAT])
   HAVE_MKDIRAT=1;       AC_SUBST([HAVE_MKDIRAT])
diff --git a/m4/unistd_h.m4 b/m4/unistd_h.m4
index dfa38f8..b4734da 100644
--- a/m4/unistd_h.m4
+++ b/m4/unistd_h.m4
@@ -1,4 +1,4 @@
-# unistd_h.m4 serial 80
+# unistd_h.m4 serial 81
 dnl Copyright (C) 2006-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,
@@ -120,7 +120,6 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS],
   dnl Assume proper GNU behavior unless another module says otherwise.
   HAVE_CHOWN=1;           AC_SUBST([HAVE_CHOWN])
   HAVE_COPY_FILE_RANGE=1; AC_SUBST([HAVE_COPY_FILE_RANGE])
-  HAVE_DUP2=1;            AC_SUBST([HAVE_DUP2])
   HAVE_DUP3=1;            AC_SUBST([HAVE_DUP3])
   HAVE_EUIDACCESS=1;      AC_SUBST([HAVE_EUIDACCESS])
   HAVE_FACCESSAT=1;       AC_SUBST([HAVE_FACCESSAT])
diff --git a/src/Makefile.in b/src/Makefile.in
index 8570918..2f373d3 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -323,8 +323,7 @@ INTERVALS_H = dispextern.h intervals.h composite.h
 
 GETLOADAVG_LIBS = @GETLOADAVG_LIBS@
 
-GMP_LIB = @GMP_LIB@
-GMP_OBJ = @GMP_OBJ@
+LIB_GMP = @LIB_GMP@
 
 LIBGCCJIT = @LIBGCCJIT_LIB@
 
@@ -536,7 +535,7 @@ LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) 
$(LIBIMAGE) \
    $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(HARFBUZZ_LIBS) $(LIBOTF_LIBS) 
$(M17N_FLT_LIBS) \
    $(LIBGNUTLS_LIBS) $(LIB_PTHREAD) $(GETADDRINFO_A_LIBS) $(LCMS2_LIBS) \
    $(NOTIFY_LIBS) $(LIB_MATH) $(LIBZ) $(LIBMODULES) $(LIBSYSTEMD_LIBS) \
-   $(JSON_LIBS) $(GMP_LIB) $(LIBGCCJIT)
+   $(JSON_LIBS) $(LIB_GMP) $(LIBGCCJIT)
 
 ## FORCE it so that admin/unidata can decide whether this file is
 ## up-to-date.  Although since charprop depends on bootstrap-emacs,
diff --git a/src/bignum.h b/src/bignum.h
index 4a906c3..251a19e 100644
--- a/src/bignum.h
+++ b/src/bignum.h
@@ -22,12 +22,7 @@ along with GNU Emacs.  If not, see 
<https://www.gnu.org/licenses/>.  */
 #ifndef BIGNUM_H
 #define BIGNUM_H
 
-#ifdef HAVE_GMP
-# include <gmp.h>
-#else
-# include "mini-gmp.h"
-#endif
-
+#include <gmp.h>
 #include "lisp.h"
 
 /* Number of data bits in a limb.  */
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 5d1ce6d..1fe160a 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -17,6 +17,13 @@ GNU General Public License for more details.
 You should have received a copy of the GNU General Public License
 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 
+/* FIXME: This code is problematic; it misuses GTK, so the GTK
+   developers don't think they should fix the resulting problems in GTK
+   itself.  The right way to fix this is by rewriting the code in Emacs
+   to use GTK3 properly.  As of 2020, there is a project to do this.
+   Talk with Yuuki Harano <masm+emacs@masm11.me> if you are interested
+   in doing substantial work on this.  */
+
 #include <config.h>
 
 #ifdef USE_GTK
diff --git a/src/mini-gmp-emacs.c b/src/mini-gmp-emacs.c
deleted file mode 100644
index b8399b0..0000000
--- a/src/mini-gmp-emacs.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Tailor mini-gmp.c for GNU Emacs
-
-Copyright 2018-2020 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or (at
-your option) any later version.
-
-GNU Emacs is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
-
-#include <config.h>
-
-#include <stddef.h>
-
-/* Pacify GCC -Wsuggest-attribute=malloc.  */
-static void *gmp_default_alloc (size_t) ATTRIBUTE_MALLOC;
-
-/* Pacify GCC -Wunused-variable for variables used only in 'assert' calls.  */
-#if defined NDEBUG && GNUC_PREREQ (4, 6, 0)
-# pragma GCC diagnostic ignored "-Wunused-variable"
-#endif
-
-#include "mini-gmp.c"
diff --git a/src/xdisp.c b/src/xdisp.c
index 97c55cd..eb7f3e7 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -26387,7 +26387,7 @@ decode_mode_spec (struct window *w, register int c, int 
field_width,
        height = WINDOW_TOTAL_LINES (w);
        /* We cannot cope with w->start being outside of the
           accessible portion of the buffer; in particular,
-          display_count_lines call below will infloop if called with
+          display_count_lines call below might infloop if called with
           startpos_byte outside of the [BEGV_BYTE..ZV_BYTE] region.
           Such w->start means we were called in some "creative" way
           when the buffer's restriction was changed, but the window
diff --git a/test/Makefile.in b/test/Makefile.in
index f03c194..c484067 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -255,12 +255,10 @@ else
 FPIC_CFLAGS = -fPIC
 endif
 
-GMP_LIB = @GMP_LIB@
-GMP_OBJ = $(if @GMP_OBJ@, ../src/@GMP_OBJ@)
+GMP_H = @GMP_H@
+LIB_GMP = @LIB_GMP@
 
-# Note: emacs-module.h is generated from emacs-module.h.in, hence we
-# look in ../src, not $(srcdir)/../src.
-MODULE_CFLAGS = -I../src -I$(srcdir)/../lib \
+MODULE_CFLAGS = -I../src -I$(srcdir)/../src -I../lib -I$(srcdir)/../lib \
   $(FPIC_CFLAGS) $(PROFILING_CFLAGS) \
   $(WARN_CFLAGS) $(WERROR_CFLAGS) $(CFLAGS)
 
@@ -273,7 +271,8 @@ src/emacs-module-tests.log src/emacs-module-tests.elc: 
$(test_module)
 $(test_module): $(test_module:${SO}=.c) ../src/emacs-module.h
        $(AM_V_at)${MKDIR_P} $(dir $@)
        $(AM_V_CCLD)$(CC) -shared $(CPPFLAGS) $(MODULE_CFLAGS) $(LDFLAGS) \
-         -o $@ $< $(GMP_LIB) $(GMP_OBJ:.o=.c) \
+         -o $@ $< $(LIB_GMP) \
+         $(and $(GMP_H),$(srcdir)/../lib/mini-gmp-gnulib.c) \
          $(srcdir)/../lib/timespec.c $(srcdir)/../lib/gettime.c
 endif
 
diff --git a/test/data/emacs-module/mod-test.c 
b/test/data/emacs-module/mod-test.c
index 5e3112f..1e64bcd 100644
--- a/test/data/emacs-module/mod-test.c
+++ b/test/data/emacs-module/mod-test.c
@@ -43,12 +43,7 @@ uintptr_t _beginthread (void (__cdecl *)(void *), unsigned, 
void *);
 # include <unistd.h>
 #endif
 
-#ifdef HAVE_GMP
 #include <gmp.h>
-#else
-#include "mini-gmp.h"
-#endif
-
 #include <emacs-module.h>
 
 #include "timespec.h"
diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el
index 1f24ba2..34782e7 100644
--- a/test/lisp/net/tramp-tests.el
+++ b/test/lisp/net/tramp-tests.el
@@ -6035,18 +6035,22 @@ Use the `ls' command."
        "银河系漫游指南系列"
        "Автостопом по гала́ктике"
        ;; Use codepoints without a name.  See Bug#31272.
-       "™›šbung")
+       "™›šbung"
+       ;; Use codepoints from Supplementary Multilingual Plane (U+10000
+       ;; to U+1FFFF).
+       "🌈🍒👋")
 
       (when (tramp--test-expensive-test)
        (delete-dups
         (mapcar
-         ;; Use all available language specific snippets.  Filter out
-         ;; strings which use unencodable characters.
+         ;; Use all available language specific snippets.
          (lambda (x)
            (and
             (stringp (setq x (eval (get-language-info (car x) 'sample-text))))
-            (not (unencodable-char-position
-                  0 (length x) file-name-coding-system nil x))
+            ;; Filter out strings which use unencodable characters.
+            (not (and (or (tramp--test-gvfs-p) (tramp--test-smb-p))
+                      (unencodable-char-position
+                       0 (length x) file-name-coding-system nil x)))
             ;; ?\n and ?/ shouldn't be part of any file name.  ?\t,
             ;; ?. and ?? do not work for "smb" method.
             (replace-regexp-in-string "[\t\n/.?]" "" x)))
diff --git a/test/lisp/progmodes/python-tests.el 
b/test/lisp/progmodes/python-tests.el
index 60cd6ea..6b3e636 100644
--- a/test/lisp/progmodes/python-tests.el
+++ b/test/lisp/progmodes/python-tests.el
@@ -3553,7 +3553,7 @@ def foo():
 ;;; Code check
 
 
-;;; Eldoc
+;;; ElDoc
 
 (ert-deftest python-eldoc--get-symbol-at-point-1 ()
   "Test paren handling."
diff --git a/test/src/emacs-module-tests.el b/test/src/emacs-module-tests.el
index 6851b89..411b450 100644
--- a/test/src/emacs-module-tests.el
+++ b/test/src/emacs-module-tests.el
@@ -288,6 +288,9 @@ during garbage collection."
   (with-temp-buffer
     (let ((standard-output (current-buffer)))
       (describe-function-1 #'mod-test-sum)
+      (goto-char (point-min))
+      (while (re-search-forward "`[^']*/data/emacs-module/" nil t)
+        (replace-match "`data/emacs-module/"))
       (should (equal
                (buffer-substring-no-properties 1 (point-max))
                (format "a module function in `data/emacs-module/mod-test%s'.



reply via email to

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