diff --git a/ChangeLog b/ChangeLog index 24c5adf667..b812349c50 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +Sat Feb 8 21:44:07 2014 Masaki Matsushita + + * configure.in: check qsort_r(3) and whether it is GNU version. + BSD version has different prototype. + + * util.h: use qsort_r() as ruby_qsort() if it is GNU version. + + * util.c: define ruby_qsort() if needed. + Sat Feb 8 16:34:36 2014 Tanaka Akira * lib/resolv.rb (Resolv::DNS::Message::MessageDecoder#get_labels): diff --git a/configure.in b/configure.in index 84aec14725..4da41df606 100644 --- a/configure.in +++ b/configure.in @@ -1920,6 +1920,7 @@ AC_CHECK_FUNCS(posix_fadvise) AC_CHECK_FUNCS(posix_memalign) AC_CHECK_FUNCS(ppoll) AC_CHECK_FUNCS(pread) +AC_CHECK_FUNCS(qsort_r) AC_CHECK_FUNCS(readlink) AC_CHECK_FUNCS(round) AC_CHECK_FUNCS(seekdir) @@ -1980,6 +1981,39 @@ RUBY_CHECK_BUILTIN_FUNC(__builtin_clzll, [__builtin_clzll(0)]) RUBY_CHECK_BUILTIN_FUNC(__builtin_choose_expr, [__builtin_choose_expr(0, 0, 0)]) RUBY_CHECK_BUILTIN_FUNC(__builtin_types_compatible_p, [__builtin_types_compatible_p(int, int)]) +if test "$ac_cv_func_qsort_r" != no; then + AC_CACHE_CHECK(that qsort_r is GNU version, rb_cv_gnu_qsort_r, + [AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include + +int unsorted[] = { 4, 3, 2, 1 }; +int sorted[] = { 1, 2, 3, 4 }; + +int +compar(const void *a, const void *b, void *arg) +{ + if (*(int *)arg != 42) exit(1); + return *(int *)a - *(int *)b; +} + +int +main(void) +{ + int arg = 42; + qsort_r(unsorted, 4, sizeof(int), compar, &arg); + if (memcmp(sorted, unsorted, 4) != 0) return 1; + return 0; +} + ]])], + [rb_cv_gnu_qsort_r=yes], + [rb_cv_gnu_qsort_r=no]) + ]) + if test "$rb_cv_gnu_qsort_r" != no; then + AC_DEFINE(HAVE_GNU_QSORT_R, 1) + fi +fi + # Some platform need -lrt for clock_gettime, but the other don't. if test x"$ac_cv_func_clock_gettime" != xyes; then # glibc 2.17 moves clock_* functions from librt to the main C library. diff --git a/include/ruby/util.h b/include/ruby/util.h index 8443af74d9..74cdd0ffd1 100644 --- a/include/ruby/util.h +++ b/include/ruby/util.h @@ -55,8 +55,12 @@ unsigned long ruby_scan_oct(const char *, size_t, size_t *); #define scan_hex(s,l,e) ((int)ruby_scan_hex((s),(l),(e))) unsigned long ruby_scan_hex(const char *, size_t, size_t *); +#ifdef HAVE_GNU_QSORT_R +# define ruby_qsort qsort_r +#else void ruby_qsort(void *, const size_t, const size_t, int (*)(const void *, const void *, void *), void *); +#endif void ruby_setenv(const char *, const char *); void ruby_unsetenv(const char *); diff --git a/util.c b/util.c index b0f9030c42..b999aff05c 100644 --- a/util.c +++ b/util.c @@ -186,6 +186,7 @@ ruby_strtoul(const char *str, char **endptr, int base) #endif +#ifndef HAVE_GNU_QSORT_R /* mm.c */ #define mmtype long @@ -452,6 +453,7 @@ ruby_qsort(void* base, const size_t nel, const size_t size, cmpfunc_t *cmp, void else goto nxt; /* need not to sort both sides */ } } +#endif /* HAVE_GNU_QSORT_R */ char * ruby_strdup(const char *str)