| --- a/lib/search.in.h |
| +++ b/lib/search.in.h |
| @@ -112,6 +112,11 @@ _GL_CXXALIASWARN (lsearch); |
| # define twalk rpl_twalk |
| # endif |
| # endif |
| +# if @REPLACE_TDESTROY@ |
| +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) |
| +# define tdestroy rpl_tdestroy |
| +# endif |
| +# endif |
| |
| /* See <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/search.h.html> |
| <https://pubs.opengroup.org/onlinepubs/9699919799/functions/tsearch.html> |
| @@ -137,6 +142,7 @@ extern "C" { |
| # if !GNULIB_defined_search_fn_types |
| typedef int (*_gl_search_compar_fn) (const void *, const void *); |
| typedef void (*_gl_search_action_fn) (const void *, VISIT, int); |
| +typedef void (*_gl_search_free_fn) (void *); |
| # define GNULIB_defined_search_fn_types 1 |
| # endif |
| # ifdef __cplusplus |
| @@ -252,9 +258,36 @@ _GL_CXXALIAS_SYS (twalk, void, |
| _GL_CXXALIASWARN (twalk); |
| # endif |
| |
| +/* Removes the whole tree pointed to by root, |
| + freeing all resources allocated by the tsearch() function. |
| + The FREE_NODE function is called: |
| + - For the data in each tree node. |
| + - Even when no such work is necessary, to a function doing nothing |
| + The arguments passed to FREE_NODE are: |
| + 1. The pointer to the data. */ |
| +# if @REPLACE_TDESTROY@ |
| +_GL_FUNCDECL_RPL (tdestroy, void, |
| + (void *vroot, _gl_search_free_fn freefct) |
| + _GL_ARG_NONNULL ((2))); |
| +_GL_CXXALIAS_RPL (tdestroy, void, |
| + (void *vroot, _gl_search_free_fn freefct)); |
| +# else |
| +# if !@HAVE_TDESTROY@ |
| +_GL_FUNCDECL_SYS (tdestroy, void, |
| + (void *vroot, _gl_search_free_fn freefct) |
| + _GL_ARG_NONNULL ((2))); |
| +# endif |
| +_GL_CXXALIAS_SYS (tdestroy, void, |
| + (void *vroot, _gl_search_free_fn freefct)); |
| +# endif |
| +# if __GLIBC__ >= 2 |
| +_GL_CXXALIASWARN (tdestroy); |
| +# endif |
| + |
| /* Flags used by tsearch.c. */ |
| # define GNULIB_defined_tsearch (@REPLACE_TSEARCH@ || !@HAVE_TSEARCH@) |
| # define GNULIB_defined_twalk (@REPLACE_TWALK@ || !@HAVE_TWALK@) |
| +# define GNULIB_defined_tdestroy (@REPLACE_TDESTROY@ || !@HAVE_TDESTROY@) |
| |
| #elif defined GNULIB_POSIXCHECK |
| # undef tsearch |
| @@ -277,6 +310,11 @@ _GL_WARN_ON_USE (tdelete, "tdelete is un |
| _GL_WARN_ON_USE (twalk, "twalk is unportable - " |
| "use gnulib module tsearch for portability"); |
| # endif |
| +# undef tdestroy |
| +# if HAVE_RAW_DECL_TDESTROY |
| +_GL_WARN_ON_USE (tdestroy, "tdestroy is unportable - " |
| + "use gnulib module tsearch for portability"); |
| +# endif |
| #endif |
| |
| |
| --- a/lib/tsearch.c |
| +++ b/lib/tsearch.c |
| @@ -98,12 +98,14 @@ |
| |
| typedef int (*__compar_fn_t) (const void *, const void *); |
| typedef void (*__action_fn_t) (const void *, VISIT, int); |
| +typedef void (*__free_fn_t) (void *); |
| |
| #ifndef weak_alias |
| # define __tsearch tsearch |
| # define __tfind tfind |
| # define __tdelete tdelete |
| # define __twalk twalk |
| +# define __tdestroy tdestroy |
| #endif |
| |
| #ifndef internal_function |
| @@ -656,7 +658,7 @@ weak_alias (__twalk, twalk) |
| #endif /* GNULIB_defined_twalk */ |
| |
| |
| -#ifdef _LIBC |
| +#if defined(_LIBC) || GNULIB_defined_tdestroy |
| |
| /* The standardized functions miss an important functionality: the |
| tree cannot be removed easily. We provide a function to do this. */ |
| @@ -683,6 +685,8 @@ __tdestroy (void *vroot, __free_fn_t fre |
| if (root != NULL) |
| tdestroy_recurse (root, freefct); |
| } |
| +#ifdef weak_alias |
| weak_alias (__tdestroy, tdestroy) |
| +#endif |
| |
| -#endif /* _LIBC */ |
| +#endif /* defined(_LIBC) || GNULIB_defined_tdestroy */ |
| --- a/m4/search_h.m4 |
| +++ b/m4/search_h.m4 |
| @@ -39,7 +39,7 @@ AC_DEFUN_ONCE([gl_SEARCH_H], |
| dnl Check for declarations of anything we want to poison if the |
| dnl corresponding gnulib module is not in use. |
| gl_WARN_ON_USE_PREPARE([[#include <search.h> |
| - ]], [tdelete tfind tsearch twalk]) |
| + ]], [tdelete tfind tsearch twalk tdestroy]) |
| |
| AC_REQUIRE([AC_C_RESTRICT]) |
| ]) |
| @@ -75,8 +75,10 @@ AC_DEFUN([gl_SEARCH_H_DEFAULTS], |
| gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MDA_LFIND], [1]) |
| gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MDA_LSEARCH], [1]) |
| dnl Assume proper GNU behavior unless another module says otherwise. |
| - HAVE_TSEARCH=1; AC_SUBST([HAVE_TSEARCH]) |
| - HAVE_TWALK=1; AC_SUBST([HAVE_TWALK]) |
| - REPLACE_TSEARCH=0; AC_SUBST([REPLACE_TSEARCH]) |
| - REPLACE_TWALK=0; AC_SUBST([REPLACE_TWALK]) |
| + HAVE_TSEARCH=1; AC_SUBST([HAVE_TSEARCH]) |
| + HAVE_TWALK=1; AC_SUBST([HAVE_TWALK]) |
| + HAVE_TDESTROY=1; AC_SUBST([HAVE_TDESTROY]) |
| + REPLACE_TSEARCH=0; AC_SUBST([REPLACE_TSEARCH]) |
| + REPLACE_TWALK=0; AC_SUBST([REPLACE_TWALK]) |
| + REPLACE_TDESTROY=0; AC_SUBST([REPLACE_TDESTROY]) |
| ]) |
| --- a/m4/tsearch.m4 |
| +++ b/m4/tsearch.m4 |
| @@ -9,6 +9,7 @@ AC_DEFUN([gl_FUNC_TSEARCH], |
| AC_REQUIRE([gl_SEARCH_H_DEFAULTS]) |
| gl_CHECK_FUNCS_ANDROID([tsearch], [[#include <search.h>]]) |
| gl_CHECK_FUNCS_ANDROID([twalk], [[#include <search.h>]]) |
| + gl_CHECK_FUNCS_ANDROID([tdestroy], [[#include <search.h>]]) |
| if test $ac_cv_func_tsearch = yes; then |
| dnl On OpenBSD 4.0, the return value of tdelete() is incorrect. |
| AC_REQUIRE([AC_PROG_CC]) |
| @@ -50,6 +51,7 @@ main () |
| *no) |
| REPLACE_TSEARCH=1 |
| REPLACE_TWALK=1 |
| + REPLACE_TDESTROY=1 |
| ;; |
| esac |
| else |
| @@ -64,6 +66,12 @@ main () |
| future*) REPLACE_TWALK=1 ;; |
| esac |
| fi |
| + if test $ac_cv_func_tdestroy != yes; then |
| + HAVE_TDESTROY=0 |
| + case "$gl_cv_onwards_func_tdestroy" in |
| + future*) REPLACE_TDESTROY=1 ;; |
| + esac |
| + fi |
| ]) |
| |
| # Prerequisites of lib/tsearch.c. |
| --- a/modules/search |
| +++ b/modules/search |
| @@ -37,8 +37,10 @@ search.h: search.in.h $(top_builddir)/co |
| -e 's/@''GNULIB_MDA_LSEARCH''@/$(GNULIB_MDA_LSEARCH)/g' \ |
| -e 's|@''HAVE_TSEARCH''@|$(HAVE_TSEARCH)|g' \ |
| -e 's|@''HAVE_TWALK''@|$(HAVE_TWALK)|g' \ |
| + -e 's|@''HAVE_TDESTROY''@|$(HAVE_TDESTROY)|g' \ |
| -e 's|@''REPLACE_TSEARCH''@|$(REPLACE_TSEARCH)|g' \ |
| -e 's|@''REPLACE_TWALK''@|$(REPLACE_TWALK)|g' \ |
| + -e 's|@''REPLACE_TDESTROY''@|$(REPLACE_TDESTROY)|g' \ |
| -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ |
| -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ |
| -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ |
| --- a/modules/tsearch |
| +++ b/modules/tsearch |
| @@ -11,7 +11,12 @@ search |
| configure.ac: |
| gl_FUNC_TSEARCH |
| gl_CONDITIONAL([GL_COND_OBJ_TSEARCH], |
| - [test $HAVE_TSEARCH = 0 || test $HAVE_TWALK = 0 || test $REPLACE_TSEARCH = 1 || test $REPLACE_TWALK = 1]) |
| + [test $HAVE_TSEARCH = 0 || |
| + test $HAVE_TWALK = 0 || |
| + test $HAVE_TDESTROY = 0 || |
| + test $REPLACE_TSEARCH = 1 || |
| + test $REPLACE_TWALK = 1 || |
| + test $REPLACE_TDESTROY = 1]) |
| AM_COND_IF([GL_COND_OBJ_TSEARCH], [ |
| gl_PREREQ_TSEARCH |
| ]) |