b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame^] | 1 | --- a/lib/search.in.h |
| 2 | +++ b/lib/search.in.h |
| 3 | @@ -112,6 +112,11 @@ _GL_CXXALIASWARN (lsearch); |
| 4 | # define twalk rpl_twalk |
| 5 | # endif |
| 6 | # endif |
| 7 | +# if @REPLACE_TDESTROY@ |
| 8 | +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) |
| 9 | +# define tdestroy rpl_tdestroy |
| 10 | +# endif |
| 11 | +# endif |
| 12 | |
| 13 | /* See <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/search.h.html> |
| 14 | <https://pubs.opengroup.org/onlinepubs/9699919799/functions/tsearch.html> |
| 15 | @@ -137,6 +142,7 @@ extern "C" { |
| 16 | # if !GNULIB_defined_search_fn_types |
| 17 | typedef int (*_gl_search_compar_fn) (const void *, const void *); |
| 18 | typedef void (*_gl_search_action_fn) (const void *, VISIT, int); |
| 19 | +typedef void (*_gl_search_free_fn) (void *); |
| 20 | # define GNULIB_defined_search_fn_types 1 |
| 21 | # endif |
| 22 | # ifdef __cplusplus |
| 23 | @@ -252,9 +258,36 @@ _GL_CXXALIAS_SYS (twalk, void, |
| 24 | _GL_CXXALIASWARN (twalk); |
| 25 | # endif |
| 26 | |
| 27 | +/* Removes the whole tree pointed to by root, |
| 28 | + freeing all resources allocated by the tsearch() function. |
| 29 | + The FREE_NODE function is called: |
| 30 | + - For the data in each tree node. |
| 31 | + - Even when no such work is necessary, to a function doing nothing |
| 32 | + The arguments passed to FREE_NODE are: |
| 33 | + 1. The pointer to the data. */ |
| 34 | +# if @REPLACE_TDESTROY@ |
| 35 | +_GL_FUNCDECL_RPL (tdestroy, void, |
| 36 | + (void *vroot, _gl_search_free_fn freefct) |
| 37 | + _GL_ARG_NONNULL ((2))); |
| 38 | +_GL_CXXALIAS_RPL (tdestroy, void, |
| 39 | + (void *vroot, _gl_search_free_fn freefct)); |
| 40 | +# else |
| 41 | +# if !@HAVE_TDESTROY@ |
| 42 | +_GL_FUNCDECL_SYS (tdestroy, void, |
| 43 | + (void *vroot, _gl_search_free_fn freefct) |
| 44 | + _GL_ARG_NONNULL ((2))); |
| 45 | +# endif |
| 46 | +_GL_CXXALIAS_SYS (tdestroy, void, |
| 47 | + (void *vroot, _gl_search_free_fn freefct)); |
| 48 | +# endif |
| 49 | +# if __GLIBC__ >= 2 |
| 50 | +_GL_CXXALIASWARN (tdestroy); |
| 51 | +# endif |
| 52 | + |
| 53 | /* Flags used by tsearch.c. */ |
| 54 | # define GNULIB_defined_tsearch (@REPLACE_TSEARCH@ || !@HAVE_TSEARCH@) |
| 55 | # define GNULIB_defined_twalk (@REPLACE_TWALK@ || !@HAVE_TWALK@) |
| 56 | +# define GNULIB_defined_tdestroy (@REPLACE_TDESTROY@ || !@HAVE_TDESTROY@) |
| 57 | |
| 58 | #elif defined GNULIB_POSIXCHECK |
| 59 | # undef tsearch |
| 60 | @@ -277,6 +310,11 @@ _GL_WARN_ON_USE (tdelete, "tdelete is un |
| 61 | _GL_WARN_ON_USE (twalk, "twalk is unportable - " |
| 62 | "use gnulib module tsearch for portability"); |
| 63 | # endif |
| 64 | +# undef tdestroy |
| 65 | +# if HAVE_RAW_DECL_TDESTROY |
| 66 | +_GL_WARN_ON_USE (tdestroy, "tdestroy is unportable - " |
| 67 | + "use gnulib module tsearch for portability"); |
| 68 | +# endif |
| 69 | #endif |
| 70 | |
| 71 | |
| 72 | --- a/lib/tsearch.c |
| 73 | +++ b/lib/tsearch.c |
| 74 | @@ -98,12 +98,14 @@ |
| 75 | |
| 76 | typedef int (*__compar_fn_t) (const void *, const void *); |
| 77 | typedef void (*__action_fn_t) (const void *, VISIT, int); |
| 78 | +typedef void (*__free_fn_t) (void *); |
| 79 | |
| 80 | #ifndef weak_alias |
| 81 | # define __tsearch tsearch |
| 82 | # define __tfind tfind |
| 83 | # define __tdelete tdelete |
| 84 | # define __twalk twalk |
| 85 | +# define __tdestroy tdestroy |
| 86 | #endif |
| 87 | |
| 88 | #ifndef internal_function |
| 89 | @@ -656,7 +658,7 @@ weak_alias (__twalk, twalk) |
| 90 | #endif /* GNULIB_defined_twalk */ |
| 91 | |
| 92 | |
| 93 | -#ifdef _LIBC |
| 94 | +#if defined(_LIBC) || GNULIB_defined_tdestroy |
| 95 | |
| 96 | /* The standardized functions miss an important functionality: the |
| 97 | tree cannot be removed easily. We provide a function to do this. */ |
| 98 | @@ -683,6 +685,8 @@ __tdestroy (void *vroot, __free_fn_t fre |
| 99 | if (root != NULL) |
| 100 | tdestroy_recurse (root, freefct); |
| 101 | } |
| 102 | +#ifdef weak_alias |
| 103 | weak_alias (__tdestroy, tdestroy) |
| 104 | +#endif |
| 105 | |
| 106 | -#endif /* _LIBC */ |
| 107 | +#endif /* defined(_LIBC) || GNULIB_defined_tdestroy */ |
| 108 | --- a/m4/search_h.m4 |
| 109 | +++ b/m4/search_h.m4 |
| 110 | @@ -39,7 +39,7 @@ AC_DEFUN_ONCE([gl_SEARCH_H], |
| 111 | dnl Check for declarations of anything we want to poison if the |
| 112 | dnl corresponding gnulib module is not in use. |
| 113 | gl_WARN_ON_USE_PREPARE([[#include <search.h> |
| 114 | - ]], [tdelete tfind tsearch twalk]) |
| 115 | + ]], [tdelete tfind tsearch twalk tdestroy]) |
| 116 | |
| 117 | AC_REQUIRE([AC_C_RESTRICT]) |
| 118 | ]) |
| 119 | @@ -75,8 +75,10 @@ AC_DEFUN([gl_SEARCH_H_DEFAULTS], |
| 120 | gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MDA_LFIND], [1]) |
| 121 | gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MDA_LSEARCH], [1]) |
| 122 | dnl Assume proper GNU behavior unless another module says otherwise. |
| 123 | - HAVE_TSEARCH=1; AC_SUBST([HAVE_TSEARCH]) |
| 124 | - HAVE_TWALK=1; AC_SUBST([HAVE_TWALK]) |
| 125 | - REPLACE_TSEARCH=0; AC_SUBST([REPLACE_TSEARCH]) |
| 126 | - REPLACE_TWALK=0; AC_SUBST([REPLACE_TWALK]) |
| 127 | + HAVE_TSEARCH=1; AC_SUBST([HAVE_TSEARCH]) |
| 128 | + HAVE_TWALK=1; AC_SUBST([HAVE_TWALK]) |
| 129 | + HAVE_TDESTROY=1; AC_SUBST([HAVE_TDESTROY]) |
| 130 | + REPLACE_TSEARCH=0; AC_SUBST([REPLACE_TSEARCH]) |
| 131 | + REPLACE_TWALK=0; AC_SUBST([REPLACE_TWALK]) |
| 132 | + REPLACE_TDESTROY=0; AC_SUBST([REPLACE_TDESTROY]) |
| 133 | ]) |
| 134 | --- a/m4/tsearch.m4 |
| 135 | +++ b/m4/tsearch.m4 |
| 136 | @@ -9,6 +9,7 @@ AC_DEFUN([gl_FUNC_TSEARCH], |
| 137 | AC_REQUIRE([gl_SEARCH_H_DEFAULTS]) |
| 138 | gl_CHECK_FUNCS_ANDROID([tsearch], [[#include <search.h>]]) |
| 139 | gl_CHECK_FUNCS_ANDROID([twalk], [[#include <search.h>]]) |
| 140 | + gl_CHECK_FUNCS_ANDROID([tdestroy], [[#include <search.h>]]) |
| 141 | if test $ac_cv_func_tsearch = yes; then |
| 142 | dnl On OpenBSD 4.0, the return value of tdelete() is incorrect. |
| 143 | AC_REQUIRE([AC_PROG_CC]) |
| 144 | @@ -50,6 +51,7 @@ main () |
| 145 | *no) |
| 146 | REPLACE_TSEARCH=1 |
| 147 | REPLACE_TWALK=1 |
| 148 | + REPLACE_TDESTROY=1 |
| 149 | ;; |
| 150 | esac |
| 151 | else |
| 152 | @@ -64,6 +66,12 @@ main () |
| 153 | future*) REPLACE_TWALK=1 ;; |
| 154 | esac |
| 155 | fi |
| 156 | + if test $ac_cv_func_tdestroy != yes; then |
| 157 | + HAVE_TDESTROY=0 |
| 158 | + case "$gl_cv_onwards_func_tdestroy" in |
| 159 | + future*) REPLACE_TDESTROY=1 ;; |
| 160 | + esac |
| 161 | + fi |
| 162 | ]) |
| 163 | |
| 164 | # Prerequisites of lib/tsearch.c. |
| 165 | --- a/modules/search |
| 166 | +++ b/modules/search |
| 167 | @@ -37,8 +37,10 @@ search.h: search.in.h $(top_builddir)/co |
| 168 | -e 's/@''GNULIB_MDA_LSEARCH''@/$(GNULIB_MDA_LSEARCH)/g' \ |
| 169 | -e 's|@''HAVE_TSEARCH''@|$(HAVE_TSEARCH)|g' \ |
| 170 | -e 's|@''HAVE_TWALK''@|$(HAVE_TWALK)|g' \ |
| 171 | + -e 's|@''HAVE_TDESTROY''@|$(HAVE_TDESTROY)|g' \ |
| 172 | -e 's|@''REPLACE_TSEARCH''@|$(REPLACE_TSEARCH)|g' \ |
| 173 | -e 's|@''REPLACE_TWALK''@|$(REPLACE_TWALK)|g' \ |
| 174 | + -e 's|@''REPLACE_TDESTROY''@|$(REPLACE_TDESTROY)|g' \ |
| 175 | -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ |
| 176 | -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ |
| 177 | -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ |
| 178 | --- a/modules/tsearch |
| 179 | +++ b/modules/tsearch |
| 180 | @@ -11,7 +11,12 @@ search |
| 181 | configure.ac: |
| 182 | gl_FUNC_TSEARCH |
| 183 | gl_CONDITIONAL([GL_COND_OBJ_TSEARCH], |
| 184 | - [test $HAVE_TSEARCH = 0 || test $HAVE_TWALK = 0 || test $REPLACE_TSEARCH = 1 || test $REPLACE_TWALK = 1]) |
| 185 | + [test $HAVE_TSEARCH = 0 || |
| 186 | + test $HAVE_TWALK = 0 || |
| 187 | + test $HAVE_TDESTROY = 0 || |
| 188 | + test $REPLACE_TSEARCH = 1 || |
| 189 | + test $REPLACE_TWALK = 1 || |
| 190 | + test $REPLACE_TDESTROY = 1]) |
| 191 | AM_COND_IF([GL_COND_OBJ_TSEARCH], [ |
| 192 | gl_PREREQ_TSEARCH |
| 193 | ]) |