gawk-diffs
[Top][All Lists]
Advanced

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

[SCM] gawk branch, gawk-5.1-stable, updated. gawk-4.1.0-4208-g33ef3ac


From: Arnold Robbins
Subject: [SCM] gawk branch, gawk-5.1-stable, updated. gawk-4.1.0-4208-g33ef3ac
Date: Mon, 8 Feb 2021 02:05:12 -0500 (EST)

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "gawk".

The branch, gawk-5.1-stable has been updated
       via  33ef3ac7854adece095e69ea8fb0e70fb1feeea6 (commit)
      from  04e5d7b0199fd98cbb7505519a9e8210d6c84eb2 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://git.sv.gnu.org/cgit/gawk.git/commit/?id=33ef3ac7854adece095e69ea8fb0e70fb1feeea6

commit 33ef3ac7854adece095e69ea8fb0e70fb1feeea6
Author: Arnold D. Robbins <arnold@skeeve.com>
Date:   Mon Feb 8 09:04:43 2021 +0200

    Updates from GNULIB, including major work on regex.

diff --git a/helpers/ChangeLog b/helpers/ChangeLog
index eb94f69..ed66051 100644
--- a/helpers/ChangeLog
+++ b/helpers/ChangeLog
@@ -1,3 +1,7 @@
+2021-02-08         Arnold D. Robbins     <arnold@skeeve.com>
+
+       * update-support.sh: Update list of files to copy over.
+
 2020-08-12         Arnold D. Robbins     <arnold@skeeve.com>
 
        * update-support.sh: New file.
diff --git a/helpers/update-support.sh b/helpers/update-support.sh
index 122ef89..a85d86a 100755
--- a/helpers/update-support.sh
+++ b/helpers/update-support.sh
@@ -25,7 +25,8 @@ regex.h
 regex_internal.c
 regex_internal.h
 verify.h
-xalloc.h"
+malloc/dynarray.h
+malloc/dynarray-skeleton.c"
 
 for i in $FILE_LIST
 do
diff --git a/support/ChangeLog b/support/ChangeLog
index 7d23411..a61893b 100644
--- a/support/ChangeLog
+++ b/support/ChangeLog
@@ -1,3 +1,12 @@
+2021-02-08         Arnold D. Robbins     <arnold@skeeve.com>
+
+       * cdefs.h, dfa.c, dfa.h, flexmember.h, intprops.h, libc-config.h,
+       localeinfo.c, localeinfo.h, regcomp.c, regex.c, regex.h,
+       regex_internal.c, regex_internal.h, regexec.c, verify.h: Sync
+       from GNULIB.
+       * attribute.h, dynarray.h: New files.
+       * malloc/dynarray.h, malloc/dynarray-skeleton.c: New files from GNULIB.
+
 2021-01-08         Arnold D. Robbins     <arnold@skeeve.com>
 
        * random.h (initstate, setstate, srandom): Add declarations.
diff --git a/support/attribute.h b/support/attribute.h
new file mode 100644
index 0000000..80c3c50
--- /dev/null
+++ b/support/attribute.h
@@ -0,0 +1 @@
+#define FALLTHROUGH ((void) 0)
diff --git a/support/cdefs.h b/support/cdefs.h
index b4ac4df..6f12c79 100644
--- a/support/cdefs.h
+++ b/support/cdefs.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992-2020 Free Software Foundation, Inc.
+/* Copyright (C) 1992-2021 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -25,7 +25,7 @@
 
 /* The GNU libc does not support any K&R compilers or the traditional mode
    of ISO C compilers anymore.  Check for some of the combinations not
-   anymore supported.  */
+   supported anymore.  */
 #if defined __GNUC__ && !defined __STDC__
 # error "You need a ISO C conforming compiler to use the glibc headers"
 #endif
@@ -34,31 +34,26 @@
 #undef __P
 #undef __PMT
 
-/* Compilers that are not clang may object to
-       #if defined __clang__ && __has_attribute(...)
-   even though they do not need to evaluate the right-hand side of the &&.  */
-#if defined __clang__ && defined __has_attribute
-# define __glibc_clang_has_attribute(name) __has_attribute (name)
+/* Compilers that lack __has_attribute may object to
+       #if defined __has_attribute && __has_attribute (...)
+   even though they do not need to evaluate the right-hand side of the &&.
+   Similarly for __has_builtin, etc.  */
+#if (defined __has_attribute \
+     && (!defined __clang_minor__ \
+         || 3 < __clang_major__ + (5 <= __clang_minor__)))
+# define __glibc_has_attribute(attr) __has_attribute (attr)
 #else
-# define __glibc_clang_has_attribute(name) 0
+# define __glibc_has_attribute(attr) 0
 #endif
-
-/* Compilers that are not clang may object to
-       #if defined __clang__ && __has_builtin(...)
-   even though they do not need to evaluate the right-hand side of the &&.  */
-#if defined __clang__ && defined __has_builtin
-# define __glibc_clang_has_builtin(name) __has_builtin (name)
+#ifdef __has_builtin
+# define __glibc_has_builtin(name) __has_builtin (name)
 #else
-# define __glibc_clang_has_builtin(name) 0
+# define __glibc_has_builtin(name) 0
 #endif
-
-/* Compilers that are not clang may object to
-       #if defined __clang__ && __has_extension(...)
-   even though they do not need to evaluate the right-hand side of the &&.  */
-#if defined __clang__ && defined __has_extension
-# define __glibc_clang_has_extension(ext) __has_extension (ext)
+#ifdef __has_extension
+# define __glibc_has_extension(ext) __has_extension (ext)
 #else
-# define __glibc_clang_has_extension(ext) 0
+# define __glibc_has_extension(ext) 0
 #endif
 
 #if defined __GNUC__ || defined __clang__
@@ -74,22 +69,26 @@
 # endif
 
 /* GCC can always grok prototypes.  For C++ programs we add throw()
-   to help it optimize the function calls.  But this works only with
+   to help it optimize the function calls.  But this only works with
    gcc 2.8.x and egcs.  For gcc 3.4 and up we even mark C functions
    as non-throwing using a function attribute since programs can use
    the -fexceptions options for C code as well.  */
 # if !defined __cplusplus \
-     && (__GNUC_PREREQ (3, 4) || __glibc_clang_has_attribute (__nothrow__))
+     && (__GNUC_PREREQ (3, 4) || __glibc_has_attribute (__nothrow__))
 #  define __THROW      __attribute__ ((__nothrow__ __LEAF))
 #  define __THROWNL    __attribute__ ((__nothrow__))
 #  define __NTH(fct)   __attribute__ ((__nothrow__ __LEAF)) fct
 #  define __NTHNL(fct)  __attribute__ ((__nothrow__)) fct
 # else
 #  if defined __cplusplus && (__GNUC_PREREQ (2,8) || __clang_major >= 4)
-#   define __THROW     throw ()
-#   define __THROWNL   throw ()
-#   define __NTH(fct)  __LEAF_ATTR fct throw ()
-#   define __NTHNL(fct) fct throw ()
+#   if __cplusplus >= 201103L
+#    define __THROW    noexcept (true)
+#   else
+#    define __THROW    throw ()
+#   endif
+#   define __THROWNL   __THROW
+#   define __NTH(fct)  __LEAF_ATTR fct __THROW
+#   define __NTHNL(fct) fct __THROW
 #  else
 #   define __THROW
 #   define __THROWNL
@@ -142,24 +141,20 @@
 #define __bos(ptr) __builtin_object_size (ptr, __USE_FORTIFY_LEVEL > 1)
 #define __bos0(ptr) __builtin_object_size (ptr, 0)
 
+/* Use __builtin_dynamic_object_size at _FORTIFY_SOURCE=3 when available.  */
+#if __USE_FORTIFY_LEVEL == 3 && __glibc_clang_prereq (9, 0)
+# define __glibc_objsize0(__o) __builtin_dynamic_object_size (__o, 0)
+# define __glibc_objsize(__o) __builtin_dynamic_object_size (__o, 1)
+#else
+# define __glibc_objsize0(__o) __bos0 (__o)
+# define __glibc_objsize(__o) __bos (__o)
+#endif
+
 #if __GNUC_PREREQ (4,3)
-# define __warndecl(name, msg) \
-  extern void name (void) __attribute__((__warning__ (msg)))
 # define __warnattr(msg) __attribute__((__warning__ (msg)))
 # define __errordecl(name, msg) \
   extern void name (void) __attribute__((__error__ (msg)))
-#elif __glibc_clang_has_attribute (__diagnose_if__) && 0
-/* These definitions are not enabled, because they produce bogus warnings
-   in the glibc Fortify functions.  These functions are written in a style
-   that works with GCC.  In order to work with clang, these functions would
-   need to be modified.  */
-# define __warndecl(name, msg) \
-  extern void name (void) __attribute__((__diagnose_if__ (1, msg, "warning")))
-# define __warnattr(msg) __attribute__((__diagnose_if__ (1, msg, "warning")))
-# define __errordecl(name, msg) \
-  extern void name (void) __attribute__((__diagnose_if__ (1, msg, "error")))
 #else
-# define __warndecl(name, msg) extern void name (void)
 # define __warnattr(msg)
 # define __errordecl(name, msg) extern void name (void)
 #endif
@@ -233,7 +228,7 @@
 /* At some point during the gcc 2.96 development the `malloc' attribute
    for functions was introduced.  We don't want to use it unconditionally
    (although this would be possible) since it generates warnings.  */
-#if __GNUC_PREREQ (2,96) || __glibc_clang_has_attribute (__malloc__)
+#if __GNUC_PREREQ (2,96) || __glibc_has_attribute (__malloc__)
 # define __attribute_malloc__ __attribute__ ((__malloc__))
 #else
 # define __attribute_malloc__ /* Ignore */
@@ -251,23 +246,31 @@
 /* At some point during the gcc 2.96 development the `pure' attribute
    for functions was introduced.  We don't want to use it unconditionally
    (although this would be possible) since it generates warnings.  */
-#if __GNUC_PREREQ (2,96) || __glibc_clang_has_attribute (__pure__)
+#if __GNUC_PREREQ (2,96) || __glibc_has_attribute (__pure__)
 # define __attribute_pure__ __attribute__ ((__pure__))
 #else
 # define __attribute_pure__ /* Ignore */
 #endif
 
 /* This declaration tells the compiler that the value is constant.  */
-#if __GNUC_PREREQ (2,5) || __glibc_clang_has_attribute (__const__)
+#if __GNUC_PREREQ (2,5) || __glibc_has_attribute (__const__)
 # define __attribute_const__ __attribute__ ((__const__))
 #else
 # define __attribute_const__ /* Ignore */
 #endif
 
+#if defined __STDC_VERSION__ && 201710L < __STDC_VERSION__
+# define __attribute_maybe_unused__ [[__maybe_unused__]]
+#elif __GNUC_PREREQ (2,7) || __glibc_has_attribute (__unused__)
+# define __attribute_maybe_unused__ __attribute__ ((__unused__))
+#else
+# define __attribute_maybe_unused__ /* Ignore */
+#endif
+
 /* At some point during the gcc 3.1 development the `used' attribute
    for functions was introduced.  We don't want to use it unconditionally
    (although this would be possible) since it generates warnings.  */
-#if __GNUC_PREREQ (3,1) || __glibc_clang_has_attribute (__used__)
+#if __GNUC_PREREQ (3,1) || __glibc_has_attribute (__used__)
 # define __attribute_used__ __attribute__ ((__used__))
 # define __attribute_noinline__ __attribute__ ((__noinline__))
 #else
@@ -276,7 +279,7 @@
 #endif
 
 /* Since version 3.2, gcc allows marking deprecated functions.  */
-#if __GNUC_PREREQ (3,2) || __glibc_clang_has_attribute (__deprecated__)
+#if __GNUC_PREREQ (3,2) || __glibc_has_attribute (__deprecated__)
 # define __attribute_deprecated__ __attribute__ ((__deprecated__))
 #else
 # define __attribute_deprecated__ /* Ignore */
@@ -285,8 +288,8 @@
 /* Since version 4.5, gcc also allows one to specify the message printed
    when a deprecated function is used.  clang claims to be gcc 4.2, but
    may also support this feature.  */
-#if __GNUC_PREREQ (4,5) || \
-    __glibc_clang_has_extension (__attribute_deprecated_with_message__)
+#if __GNUC_PREREQ (4,5) \
+    || __glibc_has_extension (__attribute_deprecated_with_message__)
 # define __attribute_deprecated_msg__(msg) \
         __attribute__ ((__deprecated__ (msg)))
 #else
@@ -299,7 +302,7 @@
    If several `format_arg' attributes are given for the same function, in
    gcc-3.0 and older, all but the last one are ignored.  In newer gccs,
    all designated arguments are considered.  */
-#if __GNUC_PREREQ (2,8) || __glibc_clang_has_attribute (__format_arg__)
+#if __GNUC_PREREQ (2,8) || __glibc_has_attribute (__format_arg__)
 # define __attribute_format_arg__(x) __attribute__ ((__format_arg__ (x)))
 #else
 # define __attribute_format_arg__(x) /* Ignore */
@@ -309,7 +312,7 @@
    attribute for functions was introduced.  We don't want to use it
    unconditionally (although this would be possible) since it
    generates warnings.  */
-#if __GNUC_PREREQ (2,97) || __glibc_clang_has_attribute (__format__)
+#if __GNUC_PREREQ (2,97) || __glibc_has_attribute (__format__)
 # define __attribute_format_strfmon__(a,b) \
   __attribute__ ((__format__ (__strfmon__, a, b)))
 #else
@@ -317,19 +320,21 @@
 #endif
 
 /* The nonnull function attribute marks pointer parameters that
-   must not be NULL.  Do not define __nonnull if it is already defined,
-   for portability when this file is used in Gnulib.  */
+   must not be NULL.  */
 #ifndef __nonnull
-# if __GNUC_PREREQ (3,3) || __glibc_clang_has_attribute (__nonnull__)
+# if __GNUC_PREREQ (3,3) || __glibc_has_attribute (__nonnull__)
 #  define __nonnull(params) __attribute__ ((__nonnull__ params))
 # else
 #  define __nonnull(params)
 # endif
+#elif !defined __GLIBC__
+# undef __nonnull
+# define __nonnull(params) _GL_ATTRIBUTE_NONNULL (params)
 #endif
 
 /* If fortification mode, we warn about unused results of certain
    function calls which can lead to problems.  */
-#if __GNUC_PREREQ (3,4) || __glibc_clang_has_attribute (__warn_unused_result__)
+#if __GNUC_PREREQ (3,4) || __glibc_has_attribute (__warn_unused_result__)
 # define __attribute_warn_unused_result__ \
    __attribute__ ((__warn_unused_result__))
 # if defined __USE_FORTIFY_LEVEL && __USE_FORTIFY_LEVEL > 0
@@ -343,7 +348,7 @@
 #endif
 
 /* Forces a function to be always inlined.  */
-#if __GNUC_PREREQ (3,2) || __glibc_clang_has_attribute (__always_inline__)
+#if __GNUC_PREREQ (3,2) || __glibc_has_attribute (__always_inline__)
 /* The Linux kernel defines __always_inline in stddef.h (283d7573), and
    it conflicts with this definition.  Therefore undefine it first to
    allow either header to be included first.  */
@@ -356,7 +361,7 @@
 
 /* Associate error messages with the source location of the call site rather
    than with the source location inside the function.  */
-#if __GNUC_PREREQ (4,3) || __glibc_clang_has_attribute (__artificial__)
+#if __GNUC_PREREQ (4,3) || __glibc_has_attribute (__artificial__)
 # define __attribute_artificial__ __attribute__ ((__artificial__))
 #else
 # define __attribute_artificial__ /* Ignore */
@@ -433,7 +438,7 @@
 # endif
 #endif
 
-#if (__GNUC__ >= 3) || __glibc_clang_has_builtin (__builtin_expect)
+#if (__GNUC__ >= 3) || __glibc_has_builtin (__builtin_expect)
 # define __glibc_unlikely(cond)        __builtin_expect ((cond), 0)
 # define __glibc_likely(cond)  __builtin_expect ((cond), 1)
 #else
@@ -441,12 +446,6 @@
 # define __glibc_likely(cond)  (cond)
 #endif
 
-#ifdef __has_attribute
-# define __glibc_has_attribute(attr)   __has_attribute (attr)
-#else
-# define __glibc_has_attribute(attr)   0
-#endif
-
 #if (!defined _Noreturn \
      && (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) < 201112 \
      &&  !(__GNUC_PREREQ (4,7) \
@@ -467,6 +466,16 @@
 # define __attribute_nonstring__
 #endif
 
+/* Undefine (also defined in libc-symbols.h).  */
+#undef __attribute_copy__
+#if __GNUC_PREREQ (9, 0)
+/* Copies attributes from the declaration or type referenced by
+   the argument.  */
+# define __attribute_copy__(arg) __attribute__ ((__copy__ (arg)))
+#else
+# define __attribute_copy__(arg)
+#endif
+
 #if (!defined _Static_assert && !defined __cplusplus \
      && (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) < 201112 \
      && (!(__GNUC_PREREQ (4, 6) || __clang_major__ >= 4) \
@@ -483,7 +492,37 @@
 # include <bits/long-double.h>
 #endif
 
-#if defined __LONG_DOUBLE_MATH_OPTIONAL && defined __NO_LONG_DOUBLE_MATH
+#if __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 1
+# ifdef __REDIRECT
+
+/* Alias name defined automatically.  */
+#  define __LDBL_REDIR(name, proto) ... unused__ldbl_redir
+#  define __LDBL_REDIR_DECL(name) \
+  extern __typeof (name) name __asm (__ASMNAME ("__" #name "ieee128"));
+
+/* Alias name defined automatically, with leading underscores.  */
+#  define __LDBL_REDIR2_DECL(name) \
+  extern __typeof (__##name) __##name \
+    __asm (__ASMNAME ("__" #name "ieee128"));
+
+/* Alias name defined manually.  */
+#  define __LDBL_REDIR1(name, proto, alias) ... unused__ldbl_redir1
+#  define __LDBL_REDIR1_DECL(name, alias) \
+  extern __typeof (name) name __asm (__ASMNAME (#alias));
+
+#  define __LDBL_REDIR1_NTH(name, proto, alias) \
+  __REDIRECT_NTH (name, proto, alias)
+#  define __REDIRECT_NTH_LDBL(name, proto, alias) \
+  __LDBL_REDIR1_NTH (name, proto, __##alias##ieee128)
+
+/* Unused.  */
+#  define __REDIRECT_LDBL(name, proto, alias) ... unused__redirect_ldbl
+#  define __LDBL_REDIR_NTH(name, proto) ... unused__ldbl_redir_nth
+
+# else
+_Static_assert (0, "IEEE 128-bits long double requires redirection on this 
platform");
+# endif
+#elif defined __LONG_DOUBLE_MATH_OPTIONAL && defined __NO_LONG_DOUBLE_MATH
 # define __LDBL_COMPAT 1
 # ifdef __REDIRECT
 #  define __LDBL_REDIR1(name, proto, alias) __REDIRECT (name, proto, alias)
@@ -492,6 +531,8 @@
 #  define __LDBL_REDIR1_NTH(name, proto, alias) __REDIRECT_NTH (name, proto, 
alias)
 #  define __LDBL_REDIR_NTH(name, proto) \
   __LDBL_REDIR1_NTH (name, proto, __nldbl_##name)
+#  define __LDBL_REDIR2_DECL(name) \
+  extern __typeof (__##name) __##name __asm (__ASMNAME ("__nldbl___" #name));
 #  define __LDBL_REDIR1_DECL(name, alias) \
   extern __typeof (name) name __asm (__ASMNAME (#alias));
 #  define __LDBL_REDIR_DECL(name) \
@@ -502,11 +543,13 @@
   __LDBL_REDIR1_NTH (name, proto, __nldbl_##alias)
 # endif
 #endif
-#if !defined __LDBL_COMPAT || !defined __REDIRECT
+#if (!defined __LDBL_COMPAT && __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 0) \
+    || !defined __REDIRECT
 # define __LDBL_REDIR1(name, proto, alias) name proto
 # define __LDBL_REDIR(name, proto) name proto
 # define __LDBL_REDIR1_NTH(name, proto, alias) name proto __THROW
 # define __LDBL_REDIR_NTH(name, proto) name proto __THROW
+# define __LDBL_REDIR2_DECL(name)
 # define __LDBL_REDIR_DECL(name)
 # ifdef __REDIRECT
 #  define __REDIRECT_LDBL(name, proto, alias) __REDIRECT (name, proto, alias)
@@ -537,7 +580,7 @@
    check is required to enable the use of generic selection.  */
 #if !defined __cplusplus \
     && (__GNUC_PREREQ (4, 9) \
-       || __glibc_clang_has_extension (c_generic_selections) \
+       || __glibc_has_extension (c_generic_selections) \
        || (!defined __GNUC__ && defined __STDC_VERSION__ \
            && __STDC_VERSION__ >= 201112L))
 # define __HAVE_GENERIC_SELECTION 1
@@ -545,4 +588,23 @@
 # define __HAVE_GENERIC_SELECTION 0
 #endif
 
+#if __GNUC_PREREQ (10, 0)
+/* Designates a 1-based positional argument ref-index of pointer type
+   that can be used to access size-index elements of the pointed-to
+   array according to access mode, or at least one element when
+   size-index is not provided:
+     access (access-mode, <ref-index> [, <size-index>])  */
+#define __attr_access(x) __attribute__ ((__access__ x))
+#else
+#  define __attr_access(x)
+#endif
+
+/* Specify that a function such as setjmp or vfork may return
+   twice.  */
+#if __GNUC_PREREQ (4, 1)
+# define __attribute_returns_twice__ __attribute__ ((__returns_twice__))
+#else
+# define __attribute_returns_twice__ /* Ignore.  */
+#endif
+
 #endif  /* sys/cdefs.h */
diff --git a/support/dfa.c b/support/dfa.c
index df32dd9..0bf72ff 100644
--- a/support/dfa.c
+++ b/support/dfa.c
@@ -1,5 +1,5 @@
 /* dfa.c - deterministic extended regexp routines for GNU
-   Copyright (C) 1988, 1998, 2000, 2002, 2004-2005, 2007-2020 Free Software
+   Copyright (C) 1988, 1998, 2000, 2002, 2004-2005, 2007-2021 Free Software
    Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
diff --git a/support/dfa.h b/support/dfa.h
index 6547789..19a4127 100644
--- a/support/dfa.h
+++ b/support/dfa.h
@@ -1,5 +1,5 @@
 /* dfa.h - declarations for GNU deterministic regexp compiler
-   Copyright (C) 1988, 1998, 2007, 2009-2020 Free Software Foundation, Inc.
+   Copyright (C) 1988, 1998, 2007, 2009-2021 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
diff --git a/support/dynarray.h b/support/dynarray.h
new file mode 100644
index 0000000..01d85af
--- /dev/null
+++ b/support/dynarray.h
@@ -0,0 +1 @@
+// dummy for gawk
diff --git a/support/flexmember.h b/support/flexmember.h
index 1e839f0..1b19a2b 100644
--- a/support/flexmember.h
+++ b/support/flexmember.h
@@ -1,6 +1,6 @@
 /* Sizes of structs with flexible array members.
 
-   Copyright 2016-2020 Free Software Foundation, Inc.
+   Copyright 2016-2021 Free Software Foundation, Inc.
 
    This file is part of the GNU C Library.
 
diff --git a/support/intprops.h b/support/intprops.h
index cb08671..967e32e 100644
--- a/support/intprops.h
+++ b/support/intprops.h
@@ -1,6 +1,6 @@
 /* intprops.h -- properties of integer types
 
-   Copyright (C) 2001-2020 Free Software Foundation, Inc.
+   Copyright (C) 2001-2021 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify it
    under the terms of the GNU Lesser General Public License as published
@@ -226,7 +226,9 @@
 
 /* True if __builtin_add_overflow (A, B, P) and __builtin_sub_overflow
    (A, B, P) work when P is non-null.  */
-#if 5 <= __GNUC__ && !defined __ICC
+/* __builtin_{add,sub}_overflow exists but is not reliable in GCC 5.x and 6.x,
+   see <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98269>.  */
+#if 7 <= __GNUC__ && !defined __ICC
 # define _GL_HAS_BUILTIN_ADD_OVERFLOW 1
 #elif defined __has_builtin
 # define _GL_HAS_BUILTIN_ADD_OVERFLOW __has_builtin (__builtin_add_overflow)
@@ -244,10 +246,14 @@
 
 /* True if __builtin_add_overflow_p (A, B, C) works, and similarly for
    __builtin_sub_overflow_p and __builtin_mul_overflow_p.  */
-#ifdef __clang__
-/* Clang 9 lacks __builtin_mul_overflow_p, and even if it did it would
-   presumably run afoul of Clang bug 16404.  */
+#if defined __clang__ || defined __ICC
+/* Clang 11 lacks __builtin_mul_overflow_p, and even if it did it
+   would presumably run afoul of Clang bug 16404.  ICC 2021.1's
+   __builtin_add_overflow_p etc. are not treated as integral constant
+   expressions even when all arguments are.  */
 # define _GL_HAS_BUILTIN_OVERFLOW_P 0
+#elif defined __has_builtin
+# define _GL_HAS_BUILTIN_OVERFLOW_P __has_builtin (__builtin_mul_overflow_p)
 #else
 # define _GL_HAS_BUILTIN_OVERFLOW_P (7 <= __GNUC__)
 #endif
@@ -383,8 +389,9 @@
    _GL_INT_OP_WRAPV (a, b, r, -, _GL_INT_SUBTRACT_RANGE_OVERFLOW)
 #endif
 #if _GL_HAS_BUILTIN_MUL_OVERFLOW
-# if (9 < __GNUC__ + (3 <= __GNUC_MINOR__) \
-      || (__GNUC__ == 8 && 4 <= __GNUC_MINOR__))
+# if ((9 < __GNUC__ + (3 <= __GNUC_MINOR__) \
+       || (__GNUC__ == 8 && 4 <= __GNUC_MINOR__)) \
+      && !defined __ICC)
 #  define INT_MULTIPLY_WRAPV(a, b, r) __builtin_mul_overflow (a, b, r)
 # else
    /* Work around GCC bug 91450.  */
@@ -591,4 +598,33 @@
          : (tmin) / (a) < (b)) \
       : (tmax) / (b) < (a)))
 
+/* The following macros compute A + B, A - B, and A * B, respectively.
+   If no overflow occurs, they set *R to the result and return 1;
+   otherwise, they return 0 and may modify *R.
+
+   Example usage:
+
+     long int result;
+     if (INT_ADD_OK (a, b, &result))
+       printf ("result is %ld\n", result);
+     else
+       printf ("overflow\n");
+
+   A, B, and *R should be integers; they need not be the same type,
+   and they need not be all signed or all unsigned.
+
+   These macros work correctly on all known practical hosts, and do not rely
+   on undefined behavior due to signed arithmetic overflow.
+
+   These macros are not constant expressions.
+
+   These macros may evaluate their arguments zero or multiple times, so the
+   arguments should not have side effects.
+
+   These macros are tuned for B being a constant.  */
+
+#define INT_ADD_OK(a, b, r) ! INT_ADD_WRAPV (a, b, r)
+#define INT_SUBTRACT_OK(a, b, r) ! INT_SUBTRACT_WRAPV (a, b, r)
+#define INT_MULTIPLY_OK(a, b, r) ! INT_MULTIPLY_WRAPV (a, b, r)
+
 #endif /* _GL_INTPROPS_H */
diff --git a/support/libc-config.h b/support/libc-config.h
index 59cfbe5..fcdafcb 100644
--- a/support/libc-config.h
+++ b/support/libc-config.h
@@ -1,6 +1,6 @@
 /* System definitions for code taken from the GNU C Library
 
-   Copyright 2017-2020 Free Software Foundation, Inc.
+   Copyright 2017-2021 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -71,107 +71,112 @@
 # endif
 #endif
 
-
-/* Prepare to include <cdefs.h>, which is our copy of glibc
-   <sys/cdefs.h>.  */
+#ifndef __attribute_maybe_unused__
+/* <sys/cdefs.h> either does not exist, or is too old for Gnulib.
+   Prepare to include <cdefs.h>, which is Gnulib's version of a
+   more-recent glibc <sys/cdefs.h>.  */
 
 /* Define _FEATURES_H so that <cdefs.h> does not include <features.h>.  */
-#ifndef _FEATURES_H
-# define _FEATURES_H 1
-#endif
+# ifndef _FEATURES_H
+#  define _FEATURES_H 1
+# endif
 /* Define __WORDSIZE so that <cdefs.h> does not attempt to include
    nonexistent files.  Make it a syntax error, since Gnulib does not
    use __WORDSIZE now, and if Gnulib uses it later the syntax error
    will let us know that __WORDSIZE needs configuring.  */
-#ifndef __WORDSIZE
-# define __WORDSIZE %%%
-#endif
+# ifndef __WORDSIZE
+#  define __WORDSIZE %%%
+# endif
 /* Undef the macros unconditionally defined by our copy of glibc
    <sys/cdefs.h>, so that they do not clash with any system-defined
    versions.  */
-#undef _SYS_CDEFS_H
-#undef __ASMNAME
-#undef __ASMNAME2
-#undef __BEGIN_DECLS
-#undef __CONCAT
-#undef __END_DECLS
-#undef __HAVE_GENERIC_SELECTION
-#undef __LDBL_COMPAT
-#undef __LDBL_REDIR
-#undef __LDBL_REDIR1
-#undef __LDBL_REDIR1_DECL
-#undef __LDBL_REDIR1_NTH
-#undef __LDBL_REDIR_DECL
-#undef __LDBL_REDIR_NTH
-#undef __LEAF
-#undef __LEAF_ATTR
-#undef __NTH
-#undef __NTHNL
-#undef __P
-#undef __PMT
-#undef __REDIRECT
-#undef __REDIRECT_LDBL
-#undef __REDIRECT_NTH
-#undef __REDIRECT_NTHNL
-#undef __REDIRECT_NTH_LDBL
-#undef __STRING
-#undef __THROW
-#undef __THROWNL
-#undef __always_inline
-#undef __attribute__
-#undef __attribute_alloc_size__
-#undef __attribute_artificial__
-#undef __attribute_const__
-#undef __attribute_deprecated__
-#undef __attribute_deprecated_msg__
-#undef __attribute_format_arg__
-#undef __attribute_format_strfmon__
-#undef __attribute_malloc__
-#undef __attribute_noinline__
-#undef __attribute_nonstring__
-#undef __attribute_pure__
-#undef __attribute_used__
-#undef __attribute_warn_unused_result__
-#undef __bos
-#undef __bos0
-#undef __errordecl
-#undef __extension__
-#undef __extern_always_inline
-#undef __extern_inline
-#undef __flexarr
-#undef __fortify_function
-#undef __glibc_c99_flexarr_available
-#undef __glibc_clang_has_extension
-#undef __glibc_likely
-#undef __glibc_macro_warning
-#undef __glibc_macro_warning1
-#undef __glibc_unlikely
-#undef __inline
-#undef __ptr_t
-#undef __restrict
-#undef __restrict_arr
-#undef __va_arg_pack
-#undef __va_arg_pack_len
-#undef __warnattr
-#undef __warndecl
+# undef _SYS_CDEFS_H
+# undef __ASMNAME
+# undef __ASMNAME2
+# undef __BEGIN_DECLS
+# undef __CONCAT
+# undef __END_DECLS
+# undef __HAVE_GENERIC_SELECTION
+# undef __LDBL_COMPAT
+# undef __LDBL_REDIR
+# undef __LDBL_REDIR1
+# undef __LDBL_REDIR1_DECL
+# undef __LDBL_REDIR1_NTH
+# undef __LDBL_REDIR2_DECL
+# undef __LDBL_REDIR_DECL
+# undef __LDBL_REDIR_NTH
+# undef __LEAF
+# undef __LEAF_ATTR
+# undef __NTH
+# undef __NTHNL
+# undef __REDIRECT
+# undef __REDIRECT_LDBL
+# undef __REDIRECT_NTH
+# undef __REDIRECT_NTHNL
+# undef __REDIRECT_NTH_LDBL
+# undef __STRING
+# undef __THROW
+# undef __THROWNL
+# undef __attr_access
+# undef __attribute__
+# undef __attribute_alloc_size__
+# undef __attribute_artificial__
+# undef __attribute_const__
+# undef __attribute_deprecated__
+# undef __attribute_deprecated_msg__
+# undef __attribute_format_arg__
+# undef __attribute_format_strfmon__
+# undef __attribute_malloc__
+# undef __attribute_noinline__
+# undef __attribute_nonstring__
+# undef __attribute_pure__
+# undef __attribute_returns_twice__
+# undef __attribute_used__
+# undef __attribute_warn_unused_result__
+# undef __bos
+# undef __bos0
+# undef __errordecl
+# undef __extension__
+# undef __extern_always_inline
+# undef __extern_inline
+# undef __flexarr
+# undef __fortify_function
+# undef __glibc_c99_flexarr_available
+# undef __glibc_has_attribute
+# undef __glibc_has_builtin
+# undef __glibc_has_extension
+# undef __glibc_macro_warning
+# undef __glibc_macro_warning1
+# undef __glibc_objsize
+# undef __glibc_objsize0
+# undef __glibc_unlikely
+# undef __inline
+# undef __ptr_t
+# undef __restrict
+# undef __restrict_arr
+# undef __va_arg_pack
+# undef __va_arg_pack_len
+# undef __warnattr
 
 /* Include our copy of glibc <sys/cdefs.h>.  */
-#include <cdefs.h>
+# include <cdefs.h>
 
 /* <cdefs.h> __inline is too pessimistic for non-GCC.  */
-#undef __inline
-#ifndef HAVE___INLINE
-# if 199901 <= __STDC_VERSION__ || defined inline
-#  define __inline inline
-# else
-#  define __inline
+# undef __inline
+# ifndef HAVE___INLINE
+#  if 199901 <= __STDC_VERSION__ || defined inline
+#   define __inline inline
+#  else
+#   define __inline
+#  endif
 # endif
-#endif
+
+#endif /* defined __glibc_likely */
 
 
 /* A substitute for glibc <libc-symbols.h>, good enough for Gnulib.  */
 #define attribute_hidden
-#define libc_hidden_proto(name, ...)
+#define libc_hidden_proto(name)
 #define libc_hidden_def(name)
 #define libc_hidden_weak(name)
 #define libc_hidden_ver(local, name)
diff --git a/support/localeinfo.c b/support/localeinfo.c
index 159ad07..f75a323 100644
--- a/support/localeinfo.c
+++ b/support/localeinfo.c
@@ -1,6 +1,6 @@
 /* locale information
 
-   Copyright 2016-2020 Free Software Foundation, Inc.
+   Copyright 2016-2021 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
diff --git a/support/localeinfo.h b/support/localeinfo.h
index 16f5129..5013612 100644
--- a/support/localeinfo.h
+++ b/support/localeinfo.h
@@ -1,6 +1,6 @@
 /* locale information
 
-   Copyright 2016-2020 Free Software Foundation, Inc.
+   Copyright 2016-2021 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
diff --git a/support/malloc/dynarray-skeleton.c 
b/support/malloc/dynarray-skeleton.c
new file mode 100644
index 0000000..5b9f37b
--- /dev/null
+++ b/support/malloc/dynarray-skeleton.c
@@ -0,0 +1,525 @@
+/* Type-safe arrays which grow dynamically.
+   Copyright (C) 2017-2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+/* Pre-processor macros which act as parameters:
+
+   DYNARRAY_STRUCT
+      The struct tag of dynamic array to be defined.
+   DYNARRAY_ELEMENT
+      The type name of the element type.  Elements are copied
+      as if by memcpy, and can change address as the dynamic
+      array grows.
+   DYNARRAY_PREFIX
+      The prefix of the functions which are defined.
+
+   The following parameters are optional:
+
+   DYNARRAY_ELEMENT_FREE
+      DYNARRAY_ELEMENT_FREE (E) is evaluated to deallocate the
+      contents of elements. E is of type  DYNARRAY_ELEMENT *.
+   DYNARRAY_ELEMENT_INIT
+      DYNARRAY_ELEMENT_INIT (E) is evaluated to initialize a new
+      element.  E is of type  DYNARRAY_ELEMENT *.
+      If DYNARRAY_ELEMENT_FREE but not DYNARRAY_ELEMENT_INIT is
+      defined, new elements are automatically zero-initialized.
+      Otherwise, new elements have undefined contents.
+   DYNARRAY_INITIAL_SIZE
+      The size of the statically allocated array (default:
+      at least 2, more elements if they fit into 128 bytes).
+      Must be a preprocessor constant.  If DYNARRAY_INITIAL_SIZE is 0,
+      there is no statically allocated array at, and all non-empty
+      arrays are heap-allocated.
+   DYNARRAY_FINAL_TYPE
+      The name of the type which holds the final array.  If not
+      defined, is PREFIX##finalize not provided.  DYNARRAY_FINAL_TYPE
+      must be a struct type, with members of type DYNARRAY_ELEMENT and
+      size_t at the start (in this order).
+
+   These macros are undefined after this header file has been
+   included.
+
+   The following types are provided (their members are private to the
+   dynarray implementation):
+
+     struct DYNARRAY_STRUCT
+
+   The following functions are provided:
+
+     void DYNARRAY_PREFIX##init (struct DYNARRAY_STRUCT *);
+     void DYNARRAY_PREFIX##free (struct DYNARRAY_STRUCT *);
+     bool DYNARRAY_PREFIX##has_failed (const struct DYNARRAY_STRUCT *);
+     void DYNARRAY_PREFIX##mark_failed (struct DYNARRAY_STRUCT *);
+     size_t DYNARRAY_PREFIX##size (const struct DYNARRAY_STRUCT *);
+     DYNARRAY_ELEMENT *DYNARRAY_PREFIX##begin (const struct DYNARRAY_STRUCT *);
+     DYNARRAY_ELEMENT *DYNARRAY_PREFIX##end (const struct DYNARRAY_STRUCT *);
+     DYNARRAY_ELEMENT *DYNARRAY_PREFIX##at (struct DYNARRAY_STRUCT *, size_t);
+     void DYNARRAY_PREFIX##add (struct DYNARRAY_STRUCT *, DYNARRAY_ELEMENT);
+     DYNARRAY_ELEMENT *DYNARRAY_PREFIX##emplace (struct DYNARRAY_STRUCT *);
+     bool DYNARRAY_PREFIX##resize (struct DYNARRAY_STRUCT *, size_t);
+     void DYNARRAY_PREFIX##remove_last (struct DYNARRAY_STRUCT *);
+     void DYNARRAY_PREFIX##clear (struct DYNARRAY_STRUCT *);
+
+   The following functions are provided are provided if the
+   prerequisites are met:
+
+     bool DYNARRAY_PREFIX##finalize (struct DYNARRAY_STRUCT *,
+                                     DYNARRAY_FINAL_TYPE *);
+       (if DYNARRAY_FINAL_TYPE is defined)
+     DYNARRAY_ELEMENT *DYNARRAY_PREFIX##finalize (struct DYNARRAY_STRUCT *,
+                                                  size_t *);
+       (if DYNARRAY_FINAL_TYPE is not defined)
+*/
+
+#include <malloc/dynarray.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef DYNARRAY_STRUCT
+# error "DYNARRAY_STRUCT must be defined"
+#endif
+
+#ifndef DYNARRAY_ELEMENT
+# error "DYNARRAY_ELEMENT must be defined"
+#endif
+
+#ifndef DYNARRAY_PREFIX
+# error "DYNARRAY_PREFIX must be defined"
+#endif
+
+#ifdef DYNARRAY_INITIAL_SIZE
+# if DYNARRAY_INITIAL_SIZE < 0
+#  error "DYNARRAY_INITIAL_SIZE must be non-negative"
+# endif
+# if DYNARRAY_INITIAL_SIZE > 0
+#  define DYNARRAY_HAVE_SCRATCH 1
+# else
+#  define DYNARRAY_HAVE_SCRATCH 0
+# endif
+#else
+/* Provide a reasonable default which limits the size of
+   DYNARRAY_STRUCT.  */
+# define DYNARRAY_INITIAL_SIZE \
+  (sizeof (DYNARRAY_ELEMENT) > 64 ? 2 : 128 / sizeof (DYNARRAY_ELEMENT))
+# define DYNARRAY_HAVE_SCRATCH 1
+#endif
+
+/* Public type definitions.  */
+
+/* All fields of this struct are private to the implementation.  */
+struct DYNARRAY_STRUCT
+{
+  union
+  {
+    struct dynarray_header dynarray_abstract;
+    struct
+    {
+      /* These fields must match struct dynarray_header.  */
+      size_t used;
+      size_t allocated;
+      DYNARRAY_ELEMENT *array;
+    } dynarray_header;
+  } u;
+
+#if DYNARRAY_HAVE_SCRATCH
+  /* Initial inline allocation.  */
+  DYNARRAY_ELEMENT scratch[DYNARRAY_INITIAL_SIZE];
+#endif
+};
+
+/* Internal use only: Helper macros.  */
+
+/* Ensure macro-expansion of DYNARRAY_PREFIX.  */
+#define DYNARRAY_CONCAT0(prefix, name) prefix##name
+#define DYNARRAY_CONCAT1(prefix, name) DYNARRAY_CONCAT0(prefix, name)
+#define DYNARRAY_NAME(name) DYNARRAY_CONCAT1(DYNARRAY_PREFIX, name)
+
+/* Use DYNARRAY_FREE instead of DYNARRAY_NAME (free),
+   so that Gnulib does not change 'free' to 'rpl_free'.  */
+#define DYNARRAY_FREE DYNARRAY_CONCAT1 (DYNARRAY_NAME (f), ree)
+
+/* Address of the scratch buffer if any.  */
+#if DYNARRAY_HAVE_SCRATCH
+# define DYNARRAY_SCRATCH(list) (list)->scratch
+#else
+# define DYNARRAY_SCRATCH(list) NULL
+#endif
+
+/* Internal use only: Helper functions.  */
+
+/* Internal function.  Call DYNARRAY_ELEMENT_FREE with the array
+   elements.  Name mangling needed due to the DYNARRAY_ELEMENT_FREE
+   macro expansion.  */
+static inline void
+DYNARRAY_NAME (free__elements__) (DYNARRAY_ELEMENT *__dynarray_array,
+                                  size_t __dynarray_used)
+{
+#ifdef DYNARRAY_ELEMENT_FREE
+  for (size_t __dynarray_i = 0; __dynarray_i < __dynarray_used; ++__dynarray_i)
+    DYNARRAY_ELEMENT_FREE (&__dynarray_array[__dynarray_i]);
+#endif /* DYNARRAY_ELEMENT_FREE */
+}
+
+/* Internal function.  Free the non-scratch array allocation.  */
+static inline void
+DYNARRAY_NAME (free__array__) (struct DYNARRAY_STRUCT *list)
+{
+#if DYNARRAY_HAVE_SCRATCH
+  if (list->u.dynarray_header.array != list->scratch)
+    free (list->u.dynarray_header.array);
+#else
+  free (list->u.dynarray_header.array);
+#endif
+}
+
+/* Public functions.  */
+
+/* Initialize a dynamic array object.  This must be called before any
+   use of the object.  */
+__nonnull ((1))
+static void
+DYNARRAY_NAME (init) (struct DYNARRAY_STRUCT *list)
+{
+  list->u.dynarray_header.used = 0;
+  list->u.dynarray_header.allocated = DYNARRAY_INITIAL_SIZE;
+  list->u.dynarray_header.array = DYNARRAY_SCRATCH (list);
+}
+
+/* Deallocate the dynamic array and its elements.  */
+__attribute_maybe_unused__ __nonnull ((1))
+static void
+DYNARRAY_FREE (struct DYNARRAY_STRUCT *list)
+{
+  DYNARRAY_NAME (free__elements__)
+    (list->u.dynarray_header.array, list->u.dynarray_header.used);
+  DYNARRAY_NAME (free__array__) (list);
+  DYNARRAY_NAME (init) (list);
+}
+
+/* Return true if the dynamic array is in an error state.  */
+__nonnull ((1))
+static inline bool
+DYNARRAY_NAME (has_failed) (const struct DYNARRAY_STRUCT *list)
+{
+  return list->u.dynarray_header.allocated == __dynarray_error_marker ();
+}
+
+/* Mark the dynamic array as failed.  All elements are deallocated as
+   a side effect.  */
+__nonnull ((1))
+static void
+DYNARRAY_NAME (mark_failed) (struct DYNARRAY_STRUCT *list)
+{
+  DYNARRAY_NAME (free__elements__)
+    (list->u.dynarray_header.array, list->u.dynarray_header.used);
+  DYNARRAY_NAME (free__array__) (list);
+  list->u.dynarray_header.array = DYNARRAY_SCRATCH (list);
+  list->u.dynarray_header.used = 0;
+  list->u.dynarray_header.allocated = __dynarray_error_marker ();
+}
+
+/* Return the number of elements which have been added to the dynamic
+   array.  */
+__nonnull ((1))
+static inline size_t
+DYNARRAY_NAME (size) (const struct DYNARRAY_STRUCT *list)
+{
+  return list->u.dynarray_header.used;
+}
+
+/* Return a pointer to the array element at INDEX.  Terminate the
+   process if INDEX is out of bounds.  */
+__nonnull ((1))
+static inline DYNARRAY_ELEMENT *
+DYNARRAY_NAME (at) (struct DYNARRAY_STRUCT *list, size_t index)
+{
+  if (__glibc_unlikely (index >= DYNARRAY_NAME (size) (list)))
+    __libc_dynarray_at_failure (DYNARRAY_NAME (size) (list), index);
+  return list->u.dynarray_header.array + index;
+}
+
+/* Return a pointer to the first array element, if any.  For a
+   zero-length array, the pointer can be NULL even though the dynamic
+   array has not entered the failure state.  */
+__nonnull ((1))
+static inline DYNARRAY_ELEMENT *
+DYNARRAY_NAME (begin) (struct DYNARRAY_STRUCT *list)
+{
+  return list->u.dynarray_header.array;
+}
+
+/* Return a pointer one element past the last array element.  For a
+   zero-length array, the pointer can be NULL even though the dynamic
+   array has not entered the failure state.  */
+__nonnull ((1))
+static inline DYNARRAY_ELEMENT *
+DYNARRAY_NAME (end) (struct DYNARRAY_STRUCT *list)
+{
+  return list->u.dynarray_header.array + list->u.dynarray_header.used;
+}
+
+/* Internal function.  Slow path for the add function below.  */
+static void
+DYNARRAY_NAME (add__) (struct DYNARRAY_STRUCT *list, DYNARRAY_ELEMENT item)
+{
+  if (__glibc_unlikely
+      (!__libc_dynarray_emplace_enlarge (&list->u.dynarray_abstract,
+                                         DYNARRAY_SCRATCH (list),
+                                         sizeof (DYNARRAY_ELEMENT))))
+    {
+      DYNARRAY_NAME (mark_failed) (list);
+      return;
+    }
+
+  /* Copy the new element and increase the array length.  */
+  list->u.dynarray_header.array[list->u.dynarray_header.used++] = item;
+}
+
+/* Add ITEM at the end of the array, enlarging it by one element.
+   Mark *LIST as failed if the dynamic array allocation size cannot be
+   increased.  */
+__nonnull ((1))
+static inline void
+DYNARRAY_NAME (add) (struct DYNARRAY_STRUCT *list, DYNARRAY_ELEMENT item)
+{
+  /* Do nothing in case of previous error.  */
+  if (DYNARRAY_NAME (has_failed) (list))
+    return;
+
+  /* Enlarge the array if necessary.  */
+  if (__glibc_unlikely (list->u.dynarray_header.used
+                        == list->u.dynarray_header.allocated))
+    {
+      DYNARRAY_NAME (add__) (list, item);
+      return;
+    }
+
+  /* Copy the new element and increase the array length.  */
+  list->u.dynarray_header.array[list->u.dynarray_header.used++] = item;
+}
+
+/* Internal function.  Building block for the emplace functions below.
+   Assumes space for one more element in *LIST.  */
+static inline DYNARRAY_ELEMENT *
+DYNARRAY_NAME (emplace__tail__) (struct DYNARRAY_STRUCT *list)
+{
+  DYNARRAY_ELEMENT *result
+    = &list->u.dynarray_header.array[list->u.dynarray_header.used];
+  ++list->u.dynarray_header.used;
+#if defined (DYNARRAY_ELEMENT_INIT)
+  DYNARRAY_ELEMENT_INIT (result);
+#elif defined (DYNARRAY_ELEMENT_FREE)
+  memset (result, 0, sizeof (*result));
+#endif
+  return result;
+}
+
+/* Internal function.  Slow path for the emplace function below.  */
+static DYNARRAY_ELEMENT *
+DYNARRAY_NAME (emplace__) (struct DYNARRAY_STRUCT *list)
+{
+  if (__glibc_unlikely
+      (!__libc_dynarray_emplace_enlarge (&list->u.dynarray_abstract,
+                                         DYNARRAY_SCRATCH (list),
+                                         sizeof (DYNARRAY_ELEMENT))))
+    {
+      DYNARRAY_NAME (mark_failed) (list);
+      return NULL;
+    }
+  return DYNARRAY_NAME (emplace__tail__) (list);
+}
+
+/* Allocate a place for a new element in *LIST and return a pointer to
+   it.  The pointer can be NULL if the dynamic array cannot be
+   enlarged due to a memory allocation failure.  */
+__attribute_maybe_unused__ __attribute_warn_unused_result__ __nonnull ((1))
+static
+/* Avoid inlining with the larger initialization code.  */
+#if !(defined (DYNARRAY_ELEMENT_INIT) || defined (DYNARRAY_ELEMENT_FREE))
+inline
+#endif
+DYNARRAY_ELEMENT *
+DYNARRAY_NAME (emplace) (struct DYNARRAY_STRUCT *list)
+{
+  /* Do nothing in case of previous error.  */
+  if (DYNARRAY_NAME (has_failed) (list))
+    return NULL;
+
+  /* Enlarge the array if necessary.  */
+  if (__glibc_unlikely (list->u.dynarray_header.used
+                        == list->u.dynarray_header.allocated))
+    return (DYNARRAY_NAME (emplace__) (list));
+  return DYNARRAY_NAME (emplace__tail__) (list);
+}
+
+/* Change the size of *LIST to SIZE.  If SIZE is larger than the
+   existing size, new elements are added (which can be initialized).
+   Otherwise, the list is truncated, and elements are freed.  Return
+   false on memory allocation failure (and mark *LIST as failed).  */
+__attribute_maybe_unused__ __nonnull ((1))
+static bool
+DYNARRAY_NAME (resize) (struct DYNARRAY_STRUCT *list, size_t size)
+{
+  if (size > list->u.dynarray_header.used)
+    {
+      bool ok;
+#if defined (DYNARRAY_ELEMENT_INIT)
+      /* The new elements have to be initialized.  */
+      size_t old_size = list->u.dynarray_header.used;
+      ok = __libc_dynarray_resize (&list->u.dynarray_abstract,
+                                   size, DYNARRAY_SCRATCH (list),
+                                   sizeof (DYNARRAY_ELEMENT));
+      if (ok)
+        for (size_t i = old_size; i < size; ++i)
+          {
+            DYNARRAY_ELEMENT_INIT (&list->u.dynarray_header.array[i]);
+          }
+#elif defined (DYNARRAY_ELEMENT_FREE)
+      /* Zero initialization is needed so that the elements can be
+         safely freed.  */
+      ok = __libc_dynarray_resize_clear
+        (&list->u.dynarray_abstract, size,
+         DYNARRAY_SCRATCH (list), sizeof (DYNARRAY_ELEMENT));
+#else
+      ok =  __libc_dynarray_resize (&list->u.dynarray_abstract,
+                                    size, DYNARRAY_SCRATCH (list),
+                                    sizeof (DYNARRAY_ELEMENT));
+#endif
+      if (__glibc_unlikely (!ok))
+        DYNARRAY_NAME (mark_failed) (list);
+      return ok;
+    }
+  else
+    {
+      /* The list has shrunk in size.  Free the removed elements.  */
+      DYNARRAY_NAME (free__elements__)
+        (list->u.dynarray_header.array + size,
+         list->u.dynarray_header.used - size);
+      list->u.dynarray_header.used = size;
+      return true;
+    }
+}
+
+/* Remove the last element of LIST if it is present.  */
+__attribute_maybe_unused__ __nonnull ((1))
+static void
+DYNARRAY_NAME (remove_last) (struct DYNARRAY_STRUCT *list)
+{
+  /* used > 0 implies that the array is the non-failed state.  */
+  if (list->u.dynarray_header.used > 0)
+    {
+      size_t new_length = list->u.dynarray_header.used - 1;
+#ifdef DYNARRAY_ELEMENT_FREE
+      DYNARRAY_ELEMENT_FREE (&list->u.dynarray_header.array[new_length]);
+#endif
+      list->u.dynarray_header.used = new_length;
+    }
+}
+
+/* Remove all elements from the list.  The elements are freed, but the
+   list itself is not.  */
+__attribute_maybe_unused__ __nonnull ((1))
+static void
+DYNARRAY_NAME (clear) (struct DYNARRAY_STRUCT *list)
+{
+  /* free__elements__ does nothing if the list is in the failed
+     state.  */
+  DYNARRAY_NAME (free__elements__)
+    (list->u.dynarray_header.array, list->u.dynarray_header.used);
+  list->u.dynarray_header.used = 0;
+}
+
+#ifdef DYNARRAY_FINAL_TYPE
+/* Transfer the dynamic array to a permanent location at *RESULT.
+   Returns true on success on false on allocation failure.  In either
+   case, *LIST is re-initialized and can be reused.  A NULL pointer is
+   stored in *RESULT if LIST refers to an empty list.  On success, the
+   pointer in *RESULT is heap-allocated and must be deallocated using
+   free.  */
+__attribute_maybe_unused__ __attribute_warn_unused_result__ __nonnull ((1, 2))
+static bool
+DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list,
+                          DYNARRAY_FINAL_TYPE *result)
+{
+  struct dynarray_finalize_result res;
+  if (__libc_dynarray_finalize (&list->u.dynarray_abstract,
+                                DYNARRAY_SCRATCH (list),
+                                sizeof (DYNARRAY_ELEMENT), &res))
+    {
+      /* On success, the result owns all the data.  */
+      DYNARRAY_NAME (init) (list);
+      *result = (DYNARRAY_FINAL_TYPE) { res.array, res.length };
+      return true;
+    }
+  else
+    {
+      /* On error, we need to free all data.  */
+      DYNARRAY_FREE (list);
+      errno = ENOMEM;
+      return false;
+    }
+}
+#else /* !DYNARRAY_FINAL_TYPE */
+/* Transfer the dynamic array to a heap-allocated array and return a
+   pointer to it.  The pointer is NULL if memory allocation fails, or
+   if the array is empty, so this function should be used only for
+   arrays which are known not be empty (usually because they always
+   have a sentinel at the end).  If LENGTHP is not NULL, the array
+   length is written to *LENGTHP.  *LIST is re-initialized and can be
+   reused.  */
+__attribute_maybe_unused__ __attribute_warn_unused_result__ __nonnull ((1))
+static DYNARRAY_ELEMENT *
+DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list, size_t *lengthp)
+{
+  struct dynarray_finalize_result res;
+  if (__libc_dynarray_finalize (&list->u.dynarray_abstract,
+                                DYNARRAY_SCRATCH (list),
+                                sizeof (DYNARRAY_ELEMENT), &res))
+    {
+      /* On success, the result owns all the data.  */
+      DYNARRAY_NAME (init) (list);
+      if (lengthp != NULL)
+        *lengthp = res.length;
+      return res.array;
+    }
+  else
+    {
+      /* On error, we need to free all data.  */
+      DYNARRAY_FREE (list);
+      errno = ENOMEM;
+      return NULL;
+    }
+}
+#endif /* !DYNARRAY_FINAL_TYPE */
+
+/* Undo macro definitions.  */
+
+#undef DYNARRAY_CONCAT0
+#undef DYNARRAY_CONCAT1
+#undef DYNARRAY_NAME
+#undef DYNARRAY_SCRATCH
+#undef DYNARRAY_HAVE_SCRATCH
+
+#undef DYNARRAY_STRUCT
+#undef DYNARRAY_ELEMENT
+#undef DYNARRAY_PREFIX
+#undef DYNARRAY_ELEMENT_FREE
+#undef DYNARRAY_ELEMENT_INIT
+#undef DYNARRAY_INITIAL_SIZE
+#undef DYNARRAY_FINAL_TYPE
diff --git a/support/malloc/dynarray.h b/support/malloc/dynarray.h
new file mode 100644
index 0000000..638c33f
--- /dev/null
+++ b/support/malloc/dynarray.h
@@ -0,0 +1,178 @@
+/* Type-safe arrays which grow dynamically.  Shared definitions.
+   Copyright (C) 2017-2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+/* To use the dynarray facility, you need to include
+   <malloc/dynarray-skeleton.c> and define the parameter macros
+   documented in that file.
+
+   A minimal example which provides a growing list of integers can be
+   defined like this:
+
+     struct int_array
+     {
+       // Pointer to result array followed by its length,
+       // as required by DYNARRAY_FINAL_TYPE.
+       int *array;
+       size_t length;
+     };
+
+     #define DYNARRAY_STRUCT dynarray_int
+     #define DYNARRAY_ELEMENT int
+     #define DYNARRAY_PREFIX dynarray_int_
+     #define DYNARRAY_FINAL_TYPE struct int_array
+     #include <malloc/dynarray-skeleton.c>
+
+   To create a three-element array with elements 1, 2, 3, use this
+   code:
+
+     struct dynarray_int dyn;
+     dynarray_int_init (&dyn);
+     for (int i = 1; i <= 3; ++i)
+       {
+         int *place = dynarray_int_emplace (&dyn);
+         assert (place != NULL);
+         *place = i;
+       }
+     struct int_array result;
+     bool ok = dynarray_int_finalize (&dyn, &result);
+     assert (ok);
+     assert (result.length == 3);
+     assert (result.array[0] == 1);
+     assert (result.array[1] == 2);
+     assert (result.array[2] == 3);
+     free (result.array);
+
+   If the elements contain resources which must be freed, define
+   DYNARRAY_ELEMENT_FREE appropriately, like this:
+
+     struct str_array
+     {
+       char **array;
+       size_t length;
+     };
+
+     #define DYNARRAY_STRUCT dynarray_str
+     #define DYNARRAY_ELEMENT char *
+     #define DYNARRAY_ELEMENT_FREE(ptr) free (*ptr)
+     #define DYNARRAY_PREFIX dynarray_str_
+     #define DYNARRAY_FINAL_TYPE struct str_array
+     #include <malloc/dynarray-skeleton.c>
+
+   Compared to scratch buffers, dynamic arrays have the following
+   features:
+
+   - They have an element type, and are not just an untyped buffer of
+     bytes.
+
+   - When growing, previously stored elements are preserved.  (It is
+     expected that scratch_buffer_grow_preserve and
+     scratch_buffer_set_array_size eventually go away because all
+     current users are moved to dynamic arrays.)
+
+   - Scratch buffers have a more aggressive growth policy because
+     growing them typically means a retry of an operation (across an
+     NSS service module boundary), which is expensive.
+
+   - For the same reason, scratch buffers have a much larger initial
+     stack allocation.  */
+
+#ifndef _DYNARRAY_H
+#define _DYNARRAY_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <string.h>
+
+struct dynarray_header
+{
+  size_t used;
+  size_t allocated;
+  void *array;
+};
+
+/* Marker used in the allocated member to indicate that an error was
+   encountered.  */
+static inline size_t
+__dynarray_error_marker (void)
+{
+  return -1;
+}
+
+/* Internal function.  See the has_failed function in
+   dynarray-skeleton.c.  */
+static inline bool
+__dynarray_error (struct dynarray_header *list)
+{
+  return list->allocated == __dynarray_error_marker ();
+}
+
+/* Internal function.  Enlarge the dynamically allocated area of the
+   array to make room for one more element.  SCRATCH is a pointer to
+   the scratch area (which is not heap-allocated and must not be
+   freed).  ELEMENT_SIZE is the size, in bytes, of one element.
+   Return false on failure, true on success.  */
+bool __libc_dynarray_emplace_enlarge (struct dynarray_header *,
+                                      void *scratch, size_t element_size);
+
+/* Internal function.  Enlarge the dynamically allocated area of the
+   array to make room for at least SIZE elements (which must be larger
+   than the existing used part of the dynamic array).  SCRATCH is a
+   pointer to the scratch area (which is not heap-allocated and must
+   not be freed).  ELEMENT_SIZE is the size, in bytes, of one element.
+   Return false on failure, true on success.  */
+bool __libc_dynarray_resize (struct dynarray_header *, size_t size,
+                             void *scratch, size_t element_size);
+
+/* Internal function.  Like __libc_dynarray_resize, but clear the new
+   part of the dynamic array.  */
+bool __libc_dynarray_resize_clear (struct dynarray_header *, size_t size,
+                                   void *scratch, size_t element_size);
+
+/* Internal type.  */
+struct dynarray_finalize_result
+{
+  void *array;
+  size_t length;
+};
+
+/* Internal function.  Copy the dynamically-allocated area to an
+   explicitly-sized heap allocation.  SCRATCH is a pointer to the
+   embedded scratch space.  ELEMENT_SIZE is the size, in bytes, of the
+   element type.  On success, true is returned, and pointer and length
+   are written to *RESULT.  On failure, false is returned.  The caller
+   has to take care of some of the memory management; this function is
+   expected to be called from dynarray-skeleton.c.  */
+bool __libc_dynarray_finalize (struct dynarray_header *list, void *scratch,
+                               size_t element_size,
+                               struct dynarray_finalize_result *result);
+
+
+/* Internal function.  Terminate the process after an index error.
+   SIZE is the number of elements of the dynamic array.  INDEX is the
+   lookup index which triggered the failure.  */
+_Noreturn void __libc_dynarray_at_failure (size_t size, size_t index);
+
+#ifndef _ISOMAC
+libc_hidden_proto (__libc_dynarray_emplace_enlarge)
+libc_hidden_proto (__libc_dynarray_resize)
+libc_hidden_proto (__libc_dynarray_resize_clear)
+libc_hidden_proto (__libc_dynarray_finalize)
+libc_hidden_proto (__libc_dynarray_at_failure)
+#endif
+
+#endif /* _DYNARRAY_H */
diff --git a/support/regcomp.c b/support/regcomp.c
index 692928b..887e5b5 100644
--- a/support/regcomp.c
+++ b/support/regcomp.c
@@ -1,5 +1,5 @@
 /* Extended regular expression matching and search library.
-   Copyright (C) 2002-2020 Free Software Foundation, Inc.
+   Copyright (C) 2002-2021 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
 
@@ -1695,12 +1695,14 @@ calc_eclosure_iter (re_node_set *new_set, re_dfa_t 
*dfa, Idx node, bool root)
   reg_errcode_t err;
   Idx i;
   re_node_set eclosure;
-  bool ok;
   bool incomplete = false;
   err = re_node_set_alloc (&eclosure, dfa->edests[node].nelem + 1);
   if (__glibc_unlikely (err != REG_NOERROR))
     return err;
 
+  /* An epsilon closure includes itself.  */
+  eclosure.elems[eclosure.nelem++] = node;
+
   /* This indicates that we are calculating this node now.
      We reference this value to avoid infinite loop.  */
   dfa->eclosures[node].nelem = -1;
@@ -1753,10 +1755,6 @@ calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, 
Idx node, bool root)
          }
       }
 
-  /* An epsilon closure includes itself.  */
-  ok = re_node_set_insert (&eclosure, node);
-  if (__glibc_unlikely (! ok))
-    return REG_ESPACE;
   if (incomplete && !root)
     dfa->eclosures[node].nelem = 0;
   else
diff --git a/support/regex.c b/support/regex.c
index 991eedc..7296be0 100644
--- a/support/regex.c
+++ b/support/regex.c
@@ -1,5 +1,5 @@
 /* Extended regular expression matching and search library.
-   Copyright (C) 2002-2020 Free Software Foundation, Inc.
+   Copyright (C) 2002-2021 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
 
diff --git a/support/regex.h b/support/regex.h
index 7418e6c..8e4ef45 100644
--- a/support/regex.h
+++ b/support/regex.h
@@ -1,6 +1,6 @@
 /* Definitions for data structures and routines for the regular
    expression library.
-   Copyright (C) 1985, 1989-2020 Free Software Foundation, Inc.
+   Copyright (C) 1985, 1989-2021 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
diff --git a/support/regex_internal.c b/support/regex_internal.c
index ed0a134..55f6b66 100644
--- a/support/regex_internal.c
+++ b/support/regex_internal.c
@@ -1,5 +1,5 @@
 /* Extended regular expression matching and search library.
-   Copyright (C) 2002-2020 Free Software Foundation, Inc.
+   Copyright (C) 2002-2021 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
 
@@ -1314,6 +1314,7 @@ re_node_set_insert (re_node_set *set, Idx elem)
     {
       for (idx = set->nelem; set->elems[idx - 1] > elem; idx--)
        set->elems[idx] = set->elems[idx - 1];
+      DEBUG_ASSERT (set->elems[idx - 1] < elem);
     }
 
   /* Insert the new element.  */
diff --git a/support/regex_internal.h b/support/regex_internal.h
index 4a3cf77..4b0a3ef 100644
--- a/support/regex_internal.h
+++ b/support/regex_internal.h
@@ -1,5 +1,5 @@
 /* Extended regular expression matching and search library.
-   Copyright (C) 2002-2020 Free Software Foundation, Inc.
+   Copyright (C) 2002-2021 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
 
@@ -32,6 +32,10 @@
 #include <stdbool.h>
 #include <stdint.h>
 
+#ifndef _LIBC
+# include <dynarray.h>
+#endif
+
 #include <intprops.h>
 #include <verify.h>
 
@@ -444,25 +448,6 @@ typedef struct re_dfa_t re_dfa_t;
 #define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx))
 #define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx))
 
-#if defined _LIBC || HAVE_ALLOCA
-# include <alloca.h>
-#endif
-
-#ifndef _LIBC
-# if HAVE_ALLOCA
-/* The OS usually guarantees only one guard page at the bottom of the stack,
-   and a page size can be as small as 4096 bytes.  So we cannot safely
-   allocate anything larger than 4096 bytes.  Also care for the possibility
-   of a few compiler-allocated temporary stack slots.  */
-#  define __libc_use_alloca(n) ((n) < 4032)
-# else
-/* alloca is implemented with malloc, so just use malloc.  */
-#  define __libc_use_alloca(n) 0
-#  undef alloca
-#  define alloca(n) malloc (n)
-# endif
-#endif
-
 #ifdef _LIBC
 # define MALLOC_0_IS_NONNULL 1
 #elif !defined MALLOC_0_IS_NONNULL
@@ -848,12 +833,14 @@ re_string_elem_size_at (const re_string_t *pstr, Idx idx)
 }
 #endif /* RE_ENABLE_I18N */
 
-#ifndef FALLTHROUGH
-# if (__GNUC__ >= 7) || (__clang_major__ >= 10)
+#ifdef _LIBC
+# if __GNUC__ >= 7
 #  define FALLTHROUGH __attribute__ ((__fallthrough__))
 # else
 #  define FALLTHROUGH ((void) 0)
 # endif
+#else
+# include "attribute.h"
 #endif
 
 #endif /*  _REGEX_INTERNAL_H */
diff --git a/support/regexec.c b/support/regexec.c
index a3ee618..6309dea 100644
--- a/support/regexec.c
+++ b/support/regexec.c
@@ -1,5 +1,5 @@
 /* Extended regular expression matching and search library.
-   Copyright (C) 2002-2020 Free Software Foundation, Inc.
+   Copyright (C) 2002-2021 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
 
@@ -59,7 +59,7 @@ static void update_regs (const re_dfa_t *dfa, regmatch_t 
*pmatch,
                         Idx cur_idx, Idx nmatch);
 static reg_errcode_t push_fail_stack (struct re_fail_stack_t *fs,
                                      Idx str_idx, Idx dest_node, Idx nregs,
-                                     regmatch_t *regs,
+                                     regmatch_t *regs, regmatch_t *prevregs,
                                      re_node_set *eps_via_nodes);
 static reg_errcode_t set_regs (const regex_t *preg,
                               const re_match_context_t *mctx,
@@ -186,7 +186,8 @@ static reg_errcode_t extend_buffers (re_match_context_t 
*mctx, int min_len);
    REG_NOTBOL is set, then ^ does not match at the beginning of the
    string; if REG_NOTEOL is set, then $ does not match at the end.
 
-   We return 0 if we find a match and REG_NOMATCH if not.  */
+   Return 0 if a match is found, REG_NOMATCH if not, REG_BADPAT if
+   EFLAGS is invalid.  */
 
 int
 regexec (const regex_t *__restrict preg, const char *__restrict string,
@@ -269,8 +270,8 @@ compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0);
    strings.)
 
    On success, re_match* functions return the length of the match, re_search*
-   return the position of the start of the match.  Return value -1 means no
-   match was found and -2 indicates an internal error.  */
+   return the position of the start of the match.  They return -1 on
+   match failure, -2 on error.  */
 
 regoff_t
 re_match (struct re_pattern_buffer *bufp, const char *string, Idx length,
@@ -1206,27 +1207,26 @@ check_halt_state_context (const re_match_context_t 
*mctx,
 /* Compute the next node to which "NFA" transit from NODE("NFA" is a NFA
    corresponding to the DFA).
    Return the destination node, and update EPS_VIA_NODES;
-   return -1 in case of errors.  */
+   return -1 on match failure, -2 on error.  */
 
 static Idx
 proceed_next_node (const re_match_context_t *mctx, Idx nregs, regmatch_t *regs,
+                  regmatch_t *prevregs,
                   Idx *pidx, Idx node, re_node_set *eps_via_nodes,
                   struct re_fail_stack_t *fs)
 {
   const re_dfa_t *const dfa = mctx->dfa;
-  Idx i;
-  bool ok;
   if (IS_EPSILON_NODE (dfa->nodes[node].type))
     {
       re_node_set *cur_nodes = &mctx->state_log[*pidx]->nodes;
       re_node_set *edests = &dfa->edests[node];
-      Idx dest_node;
-      ok = re_node_set_insert (eps_via_nodes, node);
+      bool ok = re_node_set_insert (eps_via_nodes, node);
       if (__glibc_unlikely (! ok))
        return -2;
-      /* Pick up a valid destination, or return -1 if none
-        is found.  */
-      for (dest_node = -1, i = 0; i < edests->nelem; ++i)
+
+      /* Pick a valid destination, or return -1 if none is found.  */
+      Idx dest_node = -1;
+      for (Idx i = 0; i < edests->nelem; i++)
        {
          Idx candidate = edests->elems[i];
          if (!re_node_set_contains (cur_nodes, candidate))
@@ -1244,7 +1244,7 @@ proceed_next_node (const re_match_context_t *mctx, Idx 
nregs, regmatch_t *regs,
              /* Otherwise, push the second epsilon-transition on the fail 
stack.  */
              else if (fs != NULL
                       && push_fail_stack (fs, *pidx, candidate, nregs, regs,
-                                          eps_via_nodes))
+                                          prevregs, eps_via_nodes))
                return -2;
 
              /* We know we are going to exit.  */
@@ -1288,7 +1288,7 @@ proceed_next_node (const re_match_context_t *mctx, Idx 
nregs, regmatch_t *regs,
          if (naccepted == 0)
            {
              Idx dest_node;
-             ok = re_node_set_insert (eps_via_nodes, node);
+             bool ok = re_node_set_insert (eps_via_nodes, node);
              if (__glibc_unlikely (! ok))
                return -2;
              dest_node = dfa->edests[node].elems[0];
@@ -1317,7 +1317,8 @@ proceed_next_node (const re_match_context_t *mctx, Idx 
nregs, regmatch_t *regs,
 static reg_errcode_t
 __attribute_warn_unused_result__
 push_fail_stack (struct re_fail_stack_t *fs, Idx str_idx, Idx dest_node,
-                Idx nregs, regmatch_t *regs, re_node_set *eps_via_nodes)
+                Idx nregs, regmatch_t *regs, regmatch_t *prevregs,
+                re_node_set *eps_via_nodes)
 {
   reg_errcode_t err;
   Idx num = fs->num++;
@@ -1333,28 +1334,39 @@ push_fail_stack (struct re_fail_stack_t *fs, Idx 
str_idx, Idx dest_node,
     }
   fs->stack[num].idx = str_idx;
   fs->stack[num].node = dest_node;
-  fs->stack[num].regs = re_malloc (regmatch_t, nregs);
+  fs->stack[num].regs = re_malloc (regmatch_t, 2 * nregs);
   if (fs->stack[num].regs == NULL)
     return REG_ESPACE;
   memcpy (fs->stack[num].regs, regs, sizeof (regmatch_t) * nregs);
+  memcpy (fs->stack[num].regs + nregs, prevregs, sizeof (regmatch_t) * nregs);
   err = re_node_set_init_copy (&fs->stack[num].eps_via_nodes, eps_via_nodes);
   return err;
 }
 
 static Idx
 pop_fail_stack (struct re_fail_stack_t *fs, Idx *pidx, Idx nregs,
-               regmatch_t *regs, re_node_set *eps_via_nodes)
+               regmatch_t *regs, regmatch_t *prevregs,
+               re_node_set *eps_via_nodes)
 {
+  if (fs == NULL || fs->num == 0)
+    return -1;
   Idx num = --fs->num;
-  DEBUG_ASSERT (num >= 0);
   *pidx = fs->stack[num].idx;
   memcpy (regs, fs->stack[num].regs, sizeof (regmatch_t) * nregs);
+  memcpy (prevregs, fs->stack[num].regs + nregs, sizeof (regmatch_t) * nregs);
   re_node_set_free (eps_via_nodes);
   re_free (fs->stack[num].regs);
   *eps_via_nodes = fs->stack[num].eps_via_nodes;
+  DEBUG_ASSERT (0 <= fs->stack[num].node);
   return fs->stack[num].node;
 }
 
+
+#define DYNARRAY_STRUCT  regmatch_list
+#define DYNARRAY_ELEMENT regmatch_t
+#define DYNARRAY_PREFIX  regmatch_list_
+#include <malloc/dynarray-skeleton.c>
+
 /* Set the positions where the subexpressions are starts/ends to registers
    PMATCH.
    Note: We assume that pmatch[0] is already set, and
@@ -1370,8 +1382,8 @@ set_regs (const regex_t *preg, const re_match_context_t 
*mctx, size_t nmatch,
   re_node_set eps_via_nodes;
   struct re_fail_stack_t *fs;
   struct re_fail_stack_t fs_body = { 0, 2, NULL };
-  regmatch_t *prev_idx_match;
-  bool prev_idx_match_malloced = false;
+  struct regmatch_list prev_match;
+  regmatch_list_init (&prev_match);
 
   DEBUG_ASSERT (nmatch > 1);
   DEBUG_ASSERT (mctx->state_log != NULL);
@@ -1388,53 +1400,45 @@ set_regs (const regex_t *preg, const re_match_context_t 
*mctx, size_t nmatch,
   cur_node = dfa->init_node;
   re_node_set_init_empty (&eps_via_nodes);
 
-  if (__libc_use_alloca (nmatch * sizeof (regmatch_t)))
-    prev_idx_match = (regmatch_t *) alloca (nmatch * sizeof (regmatch_t));
-  else
+  if (!regmatch_list_resize (&prev_match, nmatch))
     {
-      prev_idx_match = re_malloc (regmatch_t, nmatch);
-      if (prev_idx_match == NULL)
-       {
-         free_fail_stack_return (fs);
-         return REG_ESPACE;
-       }
-      prev_idx_match_malloced = true;
+      regmatch_list_free (&prev_match);
+      free_fail_stack_return (fs);
+      return REG_ESPACE;
     }
+  regmatch_t *prev_idx_match = regmatch_list_begin (&prev_match);
   memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch);
 
   for (idx = pmatch[0].rm_so; idx <= pmatch[0].rm_eo ;)
     {
       update_regs (dfa, pmatch, prev_idx_match, cur_node, idx, nmatch);
 
-      if (idx == pmatch[0].rm_eo && cur_node == mctx->last_node)
+      if ((idx == pmatch[0].rm_eo && cur_node == mctx->last_node)
+         || re_node_set_contains (&eps_via_nodes, cur_node))
        {
          Idx reg_idx;
+         cur_node = -1;
          if (fs)
            {
              for (reg_idx = 0; reg_idx < nmatch; ++reg_idx)
                if (pmatch[reg_idx].rm_so > -1 && pmatch[reg_idx].rm_eo == -1)
-                 break;
-             if (reg_idx == nmatch)
-               {
-                 re_node_set_free (&eps_via_nodes);
-                 if (prev_idx_match_malloced)
-                   re_free (prev_idx_match);
-                 return free_fail_stack_return (fs);
-               }
-             cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,
-                                        &eps_via_nodes);
+                 {
+                   cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,
+                                              prev_idx_match, &eps_via_nodes);
+                   break;
+                 }
            }
-         else
+         if (cur_node < 0)
            {
              re_node_set_free (&eps_via_nodes);
-             if (prev_idx_match_malloced)
-               re_free (prev_idx_match);
-             return REG_NOERROR;
+             regmatch_list_free (&prev_match);
+             return free_fail_stack_return (fs);
            }
        }
 
       /* Proceed to next node.  */
-      cur_node = proceed_next_node (mctx, nmatch, pmatch, &idx, cur_node,
+      cur_node = proceed_next_node (mctx, nmatch, pmatch, prev_idx_match,
+                                   &idx, cur_node,
                                    &eps_via_nodes, fs);
 
       if (__glibc_unlikely (cur_node < 0))
@@ -1442,26 +1446,23 @@ set_regs (const regex_t *preg, const re_match_context_t 
*mctx, size_t nmatch,
          if (__glibc_unlikely (cur_node == -2))
            {
              re_node_set_free (&eps_via_nodes);
-             if (prev_idx_match_malloced)
-               re_free (prev_idx_match);
+             regmatch_list_free (&prev_match);
              free_fail_stack_return (fs);
              return REG_ESPACE;
            }
-         if (fs)
-           cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,
-                                      &eps_via_nodes);
-         else
+         cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,
+                                    prev_idx_match, &eps_via_nodes);
+         if (cur_node < 0)
            {
              re_node_set_free (&eps_via_nodes);
-             if (prev_idx_match_malloced)
-               re_free (prev_idx_match);
+             regmatch_list_free (&prev_match);
+             free_fail_stack_return (fs);
              return REG_NOMATCH;
            }
        }
     }
   re_node_set_free (&eps_via_nodes);
-  if (prev_idx_match_malloced)
-    re_free (prev_idx_match);
+  regmatch_list_free (&prev_match);
   return free_fail_stack_return (fs);
 }
 
@@ -1499,10 +1500,10 @@ update_regs (const re_dfa_t *dfa, regmatch_t *pmatch,
     }
   else if (type == OP_CLOSE_SUBEXP)
     {
+      /* We are at the last node of this sub expression.  */
       Idx reg_num = dfa->nodes[cur_node].opr.idx + 1;
       if (reg_num < nmatch)
        {
-         /* We are at the last node of this sub expression.  */
          if (pmatch[reg_num].rm_so < cur_idx)
            {
              pmatch[reg_num].rm_eo = cur_idx;
@@ -2199,6 +2200,7 @@ sift_states_iter_mb (const re_match_context_t *mctx, 
re_sift_context_t *sctx,
 
 /* Return the next state to which the current state STATE will transit by
    accepting the current input byte, and update STATE_LOG if necessary.
+   Return NULL on failure.
    If STATE can accept a multibyte char/collating element/back reference
    update the destination of STATE_LOG.  */
 
@@ -2399,7 +2401,7 @@ check_subexp_matching_top (re_match_context_t *mctx, 
re_node_set *cur_nodes,
 
 #if 0
 /* Return the next state to which the current state STATE will transit by
-   accepting the current input byte.  */
+   accepting the current input byte.  Return NULL on failure.  */
 
 static re_dfastate_t *
 transit_state_sb (reg_errcode_t *err, re_match_context_t *mctx,
@@ -2821,7 +2823,8 @@ find_subexp_node (const re_dfa_t *dfa, const re_node_set 
*nodes,
 /* Check whether the node TOP_NODE at TOP_STR can arrive to the node
    LAST_NODE at LAST_STR.  We record the path onto PATH since it will be
    heavily reused.
-   Return REG_NOERROR if it can arrive, or REG_NOMATCH otherwise.  */
+   Return REG_NOERROR if it can arrive, REG_NOMATCH if it cannot,
+   REG_ESPACE if memory is exhausted.  */
 
 static reg_errcode_t
 __attribute_warn_unused_result__
@@ -3251,7 +3254,7 @@ expand_bkref_cache (re_match_context_t *mctx, re_node_set 
*cur_nodes,
 /* Build transition table for the state.
    Return true if successful.  */
 
-static bool
+static bool __attribute_noinline__
 build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
 {
   reg_errcode_t err;
@@ -3259,36 +3262,20 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t 
*state)
   int ch;
   bool need_word_trtable = false;
   bitset_word_t elem, mask;
-  bool dests_node_malloced = false;
-  bool dest_states_malloced = false;
   Idx ndests; /* Number of the destination states from 'state'.  */
   re_dfastate_t **trtable;
-  re_dfastate_t **dest_states = NULL, **dest_states_word, **dest_states_nl;
-  re_node_set follows, *dests_node;
-  bitset_t *dests_ch;
+  re_dfastate_t *dest_states[SBC_MAX];
+  re_dfastate_t *dest_states_word[SBC_MAX];
+  re_dfastate_t *dest_states_nl[SBC_MAX];
+  re_node_set follows;
   bitset_t acceptable;
 
-  struct dests_alloc
-  {
-    re_node_set dests_node[SBC_MAX];
-    bitset_t dests_ch[SBC_MAX];
-  } *dests_alloc;
-
   /* We build DFA states which corresponds to the destination nodes
      from 'state'.  'dests_node[i]' represents the nodes which i-th
      destination state contains, and 'dests_ch[i]' represents the
      characters which i-th destination state accepts.  */
-  if (__libc_use_alloca (sizeof (struct dests_alloc)))
-    dests_alloc = (struct dests_alloc *) alloca (sizeof (struct dests_alloc));
-  else
-    {
-      dests_alloc = re_malloc (struct dests_alloc, 1);
-      if (__glibc_unlikely (dests_alloc == NULL))
-       return false;
-      dests_node_malloced = true;
-    }
-  dests_node = dests_alloc->dests_node;
-  dests_ch = dests_alloc->dests_ch;
+  re_node_set dests_node[SBC_MAX];
+  bitset_t dests_ch[SBC_MAX];
 
   /* Initialize transition table.  */
   state->word_trtable = state->trtable = NULL;
@@ -3298,8 +3285,6 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
   ndests = group_nodes_into_DFAstates (dfa, state, dests_node, dests_ch);
   if (__glibc_unlikely (ndests <= 0))
     {
-      if (dests_node_malloced)
-       re_free (dests_alloc);
       /* Return false in case of an error, true otherwise.  */
       if (ndests == 0)
        {
@@ -3314,38 +3299,14 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t 
*state)
 
   err = re_node_set_alloc (&follows, ndests + 1);
   if (__glibc_unlikely (err != REG_NOERROR))
-    goto out_free;
-
-  /* Avoid arithmetic overflow in size calculation.  */
-  size_t ndests_max
-    = ((SIZE_MAX - (sizeof (re_node_set) + sizeof (bitset_t)) * SBC_MAX)
-       / (3 * sizeof (re_dfastate_t *)));
-  if (__glibc_unlikely (ndests_max < ndests))
-    goto out_free;
-
-  if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset_t)) * SBC_MAX
-                        + ndests * 3 * sizeof (re_dfastate_t *)))
-    dest_states = (re_dfastate_t **)
-      alloca (ndests * 3 * sizeof (re_dfastate_t *));
-  else
     {
-      dest_states = re_malloc (re_dfastate_t *, ndests * 3);
-      if (__glibc_unlikely (dest_states == NULL))
-       {
-out_free:
-         if (dest_states_malloced)
-           re_free (dest_states);
-         re_node_set_free (&follows);
-         for (i = 0; i < ndests; ++i)
-           re_node_set_free (dests_node + i);
-         if (dests_node_malloced)
-           re_free (dests_alloc);
-         return false;
-       }
-      dest_states_malloced = true;
+    out_free:
+      re_node_set_free (&follows);
+      for (i = 0; i < ndests; ++i)
+       re_node_set_free (dests_node + i);
+      return false;
     }
-  dest_states_word = dest_states + ndests;
-  dest_states_nl = dest_states_word + ndests;
+
   bitset_empty (acceptable);
 
   /* Then build the states for all destinations.  */
@@ -3470,23 +3431,17 @@ out_free:
          }
     }
 
-  if (dest_states_malloced)
-    re_free (dest_states);
-
   re_node_set_free (&follows);
   for (i = 0; i < ndests; ++i)
     re_node_set_free (dests_node + i);
-
-  if (dests_node_malloced)
-    re_free (dests_alloc);
-
   return true;
 }
 
 /* Group all nodes belonging to STATE into several destinations.
    Then for all destinations, set the nodes belonging to the destination
    to DESTS_NODE[i] and set the characters accepted by the destination
-   to DEST_CH[i].  This function return the number of destinations.  */
+   to DEST_CH[i].  Return the number of destinations if successful,
+   -1 on internal error.  */
 
 static Idx
 group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state,
@@ -4264,7 +4219,8 @@ match_ctx_add_subtop (re_match_context_t *mctx, Idx node, 
Idx str_idx)
 }
 
 /* Register the node NODE, whose type is OP_CLOSE_SUBEXP, and which matches
-   at STR_IDX, whose corresponding OP_OPEN_SUBEXP is SUB_TOP.  */
+   at STR_IDX, whose corresponding OP_OPEN_SUBEXP is SUB_TOP.
+   Return the new entry if successful, NULL if memory is exhausted.  */
 
 static re_sub_match_last_t *
 match_ctx_add_sublast (re_sub_match_top_t *subtop, Idx node, Idx str_idx)
diff --git a/support/verify.h b/support/verify.h
index fa1ed71..65514c3 100644
--- a/support/verify.h
+++ b/support/verify.h
@@ -1,6 +1,6 @@
 /* Compile-time assert-like macros.
 
-   Copyright (C) 2005-2006, 2009-2020 Free Software Foundation, Inc.
+   Copyright (C) 2005-2006, 2009-2021 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
@@ -22,16 +22,10 @@
 
 
 /* Define _GL_HAVE__STATIC_ASSERT to 1 if _Static_assert (R, DIAGNOSTIC)
-   works as per C11.  This is supported by GCC 4.6.0 and later, in C
-   mode, and by clang (also in C++ mode).
+   works as per C11.  This is supported by GCC 4.6.0+ and by clang 4+.
 
    Define _GL_HAVE__STATIC_ASSERT1 to 1 if _Static_assert (R) works as
-   per C2X.  This is supported by GCC 9.1 and later, and by clang in
-   C++1z mode.
-
-   Define _GL_HAVE_STATIC_ASSERT1 if static_assert (R) works as per
-   C++17.  This is supported by GCC 9.1 and later, and by clang in
-   C++1z mode.
+   per C2X.  This is supported by GCC 9.1+.
 
    Support compilers claiming conformance to the relevant standard,
    and also support GCC when not pedantic.  If we were willing to slow
@@ -47,18 +41,6 @@
       || (!defined __STRICT_ANSI__ && 9 <= __GNUC__))
 #  define _GL_HAVE__STATIC_ASSERT1 1
 # endif
-#else
-# if 4 <= __clang_major__
-#  define _GL_HAVE__STATIC_ASSERT 1
-# endif
-# if 4 <= __clang_major__ && 201411 <= __cpp_static_assert
-#  define _GL_HAVE__STATIC_ASSERT1 1
-# endif
-# if 201703L <= __cplusplus \
-     || 9 <= __GNUC__ \
-     || (4 <= __clang_major__ && 201411 <= __cpp_static_assert)
-#  define _GL_HAVE_STATIC_ASSERT1 1
-# endif
 #endif
 
 /* FreeBSD 9.1 <sys/cdefs.h>, included by <stddef.h> and lots of other
@@ -225,7 +207,9 @@ template <int w>
    Unfortunately, unlike C11, this implementation must appear as an
    ordinary declaration, and cannot appear inside struct { ... }.  */
 
-#if defined _GL_HAVE__STATIC_ASSERT
+#if 200410 <= __cpp_static_assert
+# define _GL_VERIFY(R, DIAGNOSTIC, ...) static_assert (R, DIAGNOSTIC)
+#elif defined _GL_HAVE__STATIC_ASSERT
 # define _GL_VERIFY(R, DIAGNOSTIC, ...) _Static_assert (R, DIAGNOSTIC)
 #else
 # define _GL_VERIFY(R, DIAGNOSTIC, ...)                                \
@@ -239,7 +223,7 @@ template <int w>
 #  define _Static_assert(...) \
      _GL_VERIFY (__VA_ARGS__, "static assertion failed", -)
 # endif
-# if !defined _GL_HAVE_STATIC_ASSERT1 && !defined static_assert
+# if __cpp_static_assert < 201411 && !defined static_assert
 #  define static_assert _Static_assert /* C11 requires this #define.  */
 # endif
 #endif

-----------------------------------------------------------------------

Summary of changes:
 helpers/ChangeLog                  |   4 +
 helpers/update-support.sh          |   3 +-
 support/ChangeLog                  |   9 +
 support/attribute.h                |   1 +
 support/cdefs.h                    | 194 +++++++++-----
 support/dfa.c                      |   2 +-
 support/dfa.h                      |   2 +-
 support/dynarray.h                 |   1 +
 support/flexmember.h               |   2 +-
 support/intprops.h                 |  50 +++-
 support/libc-config.h              | 173 ++++++------
 support/localeinfo.c               |   2 +-
 support/localeinfo.h               |   2 +-
 support/malloc/dynarray-skeleton.c | 525 +++++++++++++++++++++++++++++++++++++
 support/malloc/dynarray.h          | 178 +++++++++++++
 support/regcomp.c                  |  10 +-
 support/regex.c                    |   2 +-
 support/regex.h                    |   2 +-
 support/regex_internal.c           |   3 +-
 support/regex_internal.h           |  31 +--
 support/regexec.c                  | 204 ++++++--------
 support/verify.h                   |  30 +--
 22 files changed, 1089 insertions(+), 341 deletions(-)
 create mode 100644 support/attribute.h
 create mode 100644 support/dynarray.h
 create mode 100644 support/malloc/dynarray-skeleton.c
 create mode 100644 support/malloc/dynarray.h


hooks/post-receive
-- 
gawk



reply via email to

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