--- 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 @@ -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 - ]], [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 ]]) gl_CHECK_FUNCS_ANDROID([twalk], [[#include ]]) + gl_CHECK_FUNCS_ANDROID([tdestroy], [[#include ]]) 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 ])