aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorEd Schouten <ed@FreeBSD.org>2022-09-30 22:26:30 +0000
committerXin LI <delphij@FreeBSD.org>2022-09-30 22:26:30 +0000
commitaf3c78886fd8d4ca5eebdbe581a459a6f6d29d6a (patch)
tree9ff804d16ae1d811e013a58e71f8c824c2ff2488 /include
parent69d79ceb2c01931c129c5bafc300c33f3e106efd (diff)
Diffstat (limited to 'include')
-rw-r--r--include/stdlib.h38
1 files changed, 36 insertions, 2 deletions
diff --git a/include/stdlib.h b/include/stdlib.h
index bf1a612190ee..754e8f5f5fd4 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -311,8 +311,8 @@ int mergesort_b(void *, size_t, size_t, int (^)(const void *, const void *));
int mkostemp(char *, int);
int mkostemps(char *, int, int);
int mkostempsat(int, char *, int, int);
-void qsort_r(void *, size_t, size_t, void *,
- int (*)(void *, const void *, const void *));
+void qsort_r(void *, size_t, size_t,
+ int (*)(const void *, const void *, void *), void *);
int radixsort(const unsigned char **, int, const unsigned char *,
unsigned);
void *reallocarray(void *, size_t, size_t) __result_use_check
@@ -332,6 +332,40 @@ __int64_t
__uint64_t
strtouq(const char *, char **, int);
+/*
+ * In FreeBSD 14, the prototype of qsort_r() was modified to comply with
+ * POSIX. The standardized qsort_r()'s order of last two parameters was
+ * changed, and the comparator function is now taking thunk as its last
+ * parameter, and both are different from the ones expected by the historical
+ * FreeBSD qsort_r() interface.
+ *
+ * Apply a workaround where we explicitly link against the historical
+ * interface, qsort_r@FBSD_1.0, in case when qsort_r() is called with
+ * the last parameter with a function pointer that exactly matches the
+ * historical FreeBSD qsort_r() comparator signature, so applications
+ * written for the historical interface can continue to work without
+ * modification.
+ */
+#if defined(__generic) || defined(__cplusplus)
+void __qsort_r_compat(void *, size_t, size_t, void *,
+ int (*)(void *, const void *, const void *));
+__sym_compat(qsort_r, __qsort_r_compat, FBSD_1.0);
+#endif
+#if defined(__generic) && !defined(__cplusplus)
+#define qsort_r(base, nel, width, arg4, arg5) \
+ __generic(arg5, int (*)(void *, const void *, const void *), \
+ __qsort_r_compat, qsort_r)(base, nel, width, arg4, arg5)
+#elif defined(__cplusplus)
+__END_DECLS
+extern "C++" {
+static inline void qsort_r(void *base, size_t nmemb, size_t size,
+ void *thunk, int (*compar)(void *, const void *, const void *)) {
+ __qsort_r_compat(base, nmemb, size, thunk, compar);
+}
+}
+__BEGIN_DECLS
+#endif
+
extern char *suboptarg; /* getsubopt(3) external variable */
#endif /* __BSD_VISIBLE */