portability: check for qsort_r which does not match POSIX-next definition
FreeBSD (and also Darwin) introduced its own qsort_r, which has different semantics than the one slated for inclusion in POSIX. Add a portability thunk to deal with translating between implementations. [TT: minor stylistic fixes]cute-signatures
parent
191e2d412d
commit
44994a46d4
|
@ -21,6 +21,20 @@ foreach f : check_functions
|
||||||
endforeach
|
endforeach
|
||||||
|
|
||||||
|
|
||||||
|
# Check for wrong (non-POSIX) qsort_r prototype
|
||||||
|
qsort_r_test = '''
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <stdlib.h>
|
||||||
|
_Static_assert(_Generic((qsort_r),
|
||||||
|
void (*)(void *, size_t, size_t, void *,
|
||||||
|
int (*)(void *, const void *, const void *)) : 1, default: 0),
|
||||||
|
"Bad prototype not matched");
|
||||||
|
'''
|
||||||
|
if cc.compiles(qsort_r_test, name: 'Test qsort_r non-POSIX prototype')
|
||||||
|
add_project_arguments('-DHAVE_BROKEN_QSORT_R', language: 'c')
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
if libportability_src.length() > 0
|
if libportability_src.length() > 0
|
||||||
libportability = static_library(
|
libportability = static_library(
|
||||||
'portability',
|
'portability',
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#pragma once
|
||||||
#include_next <stdlib.h>
|
#include_next <stdlib.h>
|
||||||
|
|
||||||
#ifdef NEED_QSORT_R
|
#ifdef NEED_QSORT_R
|
||||||
|
@ -5,3 +6,28 @@ void qsort_r(void *base, size_t nmemb, size_t size,
|
||||||
int (*compar)(const void *, const void *, void *),
|
int (*compar)(const void *, const void *, void *),
|
||||||
void *arg);
|
void *arg);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_BROKEN_QSORT_R
|
||||||
|
struct __portable_qsort_r_compat_arg {
|
||||||
|
int (*compar)(const void *, const void *, void *);
|
||||||
|
void *arg;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline int __portable_qsort_r_compar_compat(void *arg, const void *a, const void *b)
|
||||||
|
{
|
||||||
|
struct __portable_qsort_r_compat_arg *compat_arg = arg;
|
||||||
|
return compat_arg->compar(a, b, compat_arg->arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void __portable_qsort_r(void *base, size_t nmemb, size_t size,
|
||||||
|
int (*compar)(const void *, const void *, void *),
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
struct __portable_qsort_r_compat_arg compat_arg = {
|
||||||
|
.compar = compar,
|
||||||
|
.arg = arg,
|
||||||
|
};
|
||||||
|
qsort_r(base, nmemb, size, &compat_arg, __portable_qsort_r_compar_compat);
|
||||||
|
}
|
||||||
|
#define qsort_r(...) __portable_qsort_r(__VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue