summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDaniel Llorens <lloda@sarc.name>2021-04-08 20:54:42 +0200
committerDaniel Llorens <lloda@sarc.name>2021-04-08 21:00:42 +0200
commitbdb07f8fc7b37ef64498c7b06cd4457faf456189 (patch)
tree4c98d2d714f2071513897efe01063bebc36e32cb /lib
parent88e703084567eb99238a3be6ba4285d87a25eeae (diff)
downloadguile-bdb07f8fc7b37ef64498c7b06cd4457faf456189.tar.gz
Update gnulib to a3a946f670718d0dee5a7425ad5ac0a29fb46ea1wip-gnulib-update
This fixes https://lists.gnu.org/archive/html/guile-devel/2021-04/msg00009.html
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am21
-rw-r--r--lib/canonicalize-lgpl.c7
-rw-r--r--lib/cdefs.h16
-rw-r--r--lib/dynarray.h255
-rw-r--r--lib/free.c16
-rw-r--r--lib/intprops.h18
-rw-r--r--lib/lc-charset-dispatch.c6
-rw-r--r--lib/libc-config.h6
-rw-r--r--lib/link.c4
-rw-r--r--lib/malloc.c16
-rw-r--r--lib/malloc/dynarray-skeleton.c33
-rw-r--r--lib/malloc/dynarray_at_failure.c4
-rw-r--r--lib/malloc/dynarray_emplace_enlarge.c4
-rw-r--r--lib/malloc/dynarray_finalize.c4
-rw-r--r--lib/malloc/dynarray_resize.c4
-rw-r--r--lib/malloc/dynarray_resize_clear.c4
-rw-r--r--lib/malloca.h1
-rw-r--r--lib/math.in.h2
-rw-r--r--lib/mbrtowc-impl-utf8.h2
-rw-r--r--lib/mbtowc-lock.h12
-rw-r--r--lib/mempcpy.c5
-rw-r--r--lib/putenv.c10
-rw-r--r--lib/rawmemchr.c5
-rw-r--r--lib/realloc.c85
-rw-r--r--lib/regcomp.c8
-rw-r--r--lib/regex_internal.c1
-rw-r--r--lib/regex_internal.h15
-rw-r--r--lib/regexec.c89
-rw-r--r--lib/rename.c2
-rw-r--r--lib/scratch_buffer.h93
-rw-r--r--lib/stdalign.in.h13
-rw-r--r--lib/stddef.in.h11
-rw-r--r--lib/stdlib.in.h117
-rw-r--r--lib/striconveh.c47
-rw-r--r--lib/time.in.h42
-rw-r--r--lib/vasnprintf.c25
-rw-r--r--lib/xalloc-oversized.h24
37 files changed, 829 insertions, 198 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 86c7aba28..02480f6e9 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -720,9 +720,7 @@ EXTRA_libgnu_la_SOURCES += floor.c
## begin gnulib module free-posix
-if gl_GNULIB_ENABLED_ef07dc4b3077c11ea9cef586db4e5955
-endif
EXTRA_DIST += free.c
EXTRA_libgnu_la_SOURCES += free.c
@@ -2003,6 +2001,17 @@ EXTRA_libgnu_la_SOURCES += readlink.c
## end gnulib module readlink
+## begin gnulib module realloc-posix
+
+if gl_GNULIB_ENABLED_61bcaca76b3e6f9ae55d57a1c3193bc4
+
+endif
+EXTRA_DIST += realloc.c
+
+EXTRA_libgnu_la_SOURCES += realloc.c
+
+## end gnulib module realloc-posix
+
## begin gnulib module recv
@@ -2628,8 +2637,10 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \
-e 's/@''GNULIB_SECURE_GETENV''@/$(GNULIB_SECURE_GETENV)/g' \
-e 's/@''GNULIB_SETENV''@/$(GNULIB_SETENV)/g' \
-e 's/@''GNULIB_STRTOD''@/$(GNULIB_STRTOD)/g' \
+ -e 's/@''GNULIB_STRTOL''@/$(GNULIB_STRTOL)/g' \
-e 's/@''GNULIB_STRTOLD''@/$(GNULIB_STRTOLD)/g' \
-e 's/@''GNULIB_STRTOLL''@/$(GNULIB_STRTOLL)/g' \
+ -e 's/@''GNULIB_STRTOUL''@/$(GNULIB_STRTOUL)/g' \
-e 's/@''GNULIB_STRTOULL''@/$(GNULIB_STRTOULL)/g' \
-e 's/@''GNULIB_SYSTEM_POSIX''@/$(GNULIB_SYSTEM_POSIX)/g' \
-e 's/@''GNULIB_UNLOCKPT''@/$(GNULIB_UNLOCKPT)/g' \
@@ -2675,8 +2686,10 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \
-e 's|@''HAVE_SETSTATE''@|$(HAVE_SETSTATE)|g' \
-e 's|@''HAVE_DECL_SETSTATE''@|$(HAVE_DECL_SETSTATE)|g' \
-e 's|@''HAVE_STRTOD''@|$(HAVE_STRTOD)|g' \
+ -e 's|@''HAVE_STRTOL''@|$(HAVE_STRTOL)|g' \
-e 's|@''HAVE_STRTOLD''@|$(HAVE_STRTOLD)|g' \
-e 's|@''HAVE_STRTOLL''@|$(HAVE_STRTOLL)|g' \
+ -e 's|@''HAVE_STRTOUL''@|$(HAVE_STRTOUL)|g' \
-e 's|@''HAVE_STRTOULL''@|$(HAVE_STRTOULL)|g' \
-e 's|@''HAVE_STRUCT_RANDOM_DATA''@|$(HAVE_STRUCT_RANDOM_DATA)|g' \
-e 's|@''HAVE_SYS_LOADAVG_H''@|$(HAVE_SYS_LOADAVG_H)|g' \
@@ -2702,7 +2715,11 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \
-e 's|@''REPLACE_SETENV''@|$(REPLACE_SETENV)|g' \
-e 's|@''REPLACE_SETSTATE''@|$(REPLACE_SETSTATE)|g' \
-e 's|@''REPLACE_STRTOD''@|$(REPLACE_STRTOD)|g' \
+ -e 's|@''REPLACE_STRTOL''@|$(REPLACE_STRTOL)|g' \
-e 's|@''REPLACE_STRTOLD''@|$(REPLACE_STRTOLD)|g' \
+ -e 's|@''REPLACE_STRTOLL''@|$(REPLACE_STRTOLL)|g' \
+ -e 's|@''REPLACE_STRTOUL''@|$(REPLACE_STRTOUL)|g' \
+ -e 's|@''REPLACE_STRTOULL''@|$(REPLACE_STRTOULL)|g' \
-e 's|@''REPLACE_UNSETENV''@|$(REPLACE_UNSETENV)|g' \
-e 's|@''REPLACE_WCTOMB''@|$(REPLACE_WCTOMB)|g' \
-e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
diff --git a/lib/canonicalize-lgpl.c b/lib/canonicalize-lgpl.c
index bf63355da..c6fef174c 100644
--- a/lib/canonicalize-lgpl.c
+++ b/lib/canonicalize-lgpl.c
@@ -21,7 +21,6 @@
optimizes away the name == NULL test below. */
# define _GL_ARG_NONNULL(params)
-# define _GL_USE_STDLIB_ALLOC 1
# include <libc-config.h>
#endif
@@ -76,6 +75,12 @@
# define __rawmemchr rawmemchr
# define __readlink readlink
# define __stat stat
+# if IN_RELOCWRAPPER
+ /* When building the relocatable program wrapper, use the system's memmove
+ function, not the gnulib override, otherwise we would get a link error.
+ */
+# undef memmove
+# endif
#endif
/* Suppress bogus GCC -Wmaybe-uninitialized warnings. */
diff --git a/lib/cdefs.h b/lib/cdefs.h
index a22ae6db2..90f97412a 100644
--- a/lib/cdefs.h
+++ b/lib/cdefs.h
@@ -38,7 +38,9 @@
#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. */
-#ifdef __has_attribute
+#if (defined __has_attribute \
+ && (!defined __clang_minor__ \
+ || 3 < __clang_major__ + (5 <= __clang_minor__)))
# define __glibc_has_attribute(attr) __has_attribute (attr)
#else
# define __glibc_has_attribute(attr) 0
@@ -318,15 +320,17 @@
#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. */
-#ifndef __nonnull
+ must not be NULL. */
+#ifndef __attribute_nonnull__
# if __GNUC_PREREQ (3,3) || __glibc_has_attribute (__nonnull__)
-# define __nonnull(params) __attribute__ ((__nonnull__ params))
+# define __attribute_nonnull__(params) __attribute__ ((__nonnull__ params))
# else
-# define __nonnull(params)
+# define __attribute_nonnull__(params)
# endif
#endif
+#ifndef __nonnull
+# define __nonnull(params) __attribute_nonnull__ (params)
+#endif
/* If fortification mode, we warn about unused results of certain
function calls which can lead to problems. */
diff --git a/lib/dynarray.h b/lib/dynarray.h
index 0e249422e..5db6ed95b 100644
--- a/lib/dynarray.h
+++ b/lib/dynarray.h
@@ -14,18 +14,267 @@
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
-/* Written by Paul Eggert, 2021. */
+/* Written by Paul Eggert and Bruno Haible, 2021. */
#ifndef _GL_DYNARRAY_H
#define _GL_DYNARRAY_H
-#include <libc-config.h>
+/* Before including this file, you need to define:
+ 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:
+ */
+
+/* Initialize a dynamic array object. This must be called before any
+ use of the object. */
+#if 0
+static void
+ DYNARRAY_PREFIX##init (struct DYNARRAY_STRUCT *list);
+#endif
+
+/* Deallocate the dynamic array and its elements. */
+#if 0
+static void
+ DYNARRAY_PREFIX##free (struct DYNARRAY_STRUCT *list);
+#endif
+
+/* Return true if the dynamic array is in an error state. */
+#if 0
+static bool
+ DYNARRAY_PREFIX##has_failed (const struct DYNARRAY_STRUCT *list);
+#endif
+
+/* Mark the dynamic array as failed. All elements are deallocated as
+ a side effect. */
+#if 0
+static void
+ DYNARRAY_PREFIX##mark_failed (struct DYNARRAY_STRUCT *list);
+#endif
+
+/* Return the number of elements which have been added to the dynamic
+ array. */
+#if 0
+static size_t
+ DYNARRAY_PREFIX##size (const struct DYNARRAY_STRUCT *list);
+#endif
+
+/* 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. */
+#if 0
+static DYNARRAY_ELEMENT *
+ DYNARRAY_PREFIX##begin (const struct DYNARRAY_STRUCT *list);
+#endif
+
+/* 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. */
+#if 0
+static DYNARRAY_ELEMENT *
+ DYNARRAY_PREFIX##end (const struct DYNARRAY_STRUCT *list);
+#endif
+
+/* Return a pointer to the array element at INDEX. Terminate the
+ process if INDEX is out of bounds. */
+#if 0
+static DYNARRAY_ELEMENT *
+ DYNARRAY_PREFIX##at (struct DYNARRAY_STRUCT *list, size_t index);
+#endif
+
+/* 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. */
+#if 0
+static void
+ DYNARRAY_PREFIX##add (struct DYNARRAY_STRUCT *list,
+ DYNARRAY_ELEMENT item);
+#endif
+
+/* 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. */
+#if 0
+static DYNARRAY_ELEMENT *
+ DYNARRAY_PREFIX##emplace (struct DYNARRAY_STRUCT *list);
+#endif
+
+/* 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). */
+#if 0
+static bool
+ DYNARRAY_PREFIX##resize (struct DYNARRAY_STRUCT *list, size_t size);
+#endif
+
+/* Remove the last element of LIST if it is present. */
+#if 0
+static void
+ DYNARRAY_PREFIX##remove_last (struct DYNARRAY_STRUCT *list);
+#endif
+
+/* Remove all elements from the list. The elements are freed, but the
+ list itself is not. */
+#if 0
+static void
+ DYNARRAY_PREFIX##clear (struct DYNARRAY_STRUCT *list);
+#endif
+
+#if defined 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. */
+#if 0
+static bool
+ DYNARRAY_PREFIX##finalize (struct DYNARRAY_STRUCT *list,
+ DYNARRAY_FINAL_TYPE *result);
+#endif
+#else /* !defined 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. */
+#if 0
+static DYNARRAY_ELEMENT *
+ DYNARRAY_PREFIX##finalize (struct DYNARRAY_STRUCT *list,
+ size_t *lengthp);
+#endif
+#endif
+
+/* 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>
+ */
+
+
+/* The implementation is imported from glibc. */
+
+/* Avoid possible conflicts with symbols exported by the GNU libc. */
#define __libc_dynarray_at_failure gl_dynarray_at_failure
#define __libc_dynarray_emplace_enlarge gl_dynarray_emplace_enlarge
#define __libc_dynarray_finalize gl_dynarray_finalize
#define __libc_dynarray_resize_clear gl_dynarray_resize_clear
#define __libc_dynarray_resize gl_dynarray_resize
-#include <malloc/dynarray.h>
+
+#if defined DYNARRAY_STRUCT || defined DYNARRAY_ELEMENT || defined DYNARRAY_PREFIX
+
+# include <libc-config.h>
+
+/* Define auxiliary structs and declare auxiliary functions, common to all
+ instantiations of dynarray. */
+# include <malloc/dynarray.h>
+
+/* Define the instantiation, specified through
+ DYNARRAY_STRUCT
+ DYNARRAY_ELEMENT
+ DYNARRAY_PREFIX
+ etc. */
+# include <malloc/dynarray-skeleton.c>
+
+#else
+
+/* This file is being included from one of the malloc/dynarray_*.c files. */
+# include <malloc/dynarray.h>
+
+#endif
#endif /* _GL_DYNARRAY_H */
diff --git a/lib/free.c b/lib/free.c
index 35872c848..b22124154 100644
--- a/lib/free.c
+++ b/lib/free.c
@@ -19,15 +19,19 @@
#include <config.h>
+/* Specification. */
#include <stdlib.h>
-#include <errno.h>
+/* A function definition is only needed if HAVE_FREE_POSIX is not defined. */
+#if !HAVE_FREE_POSIX
+
+# include <errno.h>
void
rpl_free (void *p)
-#undef free
+# undef free
{
-#if defined __GNUC__ && !defined __clang__
+# if defined __GNUC__ && !defined __clang__
/* An invalid GCC optimization
<https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98396>
would optimize away the assignments in the code below, when link-time
@@ -39,9 +43,11 @@ rpl_free (void *p)
errno = 0;
free (p);
errno = err[errno == 0];
-#else
+# else
int err = errno;
free (p);
errno = err;
-#endif
+# endif
}
+
+#endif
diff --git a/lib/intprops.h b/lib/intprops.h
index 967e32ea0..9d10028a5 100644
--- a/lib/intprops.h
+++ b/lib/intprops.h
@@ -133,7 +133,8 @@
operators might not yield numerically correct answers due to
arithmetic overflow. They do not rely on undefined or
implementation-defined behavior. Their implementations are simple
- and straightforward, but they are a bit harder to use than the
+ and straightforward, but they are harder to use and may be less
+ efficient than the INT_<op>_WRAPV, INT_<op>_OK, and
INT_<op>_OVERFLOW macros described below.
Example usage:
@@ -158,6 +159,9 @@
must have minimum value MIN and maximum MAX. Unsigned types should
use a zero MIN of the proper type.
+ Because all arguments are subject to integer promotions, these
+ macros typically do not work on types narrower than 'int'.
+
These macros are tuned for constant MIN and MAX. For commutative
operations such as A + B, they are also tuned for constant B. */
@@ -339,9 +343,15 @@
arguments should not have side effects.
The WRAPV macros are not constant expressions. They support only
- +, binary -, and *. Because the WRAPV macros convert the result,
- they report overflow in different circumstances than the OVERFLOW
- macros do.
+ +, binary -, and *.
+
+ Because the WRAPV macros convert the result, they report overflow
+ in different circumstances than the OVERFLOW macros do. For
+ example, in the typical case with 16-bit 'short' and 32-bit 'int',
+ if A, B and R are all of type 'short' then INT_ADD_OVERFLOW (A, B)
+ returns false because the addition cannot overflow after A and B
+ are converted to 'int', whereas INT_ADD_WRAPV (A, B, &R) returns
+ true or false depending on whether the sum fits into 'short'.
These macros are tuned for their last input argument being a constant.
diff --git a/lib/lc-charset-dispatch.c b/lib/lc-charset-dispatch.c
index 4b4d93ddb..98c6e9de7 100644
--- a/lib/lc-charset-dispatch.c
+++ b/lib/lc-charset-dispatch.c
@@ -26,7 +26,7 @@
# include "localcharset.h"
# include "streq.h"
-# if GNULIB_WCHAR_SINGLE
+# if GNULIB_WCHAR_SINGLE_LOCALE
/* When we know that the locale does not change, provide a speedup by
caching the value of locale_encoding_classification. */
# define locale_encoding_classification_cached locale_encoding_classification
@@ -35,7 +35,7 @@
# define locale_encoding_classification_uncached locale_encoding_classification
# endif
-# if GNULIB_WCHAR_SINGLE
+# if GNULIB_WCHAR_SINGLE_LOCALE
static inline
# endif
enc_t
@@ -59,7 +59,7 @@ locale_encoding_classification_uncached (void)
return enc_other;
}
-# if GNULIB_WCHAR_SINGLE
+# if GNULIB_WCHAR_SINGLE_LOCALE
static int cached_locale_enc = -1;
diff --git a/lib/libc-config.h b/lib/libc-config.h
index fcdafcb96..f14013f7e 100644
--- a/lib/libc-config.h
+++ b/lib/libc-config.h
@@ -33,9 +33,9 @@
#include <config.h>
/* On glibc this includes <features.h> and <sys/cdefs.h> and #defines
- _FEATURES_H, __WORDSIZE, and __set_errno. On FreeBSD 11 it
- includes <sys/cdefs.h> which defines __nonnull. Elsewhere it
- is harmless. */
+ _FEATURES_H, __WORDSIZE, and __set_errno. On FreeBSD 11 and
+ DragonFlyBSD 5.9 it includes <sys/cdefs.h> which defines __nonnull.
+ Elsewhere it is harmless. */
#include <errno.h>
/* From glibc <errno.h>. */
diff --git a/lib/link.c b/lib/link.c
index 6fff67a4f..3ba897a8b 100644
--- a/lib/link.c
+++ b/lib/link.c
@@ -117,9 +117,7 @@ link (const char *file1, const char *file2)
*p = '\0';
if (p != dir && stat (dir, &st) != 0 && errno != EOVERFLOW)
{
- int saved_errno = errno;
free (dir);
- errno = saved_errno;
return -1;
}
free (dir);
@@ -228,9 +226,7 @@ rpl_link (char const *file1, char const *file2)
*p = '\0';
if (stat (dir, &st) != 0 && errno != EOVERFLOW)
{
- int saved_errno = errno;
free (dir);
- errno = saved_errno;
return -1;
}
}
diff --git a/lib/malloc.c b/lib/malloc.c
index 0c3e9da68..6bbb97dc2 100644
--- a/lib/malloc.c
+++ b/lib/malloc.c
@@ -30,7 +30,11 @@
#include <stdlib.h>
-#include <errno.h>
+/* A function definition is only needed if NEED_MALLOC_GNU is defined above
+ or if the module 'malloc-posix' requests it. */
+#if NEED_MALLOC_GNU || (GNULIB_MALLOC_POSIX && !HAVE_MALLOC_POSIX)
+
+# include <errno.h>
/* Allocate an N-byte block of memory from the heap.
If N is zero, allocate a 1-byte block. */
@@ -40,17 +44,19 @@ rpl_malloc (size_t n)
{
void *result;
-#if NEED_MALLOC_GNU
+# if NEED_MALLOC_GNU
if (n == 0)
n = 1;
-#endif
+# endif
result = malloc (n);
-#if !HAVE_MALLOC_POSIX
+# if !HAVE_MALLOC_POSIX
if (result == NULL)
errno = ENOMEM;
-#endif
+# endif
return result;
}
+
+#endif
diff --git a/lib/malloc/dynarray-skeleton.c b/lib/malloc/dynarray-skeleton.c
index 5b9f37bdd..48210e325 100644
--- a/lib/malloc/dynarray-skeleton.c
+++ b/lib/malloc/dynarray-skeleton.c
@@ -192,7 +192,7 @@ DYNARRAY_NAME (free__array__) (struct DYNARRAY_STRUCT *list)
/* Initialize a dynamic array object. This must be called before any
use of the object. */
-__nonnull ((1))
+__attribute_nonnull__ ((1))
static void
DYNARRAY_NAME (init) (struct DYNARRAY_STRUCT *list)
{
@@ -202,7 +202,7 @@ DYNARRAY_NAME (init) (struct DYNARRAY_STRUCT *list)
}
/* Deallocate the dynamic array and its elements. */
-__attribute_maybe_unused__ __nonnull ((1))
+__attribute_maybe_unused__ __attribute_nonnull__ ((1))
static void
DYNARRAY_FREE (struct DYNARRAY_STRUCT *list)
{
@@ -213,7 +213,7 @@ DYNARRAY_FREE (struct DYNARRAY_STRUCT *list)
}
/* Return true if the dynamic array is in an error state. */
-__nonnull ((1))
+__attribute_nonnull__ ((1))
static inline bool
DYNARRAY_NAME (has_failed) (const struct DYNARRAY_STRUCT *list)
{
@@ -222,7 +222,7 @@ DYNARRAY_NAME (has_failed) (const struct DYNARRAY_STRUCT *list)
/* Mark the dynamic array as failed. All elements are deallocated as
a side effect. */
-__nonnull ((1))
+__attribute_nonnull__ ((1))
static void
DYNARRAY_NAME (mark_failed) (struct DYNARRAY_STRUCT *list)
{
@@ -236,7 +236,7 @@ DYNARRAY_NAME (mark_failed) (struct DYNARRAY_STRUCT *list)
/* Return the number of elements which have been added to the dynamic
array. */
-__nonnull ((1))
+__attribute_nonnull__ ((1))
static inline size_t
DYNARRAY_NAME (size) (const struct DYNARRAY_STRUCT *list)
{
@@ -245,7 +245,7 @@ DYNARRAY_NAME (size) (const struct DYNARRAY_STRUCT *list)
/* Return a pointer to the array element at INDEX. Terminate the
process if INDEX is out of bounds. */
-__nonnull ((1))
+__attribute_nonnull__ ((1))
static inline DYNARRAY_ELEMENT *
DYNARRAY_NAME (at) (struct DYNARRAY_STRUCT *list, size_t index)
{
@@ -257,7 +257,7 @@ DYNARRAY_NAME (at) (struct DYNARRAY_STRUCT *list, size_t 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))
+__attribute_nonnull__ ((1))
static inline DYNARRAY_ELEMENT *
DYNARRAY_NAME (begin) (struct DYNARRAY_STRUCT *list)
{
@@ -267,7 +267,7 @@ DYNARRAY_NAME (begin) (struct DYNARRAY_STRUCT *list)
/* 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))
+__attribute_nonnull__ ((1))
static inline DYNARRAY_ELEMENT *
DYNARRAY_NAME (end) (struct DYNARRAY_STRUCT *list)
{
@@ -294,7 +294,7 @@ DYNARRAY_NAME (add__) (struct DYNARRAY_STRUCT *list, DYNARRAY_ELEMENT 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))
+__attribute_nonnull__ ((1))
static inline void
DYNARRAY_NAME (add) (struct DYNARRAY_STRUCT *list, DYNARRAY_ELEMENT item)
{
@@ -348,7 +348,8 @@ DYNARRAY_NAME (emplace__) (struct DYNARRAY_STRUCT *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))
+__attribute_maybe_unused__ __attribute_warn_unused_result__
+__attribute_nonnull__ ((1))
static
/* Avoid inlining with the larger initialization code. */
#if !(defined (DYNARRAY_ELEMENT_INIT) || defined (DYNARRAY_ELEMENT_FREE))
@@ -372,7 +373,7 @@ DYNARRAY_NAME (emplace) (struct DYNARRAY_STRUCT *list)
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))
+__attribute_maybe_unused__ __attribute_nonnull__ ((1))
static bool
DYNARRAY_NAME (resize) (struct DYNARRAY_STRUCT *list, size_t size)
{
@@ -417,7 +418,7 @@ DYNARRAY_NAME (resize) (struct DYNARRAY_STRUCT *list, size_t size)
}
/* Remove the last element of LIST if it is present. */
-__attribute_maybe_unused__ __nonnull ((1))
+__attribute_maybe_unused__ __attribute_nonnull__ ((1))
static void
DYNARRAY_NAME (remove_last) (struct DYNARRAY_STRUCT *list)
{
@@ -434,7 +435,7 @@ DYNARRAY_NAME (remove_last) (struct DYNARRAY_STRUCT *list)
/* Remove all elements from the list. The elements are freed, but the
list itself is not. */
-__attribute_maybe_unused__ __nonnull ((1))
+__attribute_maybe_unused__ __attribute_nonnull__ ((1))
static void
DYNARRAY_NAME (clear) (struct DYNARRAY_STRUCT *list)
{
@@ -452,7 +453,8 @@ DYNARRAY_NAME (clear) (struct DYNARRAY_STRUCT *list)
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))
+__attribute_maybe_unused__ __attribute_warn_unused_result__
+__attribute_nonnull__ ((1, 2))
static bool
DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list,
DYNARRAY_FINAL_TYPE *result)
@@ -483,7 +485,8 @@ DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list,
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))
+__attribute_maybe_unused__ __attribute_warn_unused_result__
+__attribute_nonnull__ ((1))
static DYNARRAY_ELEMENT *
DYNARRAY_NAME (finalize) (struct DYNARRAY_STRUCT *list, size_t *lengthp)
{
diff --git a/lib/malloc/dynarray_at_failure.c b/lib/malloc/dynarray_at_failure.c
index 0fa12c7cd..4f840db7c 100644
--- a/lib/malloc/dynarray_at_failure.c
+++ b/lib/malloc/dynarray_at_failure.c
@@ -16,6 +16,10 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
+#ifndef _LIBC
+# include <libc-config.h>
+#endif
+
#include <dynarray.h>
#include <stdio.h>
#include <stdlib.h>
diff --git a/lib/malloc/dynarray_emplace_enlarge.c b/lib/malloc/dynarray_emplace_enlarge.c
index ddfe306fc..0f8baf94a 100644
--- a/lib/malloc/dynarray_emplace_enlarge.c
+++ b/lib/malloc/dynarray_emplace_enlarge.c
@@ -16,6 +16,10 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
+#ifndef _LIBC
+# include <libc-config.h>
+#endif
+
#include <dynarray.h>
#include <errno.h>
#include <intprops.h>
diff --git a/lib/malloc/dynarray_finalize.c b/lib/malloc/dynarray_finalize.c
index 8ec6ad2bc..c33da4138 100644
--- a/lib/malloc/dynarray_finalize.c
+++ b/lib/malloc/dynarray_finalize.c
@@ -16,6 +16,10 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
+#ifndef _LIBC
+# include <libc-config.h>
+#endif
+
#include <dynarray.h>
#include <stdlib.h>
#include <string.h>
diff --git a/lib/malloc/dynarray_resize.c b/lib/malloc/dynarray_resize.c
index 5c60927f3..5a57166a8 100644
--- a/lib/malloc/dynarray_resize.c
+++ b/lib/malloc/dynarray_resize.c
@@ -16,6 +16,10 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
+#ifndef _LIBC
+# include <libc-config.h>
+#endif
+
#include <dynarray.h>
#include <errno.h>
#include <intprops.h>
diff --git a/lib/malloc/dynarray_resize_clear.c b/lib/malloc/dynarray_resize_clear.c
index e893d1d58..9c43b00c3 100644
--- a/lib/malloc/dynarray_resize_clear.c
+++ b/lib/malloc/dynarray_resize_clear.c
@@ -16,6 +16,10 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
+#ifndef _LIBC
+# include <libc-config.h>
+#endif
+
#include <dynarray.h>
#include <string.h>
diff --git a/lib/malloca.h b/lib/malloca.h
index fd40073e3..9cf7fbb52 100644
--- a/lib/malloca.h
+++ b/lib/malloca.h
@@ -77,6 +77,7 @@ extern void freea (void *p);
/* nmalloca(N,S) is an overflow-safe variant of malloca (N * S).
It allocates an array of N objects, each with S bytes of memory,
on the stack. S must be positive and N must be nonnegative.
+ Either N or S should be of type ptrdiff_t or size_t or wider.
The array must be freed using freea() before the function returns. */
#define nmalloca(n, s) (xalloc_oversized (n, s) ? NULL : malloca ((n) * (s)))
diff --git a/lib/math.in.h b/lib/math.in.h
index 73b13fa17..d80047cd6 100644
--- a/lib/math.in.h
+++ b/lib/math.in.h
@@ -2579,7 +2579,7 @@ _GL_EXTERN_C int rpl_isnanl (long double x) _GL_ATTRIBUTE_CONST;
# if defined isnan || defined GNULIB_NAMESPACE
_GL_MATH_CXX_REAL_FLOATING_DECL_1 (isnan)
# undef isnan
-# if __GNUC__ >= 6 || (defined __clang__ && !((defined __APPLE__ && defined __MACH__) || (defined __FreeBSD__ && __clang_major__ < 7) || defined __OpenBSD__ || (defined _WIN32 && !defined __CYGWIN__)))
+# if __GNUC__ >= 6 || (defined __clang__ && !((defined __APPLE__ && defined __MACH__ && __clang_major__ < 12) || (defined __FreeBSD__ && __clang_major__ < 7) || defined __OpenBSD__ || (defined _WIN32 && !defined __CYGWIN__)))
/* This platform's <cmath> possibly defines isnan through a set of inline
functions. */
_GL_MATH_CXX_REAL_FLOATING_DECL_2 (isnan, rpl_isnan, bool)
diff --git a/lib/mbrtowc-impl-utf8.h b/lib/mbrtowc-impl-utf8.h
index b27516bc9..ea5ef1fe5 100644
--- a/lib/mbrtowc-impl-utf8.h
+++ b/lib/mbrtowc-impl-utf8.h
@@ -96,7 +96,7 @@
if ((c2 ^ 0x80) < 0x40
&& (c >= 0xf1 || c2 >= 0x90)
- && (c < 0xf4 || (c == 0xf4 && c2 < 0x90)))
+ && (c < 0xf4 || (/* c == 0xf4 && */ c2 < 0x90)))
{
if (m == 2)
goto incomplete;
diff --git a/lib/mbtowc-lock.h b/lib/mbtowc-lock.h
index 320613eae..093951713 100644
--- a/lib/mbtowc-lock.h
+++ b/lib/mbtowc-lock.h
@@ -32,7 +32,17 @@ mbtowc_unlocked (wchar_t *pwc, const char *p, size_t m)
/* Prohibit renaming this symbol. */
#undef gl_get_mbtowc_lock
-#if defined _WIN32 && !defined __CYGWIN__
+#if GNULIB_MBRTOWC_SINGLE_THREAD
+
+/* All uses of this function are in a single thread. No locking needed. */
+
+static int
+mbtowc_with_lock (wchar_t *pwc, const char *p, size_t m)
+{
+ return mbtowc_unlocked (pwc, p, m);
+}
+
+#elif defined _WIN32 && !defined __CYGWIN__
extern __declspec(dllimport) CRITICAL_SECTION *gl_get_mbtowc_lock (void);
diff --git a/lib/mempcpy.c b/lib/mempcpy.c
index 39e476dae..c80e119f7 100644
--- a/lib/mempcpy.c
+++ b/lib/mempcpy.c
@@ -19,6 +19,9 @@
/* Specification. */
#include <string.h>
+/* A function definition is only needed if HAVE_MEMPCPY is not defined. */
+#if !HAVE_MEMPCPY
+
/* Copy N bytes of SRC to DEST, return pointer to bytes after the
last written byte. */
void *
@@ -26,3 +29,5 @@ mempcpy (void *dest, const void *src, size_t n)
{
return (char *) memcpy (dest, src, n) + n;
}
+
+#endif
diff --git a/lib/putenv.c b/lib/putenv.c
index 665efffa0..d342b8153 100644
--- a/lib/putenv.c
+++ b/lib/putenv.c
@@ -82,15 +82,13 @@ _unsetenv (const char *name)
#if HAVE_DECL__PUTENV
{
- int putenv_result, putenv_errno;
+ int putenv_result;
char *name_ = malloc (len + 2);
memcpy (name_, name, len);
name_[len] = '=';
name_[len + 1] = 0;
putenv_result = _putenv (name_);
- putenv_errno = errno;
free (name_);
- __set_errno (putenv_errno);
return putenv_result;
}
#else
@@ -144,7 +142,7 @@ putenv (char *string)
/* _putenv ("NAME=") unsets NAME, so invoke _putenv ("NAME= ")
to allocate the environ vector and then replace the new
entry with "NAME=". */
- int putenv_result, putenv_errno;
+ int putenv_result;
char *name_x = malloc (name_end - string + sizeof "= ");
if (!name_x)
return -1;
@@ -152,7 +150,6 @@ putenv (char *string)
name_x[name_end - string + 1] = ' ';
name_x[name_end - string + 2] = 0;
putenv_result = _putenv (name_x);
- putenv_errno = errno;
for (ep = environ; *ep; ep++)
if (strcmp (*ep, name_x) == 0)
{
@@ -166,11 +163,10 @@ putenv (char *string)
fix that by calling SetEnvironmentVariable directly. */
name_x[name_end - string] = 0;
putenv_result = SetEnvironmentVariable (name_x, "") ? 0 : -1;
- putenv_errno = ENOMEM; /* ENOMEM is the only way to fail. */
+ errno = ENOMEM; /* ENOMEM is the only way to fail. */
}
# endif
free (name_x);
- __set_errno (putenv_errno);
return putenv_result;
}
#else
diff --git a/lib/rawmemchr.c b/lib/rawmemchr.c
index 655cc8ec9..ef356895e 100644
--- a/lib/rawmemchr.c
+++ b/lib/rawmemchr.c
@@ -19,6 +19,9 @@
/* Specification. */
#include <string.h>
+/* A function definition is only needed if HAVE_RAWMEMCHR is not defined. */
+#if !HAVE_RAWMEMCHR
+
/* Find the first occurrence of C in S. */
void *
rawmemchr (const void *s, int c_in)
@@ -134,3 +137,5 @@ rawmemchr (const void *s, int c_in)
char_ptr++;
return (void *) char_ptr;
}
+
+#endif
diff --git a/lib/realloc.c b/lib/realloc.c
new file mode 100644
index 000000000..114551498
--- /dev/null
+++ b/lib/realloc.c
@@ -0,0 +1,85 @@
+/* realloc() function that is glibc compatible.
+
+ Copyright (C) 1997, 2003-2004, 2006-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 Lesser 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* written by Jim Meyering and Bruno Haible */
+
+#define _GL_USE_STDLIB_ALLOC 1
+#include <config.h>
+
+/* Only the AC_FUNC_REALLOC macro defines 'realloc' already in config.h. */
+#ifdef realloc
+# define NEED_REALLOC_GNU 1
+/* Whereas the gnulib module 'realloc-gnu' defines HAVE_REALLOC_GNU. */
+#elif GNULIB_REALLOC_GNU && !HAVE_REALLOC_GNU
+# define NEED_REALLOC_GNU 1
+#endif
+
+/* Infer the properties of the system's malloc function.
+ The gnulib module 'malloc-gnu' defines HAVE_MALLOC_GNU. */
+#if GNULIB_MALLOC_GNU && HAVE_MALLOC_GNU
+# define SYSTEM_MALLOC_GLIBC_COMPATIBLE 1
+#endif
+
+#include <stdlib.h>
+
+/* A function definition is only needed if NEED_REALLOC_GNU is defined above
+ or if the module 'realloc-posix' requests it. */
+#if NEED_REALLOC_GNU || (GNULIB_REALLOC_POSIX && !HAVE_REALLOC_POSIX)
+
+# include <errno.h>
+
+/* Change the size of an allocated block of memory P to N bytes,
+ with error checking. If N is zero, change it to 1. If P is NULL,
+ use malloc. */
+
+void *
+rpl_realloc (void *p, size_t n)
+{
+ void *result;
+
+# if NEED_REALLOC_GNU
+ if (n == 0)
+ {
+ n = 1;
+
+ /* In theory realloc might fail, so don't rely on it to free. */
+ free (p);
+ p = NULL;
+ }
+# endif
+
+ if (p == NULL)
+ {
+# if GNULIB_REALLOC_GNU && !NEED_REALLOC_GNU && !SYSTEM_MALLOC_GLIBC_COMPATIBLE
+ if (n == 0)
+ n = 1;
+# endif
+ result = malloc (n);
+ }
+ else
+ result = realloc (p, n);
+
+# if !HAVE_REALLOC_POSIX
+ if (result == NULL)
+ errno = ENOMEM;
+# endif
+
+ return result;
+}
+
+#endif
diff --git a/lib/regcomp.c b/lib/regcomp.c
index d93698ae7..887e5b506 100644
--- a/lib/regcomp.c
+++ b/lib/regcomp.c
@@ -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/lib/regex_internal.c b/lib/regex_internal.c
index 9dd387ef8..55f6b66de 100644
--- a/lib/regex_internal.c
+++ b/lib/regex_internal.c
@@ -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/lib/regex_internal.h b/lib/regex_internal.h
index b4f91d9ec..1245e782f 100644
--- a/lib/regex_internal.h
+++ b/lib/regex_internal.h
@@ -32,7 +32,10 @@
#include <stdbool.h>
#include <stdint.h>
-#include <dynarray.h>
+#ifndef _LIBC
+# include <dynarray.h>
+#endif
+
#include <intprops.h>
#include <verify.h>
@@ -50,14 +53,14 @@
# define lock_fini(lock) ((void) 0)
# define lock_lock(lock) __libc_lock_lock (lock)
# define lock_unlock(lock) __libc_lock_unlock (lock)
-#elif defined GNULIB_LOCK && !defined USE_UNLOCKED_IO
+#elif defined GNULIB_LOCK && !defined GNULIB_REGEX_SINGLE_THREAD
# include "glthread/lock.h"
# define lock_define(name) gl_lock_define (, name)
# define lock_init(lock) glthread_lock_init (&(lock))
# define lock_fini(lock) glthread_lock_destroy (&(lock))
# define lock_lock(lock) glthread_lock_lock (&(lock))
# define lock_unlock(lock) glthread_lock_unlock (&(lock))
-#elif defined GNULIB_PTHREAD && !defined USE_UNLOCKED_IO
+#elif defined GNULIB_PTHREAD && !defined GNULIB_REGEX_SINGLE_THREAD
# include <pthread.h>
# define lock_define(name) pthread_mutex_t name;
# define lock_init(lock) pthread_mutex_init (&(lock), 0)
@@ -830,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/lib/regexec.c b/lib/regexec.c
index f7b4f9cfc..6309deac8 100644
--- a/lib/regexec.c
+++ b/lib/regexec.c
@@ -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,25 +1334,30 @@ 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;
}
@@ -1407,33 +1413,32 @@ set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch,
{
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);
- regmatch_list_free (&prev_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);
regmatch_list_free (&prev_match);
- return REG_NOERROR;
+ 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))
@@ -1445,13 +1450,13 @@ set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch,
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);
regmatch_list_free (&prev_match);
+ free_fail_stack_return (fs);
return REG_NOMATCH;
}
}
@@ -1495,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;
@@ -2195,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. */
@@ -2395,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,
@@ -2817,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__
@@ -3433,7 +3440,8 @@ build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)
/* 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,
@@ -4211,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/lib/rename.c b/lib/rename.c
index 0d9f2039c..487302543 100644
--- a/lib/rename.c
+++ b/lib/rename.c
@@ -165,10 +165,8 @@ rpl_rename (char const *src, char const *dst)
}
if (rmdir (dst))
{
- error = errno;
free (src_temp);
free (dst_temp);
- errno = error;
return -1;
}
free (src_temp);
diff --git a/lib/scratch_buffer.h b/lib/scratch_buffer.h
index 5b8f61706..4b17f72ea 100644
--- a/lib/scratch_buffer.h
+++ b/lib/scratch_buffer.h
@@ -19,12 +19,105 @@
#ifndef _GL_SCRATCH_BUFFER_H
#define _GL_SCRATCH_BUFFER_H
+/* Scratch buffers with a default stack allocation and fallback to
+ heap allocation. It is expected that this function is used in this
+ way:
+
+ struct scratch_buffer tmpbuf;
+ scratch_buffer_init (&tmpbuf);
+
+ while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length))
+ if (!scratch_buffer_grow (&tmpbuf))
+ return -1;
+
+ scratch_buffer_free (&tmpbuf);
+ return 0;
+
+ The allocation functions (scratch_buffer_grow,
+ scratch_buffer_grow_preserve, scratch_buffer_set_array_size) make
+ sure that the heap allocation, if any, is freed, so that the code
+ above does not have a memory leak. The buffer still remains in a
+ state that can be deallocated using scratch_buffer_free, so a loop
+ like this is valid as well:
+
+ struct scratch_buffer tmpbuf;
+ scratch_buffer_init (&tmpbuf);
+
+ while (!function_that_uses_buffer (tmpbuf.data, tmpbuf.length))
+ if (!scratch_buffer_grow (&tmpbuf))
+ break;
+
+ scratch_buffer_free (&tmpbuf);
+
+ scratch_buffer_grow and scratch_buffer_grow_preserve are guaranteed
+ to grow the buffer by at least 512 bytes. This means that when
+ using the scratch buffer as a backing store for a non-character
+ array whose element size, in bytes, is 512 or smaller, the scratch
+ buffer only has to grow once to make room for at least one more
+ element.
+*/
+
+/* Scratch buffer. Must be initialized with scratch_buffer_init
+ before its use. */
+struct scratch_buffer;
+
+/* Initializes *BUFFER so that BUFFER->data points to BUFFER->__space
+ and BUFFER->length reflects the available space. */
+#if 0
+extern void scratch_buffer_init (struct scratch_buffer *buffer);
+#endif
+
+/* Deallocates *BUFFER (if it was heap-allocated). */
+#if 0
+extern void scratch_buffer_free (struct scratch_buffer *buffer);
+#endif
+
+/* Grow *BUFFER by some arbitrary amount. The buffer contents is NOT
+ preserved. Return true on success, false on allocation failure (in
+ which case the old buffer is freed). On success, the new buffer is
+ larger than the previous size. On failure, *BUFFER is deallocated,
+ but remains in a free-able state, and errno is set. */
+#if 0
+extern bool scratch_buffer_grow (struct scratch_buffer *buffer);
+#endif
+
+/* Like scratch_buffer_grow, but preserve the old buffer
+ contents on success, as a prefix of the new buffer. */
+#if 0
+extern bool scratch_buffer_grow_preserve (struct scratch_buffer *buffer);
+#endif
+
+/* Grow *BUFFER so that it can store at least NELEM elements of SIZE
+ bytes. The buffer contents are NOT preserved. Both NELEM and SIZE
+ can be zero. Return true on success, false on allocation failure
+ (in which case the old buffer is freed, but *BUFFER remains in a
+ free-able state, and errno is set). It is unspecified whether this
+ function can reduce the array size. */
+#if 0
+extern bool scratch_buffer_set_array_size (struct scratch_buffer *buffer,
+ size_t nelem, size_t size);
+#endif
+
+/* Return a copy of *BUFFER's first SIZE bytes as a heap-allocated block,
+ deallocating *BUFFER if it was heap-allocated. SIZE must be at
+ most *BUFFER's size. Return NULL (setting errno) on memory
+ exhaustion. */
+#if 0
+extern void *scratch_buffer_dupfree (struct scratch_buffer *buffer,
+ size_t size);
+#endif
+
+
+/* The implementation is imported from glibc. */
+
#include <libc-config.h>
+/* Avoid possible conflicts with symbols exported by the GNU libc. */
#define __libc_scratch_buffer_dupfree gl_scratch_buffer_dupfree
#define __libc_scratch_buffer_grow gl_scratch_buffer_grow
#define __libc_scratch_buffer_grow_preserve gl_scratch_buffer_grow_preserve
#define __libc_scratch_buffer_set_array_size gl_scratch_buffer_set_array_size
+
#include <malloc/scratch_buffer.h>
#endif /* _GL_SCRATCH_BUFFER_H */
diff --git a/lib/stdalign.in.h b/lib/stdalign.in.h
index 597293db8..7b51043ec 100644
--- a/lib/stdalign.in.h
+++ b/lib/stdalign.in.h
@@ -104,12 +104,13 @@
#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112
# if defined __cplusplus && 201103 <= __cplusplus
# define _Alignas(a) alignas (a)
-# elif ((defined __APPLE__ && defined __MACH__ \
- ? 4 < __GNUC__ + (1 <= __GNUC_MINOR__) \
- : __GNUC__ && !defined __ibmxl__) \
- || (4 <= __clang_major__) \
- || (__ia64 && (61200 <= __HP_cc || 61200 <= __HP_aCC)) \
- || __ICC || 0x590 <= __SUNPRO_C || 0x0600 <= __xlC__)
+# elif (!defined __attribute__ \
+ && ((defined __APPLE__ && defined __MACH__ \
+ ? 4 < __GNUC__ + (1 <= __GNUC_MINOR__) \
+ : __GNUC__ && !defined __ibmxl__) \
+ || (4 <= __clang_major__) \
+ || (__ia64 && (61200 <= __HP_cc || 61200 <= __HP_aCC)) \
+ || __ICC || 0x590 <= __SUNPRO_C || 0x0600 <= __xlC__))
# define _Alignas(a) __attribute__ ((__aligned__ (a)))
# elif 1300 <= _MSC_VER
# define _Alignas(a) __declspec (align (a))
diff --git a/lib/stddef.in.h b/lib/stddef.in.h
index b4f617298..4c53e6455 100644
--- a/lib/stddef.in.h
+++ b/lib/stddef.in.h
@@ -42,6 +42,13 @@
# define _GL_STDDEF_WINT_T
# endif
# @INCLUDE_NEXT@ @NEXT_STDDEF_H@
+ /* On TinyCC, make sure that the macros that indicate the special invocation
+ convention get undefined. */
+# undef __need_wchar_t
+# undef __need_size_t
+# undef __need_ptrdiff_t
+# undef __need_NULL
+# undef __need_wint_t
# endif
#else
@@ -51,7 +58,7 @@
/* On AIX 7.2, with xlc in 64-bit mode, <stddef.h> defines max_align_t to a
type with alignment 4, but 'long' has alignment 8. */
-# if defined _AIX && defined _ARCH_PPC64
+# if defined _AIX && defined __LP64__
# if !GNULIB_defined_max_align_t
# ifdef _MAX_ALIGN_T
/* /usr/include/stddef.h has already defined max_align_t. Override it. */
@@ -109,7 +116,7 @@ typedef long max_align_t;
&& defined __cplusplus
# include <cstddef>
#else
-# if ! (@HAVE_MAX_ALIGN_T@ || defined _GCC_MAX_ALIGN_T)
+# if ! (@HAVE_MAX_ALIGN_T@ || (defined _GCC_MAX_ALIGN_T && !defined __clang__))
# if !GNULIB_defined_max_align_t
/* On the x86, the maximum storage alignment of double, long, etc. is 4,
but GCC's C11 ABI for x86 says that max_align_t has an alignment of 8,
diff --git a/lib/stdlib.in.h b/lib/stdlib.in.h
index 9edad426c..7e012621d 100644
--- a/lib/stdlib.in.h
+++ b/lib/stdlib.in.h
@@ -1202,6 +1202,47 @@ _GL_WARN_ON_USE (strtold, "strtold is unportable - "
# endif
#endif
+#if @GNULIB_STRTOL@
+/* Parse a signed integer whose textual representation starts at STRING.
+ The integer is expected to be in base BASE (2 <= BASE <= 36); if BASE == 0,
+ it may be decimal or octal (with prefix "0") or hexadecimal (with prefix
+ "0x").
+ If ENDPTR is not NULL, the address of the first byte after the integer is
+ stored in *ENDPTR.
+ Upon overflow, the return value is LONG_MAX or LONG_MIN, and errno is set
+ to ERANGE. */
+# if @REPLACE_STRTOL@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# define strtol rpl_strtol
+# endif
+# define GNULIB_defined_strtol_function 1
+_GL_FUNCDECL_RPL (strtol, long,
+ (const char *restrict string, char **restrict endptr,
+ int base)
+ _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (strtol, long,
+ (const char *restrict string, char **restrict endptr,
+ int base));
+# else
+# if !@HAVE_STRTOL@
+_GL_FUNCDECL_SYS (strtol, long,
+ (const char *restrict string, char **restrict endptr,
+ int base)
+ _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (strtol, long,
+ (const char *restrict string, char **restrict endptr,
+ int base));
+# endif
+_GL_CXXALIASWARN (strtol);
+#elif defined GNULIB_POSIXCHECK
+# undef strtol
+# if HAVE_RAW_DECL_STRTOL
+_GL_WARN_ON_USE (strtol, "strtol is unportable - "
+ "use gnulib module strtol for portability");
+# endif
+#endif
+
#if @GNULIB_STRTOLL@
/* Parse a signed integer whose textual representation starts at STRING.
The integer is expected to be in base BASE (2 <= BASE <= 36); if BASE == 0,
@@ -1211,15 +1252,29 @@ _GL_WARN_ON_USE (strtold, "strtold is unportable - "
stored in *ENDPTR.
Upon overflow, the return value is LLONG_MAX or LLONG_MIN, and errno is set
to ERANGE. */
-# if !@HAVE_STRTOLL@
+# if @REPLACE_STRTOLL@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# define strtoll rpl_strtoll
+# endif
+# define GNULIB_defined_strtoll_function 1
+_GL_FUNCDECL_RPL (strtoll, long long,
+ (const char *restrict string, char **restrict endptr,
+ int base)
+ _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (strtoll, long long,
+ (const char *restrict string, char **restrict endptr,
+ int base));
+# else
+# if !@HAVE_STRTOLL@
_GL_FUNCDECL_SYS (strtoll, long long,
(const char *restrict string, char **restrict endptr,
int base)
_GL_ARG_NONNULL ((1)));
-# endif
+# endif
_GL_CXXALIAS_SYS (strtoll, long long,
(const char *restrict string, char **restrict endptr,
int base));
+# endif
_GL_CXXALIASWARN (strtoll);
#elif defined GNULIB_POSIXCHECK
# undef strtoll
@@ -1229,6 +1284,46 @@ _GL_WARN_ON_USE (strtoll, "strtoll is unportable - "
# endif
#endif
+#if @GNULIB_STRTOUL@
+/* Parse an unsigned integer whose textual representation starts at STRING.
+ The integer is expected to be in base BASE (2 <= BASE <= 36); if BASE == 0,
+ it may be decimal or octal (with prefix "0") or hexadecimal (with prefix
+ "0x").
+ If ENDPTR is not NULL, the address of the first byte after the integer is
+ stored in *ENDPTR.
+ Upon overflow, the return value is ULONG_MAX, and errno is set to ERANGE. */
+# if @REPLACE_STRTOUL@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# define strtoul rpl_strtoul
+# endif
+# define GNULIB_defined_strtoul_function 1
+_GL_FUNCDECL_RPL (strtoul, unsigned long,
+ (const char *restrict string, char **restrict endptr,
+ int base)
+ _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (strtoul, unsigned long,
+ (const char *restrict string, char **restrict endptr,
+ int base));
+# else
+# if !@HAVE_STRTOUL@
+_GL_FUNCDECL_SYS (strtoul, unsigned long,
+ (const char *restrict string, char **restrict endptr,
+ int base)
+ _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (strtoul, unsigned long,
+ (const char *restrict string, char **restrict endptr,
+ int base));
+# endif
+_GL_CXXALIASWARN (strtoul);
+#elif defined GNULIB_POSIXCHECK
+# undef strtoul
+# if HAVE_RAW_DECL_STRTOUL
+_GL_WARN_ON_USE (strtoul, "strtoul is unportable - "
+ "use gnulib module strtoul for portability");
+# endif
+#endif
+
#if @GNULIB_STRTOULL@
/* Parse an unsigned integer whose textual representation starts at STRING.
The integer is expected to be in base BASE (2 <= BASE <= 36); if BASE == 0,
@@ -1238,15 +1333,29 @@ _GL_WARN_ON_USE (strtoll, "strtoll is unportable - "
stored in *ENDPTR.
Upon overflow, the return value is ULLONG_MAX, and errno is set to
ERANGE. */
-# if !@HAVE_STRTOULL@
+# if @REPLACE_STRTOULL@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# define strtoull rpl_strtoull
+# endif
+# define GNULIB_defined_strtoull_function 1
+_GL_FUNCDECL_RPL (strtoull, unsigned long long,
+ (const char *restrict string, char **restrict endptr,
+ int base)
+ _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (strtoull, unsigned long long,
+ (const char *restrict string, char **restrict endptr,
+ int base));
+# else
+# if !@HAVE_STRTOULL@
_GL_FUNCDECL_SYS (strtoull, unsigned long long,
(const char *restrict string, char **restrict endptr,
int base)
_GL_ARG_NONNULL ((1)));
-# endif
+# endif
_GL_CXXALIAS_SYS (strtoull, unsigned long long,
(const char *restrict string, char **restrict endptr,
int base));
+# endif
_GL_CXXALIASWARN (strtoull);
#elif defined GNULIB_POSIXCHECK
# undef strtoull
diff --git a/lib/striconveh.c b/lib/striconveh.c
index d24d2d362..82f6467ba 100644
--- a/lib/striconveh.c
+++ b/lib/striconveh.c
@@ -499,11 +499,7 @@ mem_cd_iconveh_internal (const char *src, size_t srclen,
else
{
if (result != initial_result)
- {
- int saved_errno = errno;
- free (result);
- errno = saved_errno;
- }
+ free (result);
return -1;
}
}
@@ -570,11 +566,7 @@ mem_cd_iconveh_internal (const char *src, size_t srclen,
else
{
if (result != initial_result)
- {
- int saved_errno = errno;
- free (result);
- errno = saved_errno;
- }
+ free (result);
return -1;
}
}
@@ -683,11 +675,7 @@ mem_cd_iconveh_internal (const char *src, size_t srclen,
&& !(errno == E2BIG || errno == EINVAL || errno == EILSEQ))
{
if (result != initial_result)
- {
- int saved_errno = errno;
- free (result);
- errno = saved_errno;
- }
+ free (result);
return -1;
}
if (res1 == (size_t)(-1)
@@ -907,22 +895,14 @@ mem_cd_iconveh_internal (const char *src, size_t srclen,
{
/* Failure converting the ASCII replacement. */
if (result != initial_result)
- {
- int saved_errno = errno;
- free (result);
- errno = saved_errno;
- }
+ free (result);
return -1;
}
}
else
{
if (result != initial_result)
- {
- int saved_errno = errno;
- free (result);
- errno = saved_errno;
- }
+ free (result);
return -1;
}
}
@@ -1041,12 +1021,7 @@ str_cd_iconveh (const char *src,
if (retval < 0)
{
- if (result != NULL)
- {
- int saved_errno = errno;
- free (result);
- errno = saved_errno;
- }
+ free (result);
return NULL;
}
@@ -1118,12 +1093,8 @@ mem_iconveh (const char *src, size_t srclen,
{
if (iconveh_close (&cd) < 0)
{
- /* Return -1, but free the allocated memory, and while doing
- that, preserve the errno from iconveh_close. */
- int saved_errno = errno;
- if (result != *resultp && result != NULL)
+ if (result != *resultp)
free (result);
- errno = saved_errno;
return -1;
}
*resultp = result;
@@ -1177,11 +1148,7 @@ str_iconveh (const char *src,
{
if (iconveh_close (&cd) < 0)
{
- /* Return NULL, but free the allocated memory, and while doing
- that, preserve the errno from iconveh_close. */
- int saved_errno = errno;
free (result);
- errno = saved_errno;
return NULL;
}
}
diff --git a/lib/time.in.h b/lib/time.in.h
index fe1a1e81d..cbd2bbaf7 100644
--- a/lib/time.in.h
+++ b/lib/time.in.h
@@ -340,22 +340,60 @@ _GL_CXXALIASWARN (strftime);
# endif
# if defined _GNU_SOURCE && @GNULIB_TIME_RZ@ && ! @HAVE_TIMEZONE_T@
+/* Functions that use a first-class time zone data type, instead of
+ relying on an implicit global time zone.
+ Inspired by NetBSD. */
+
+/* Represents a time zone.
+ (timezone_t) NULL stands for UTC. */
typedef struct tm_zone *timezone_t;
+
+/* tzalloc (name)
+ Returns a time zone object for the given time zone NAME. This object
+ represents the time zone that other functions would use it the TZ
+ environment variable was set to NAME.
+ If NAME is NULL, the result represents the time zone that other functions
+ would use it the TZ environment variable was unset.
+ May return NULL if NAME is invalid (this is platform dependent) or
+ upon memory allocation failure. */
_GL_FUNCDECL_SYS (tzalloc, timezone_t, (char const *__name));
_GL_CXXALIAS_SYS (tzalloc, timezone_t, (char const *__name));
+
+/* tzfree (tz)
+ Frees a time zone object.
+ The argument must have been returned by tzalloc(). */
_GL_FUNCDECL_SYS (tzfree, void, (timezone_t __tz));
_GL_CXXALIAS_SYS (tzfree, void, (timezone_t __tz));
+
+/* localtime_rz (tz, &t, &result)
+ Converts an absolute time T to a broken-down time RESULT, assuming the
+ time zone TZ.
+ This function is like 'localtime_r', but relies on the argument TZ instead
+ of an implicit global time zone. */
_GL_FUNCDECL_SYS (localtime_rz, struct tm *,
(timezone_t __tz, time_t const *restrict __timer,
struct tm *restrict __result) _GL_ARG_NONNULL ((2, 3)));
_GL_CXXALIAS_SYS (localtime_rz, struct tm *,
(timezone_t __tz, time_t const *restrict __timer,
struct tm *restrict __result));
+
+/* mktime_z (tz, &tm)
+ Normalizes the broken-down time TM and converts it to an absolute time,
+ assuming the time zone TZ. Returns the absolute time.
+ This function is like 'mktime', but relies on the argument TZ instead
+ of an implicit global time zone. */
_GL_FUNCDECL_SYS (mktime_z, time_t,
- (timezone_t __tz, struct tm *restrict __result)
+ (timezone_t __tz, struct tm *restrict __tm)
_GL_ARG_NONNULL ((2)));
_GL_CXXALIAS_SYS (mktime_z, time_t,
- (timezone_t __tz, struct tm *restrict __result));
+ (timezone_t __tz, struct tm *restrict __tm));
+
+/* Time zone abbreviation strings (returned by 'localtime_rz' or 'mktime_z'
+ in the 'tm_zone' member of 'struct tm') are valid as long as
+ - the 'struct tm' argument is not destroyed or overwritten,
+ and
+ - the 'timezone_t' argument is not freed through tzfree(). */
+
# endif
/* Convert TM to a time_t value, assuming UTC. */
diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c
index a6249ff3c..8d5100695 100644
--- a/lib/vasnprintf.c
+++ b/lib/vasnprintf.c
@@ -1859,6 +1859,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
/* errno is already set. */
return NULL;
+ /* Frees the memory allocated by this function. Preserves errno. */
#define CLEANUP() \
if (d.dir != d.direct_alloc_dir) \
free (d.dir); \
@@ -2183,13 +2184,11 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
# endif
if (converted == NULL)
{
- int saved_errno = errno;
if (!(result == resultbuf || result == NULL))
free (result);
if (buf_malloced != NULL)
free (buf_malloced);
CLEANUP ();
- errno = saved_errno;
return NULL;
}
if (converted != result + length)
@@ -2309,13 +2308,11 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
# endif
if (converted == NULL)
{
- int saved_errno = errno;
if (!(result == resultbuf || result == NULL))
free (result);
if (buf_malloced != NULL)
free (buf_malloced);
CLEANUP ();
- errno = saved_errno;
return NULL;
}
if (converted != result + length)
@@ -2435,13 +2432,11 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
# endif
if (converted == NULL)
{
- int saved_errno = errno;
if (!(result == resultbuf || result == NULL))
free (result);
if (buf_malloced != NULL)
free (buf_malloced);
CLEANUP ();
- errno = saved_errno;
return NULL;
}
if (converted != result + length)
@@ -2852,14 +2847,12 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
NULL, &tmpdst_len);
if (tmpdst == NULL)
{
- int saved_errno = errno;
free (tmpsrc);
if (!(result == resultbuf || result == NULL))
free (result);
if (buf_malloced != NULL)
free (buf_malloced);
CLEANUP ();
- errno = saved_errno;
return NULL;
}
free (tmpsrc);
@@ -3079,13 +3072,11 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
NULL, &tmpdst_len);
if (tmpdst == NULL)
{
- int saved_errno = errno;
if (!(result == resultbuf || result == NULL))
free (result);
if (buf_malloced != NULL)
free (buf_malloced);
CLEANUP ();
- errno = saved_errno;
return NULL;
}
# endif
@@ -5449,15 +5440,14 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
/* Attempt to handle failure. */
if (count < 0)
{
- /* SNPRINTF or sprintf failed. Save and use the errno
- that it has set, if any. */
- int saved_errno = errno;
- if (saved_errno == 0)
+ /* SNPRINTF or sprintf failed. Use the errno that it
+ has set, if any. */
+ if (errno == 0)
{
if (dp->conversion == 'c' || dp->conversion == 's')
- saved_errno = EILSEQ;
+ errno = EILSEQ;
else
- saved_errno = EINVAL;
+ errno = EINVAL;
}
if (!(result == resultbuf || result == NULL))
@@ -5466,7 +5456,6 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
free (buf_malloced);
CLEANUP ();
- errno = saved_errno;
return NULL;
}
@@ -5602,13 +5591,11 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
NULL, &tmpdst_len);
if (tmpdst == NULL)
{
- int saved_errno = errno;
if (!(result == resultbuf || result == NULL))
free (result);
if (buf_malloced != NULL)
free (buf_malloced);
CLEANUP ();
- errno = saved_errno;
return NULL;
}
ENSURE_ALLOCATION (xsum (length, tmpdst_len));
diff --git a/lib/xalloc-oversized.h b/lib/xalloc-oversized.h
index 36a05d5ce..d25596932 100644
--- a/lib/xalloc-oversized.h
+++ b/lib/xalloc-oversized.h
@@ -21,34 +21,34 @@
#include <stddef.h>
#include <stdint.h>
-/* True if N * S would overflow in a size_t calculation,
- or would generate a value larger than PTRDIFF_MAX.
+/* True if N * S does not fit into both ptrdiff_t and size_t.
+ S must be positive and N must be nonnegative.
This expands to a constant expression if N and S are both constants.
- By gnulib convention, SIZE_MAX represents overflow in size
+ By gnulib convention, SIZE_MAX represents overflow in size_t
calculations, so the conservative size_t-based dividend to use here
is SIZE_MAX - 1. */
#define __xalloc_oversized(n, s) \
((size_t) (PTRDIFF_MAX < SIZE_MAX ? PTRDIFF_MAX : SIZE_MAX - 1) / (s) < (n))
#if PTRDIFF_MAX < SIZE_MAX
-typedef ptrdiff_t __xalloc_count_type;
+typedef ptrdiff_t xalloc_count_t;
#else
-typedef size_t __xalloc_count_type;
+typedef size_t xalloc_count_t;
#endif
-/* Return 1 if an array of N objects, each of size S, cannot exist
- reliably due to size or ptrdiff_t arithmetic overflow. S must be
- positive and N must be nonnegative. This is a macro, not a
- function, so that it works correctly even when SIZE_MAX < N. */
-
+/* Return 1 if an array of N objects, each of size S, cannot exist reliably
+ because its total size in bytes exceeds MIN (PTRDIFF_MAX, SIZE_MAX).
+ N must be nonnegative, S must be positive, and either N or S should be
+ of type ptrdiff_t or size_t or wider. This is a macro, not a function,
+ so that it works even if an argument exceeds MAX (PTRDIFF_MAX, SIZE_MAX). */
#if 7 <= __GNUC__ && !defined __clang__
# define xalloc_oversized(n, s) \
- __builtin_mul_overflow_p (n, s, (__xalloc_count_type) 1)
+ __builtin_mul_overflow_p (n, s, (xalloc_count_t) 1)
#elif 5 <= __GNUC__ && !defined __ICC && !__STRICT_ANSI__
# define xalloc_oversized(n, s) \
(__builtin_constant_p (n) && __builtin_constant_p (s) \
? __xalloc_oversized (n, s) \
- : ({ __xalloc_count_type __xalloc_count; \
+ : ({ xalloc_count_t __xalloc_count; \
__builtin_mul_overflow (n, s, &__xalloc_count); }))
/* Other compilers use integer division; this may be slower but is