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
|
||||
|
||||
|
||||
# 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
|
||||
libportability = static_library(
|
||||
'portability',
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#pragma once
|
||||
#include_next <stdlib.h>
|
||||
|
||||
#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 *),
|
||||
void *arg);
|
||||
#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