[PATCH] qsort_r

Yaakov Selkowitz yselkowi@redhat.com
Fri Dec 5 01:14:00 GMT 2014


Patch attached.

-- 
Yaakov Selkowitz
Associate Software Engineer, ARM
Red Hat, Inc.
-------------- next part --------------
2014-12-04  Yaakov Selkowitz  <yselkowi@...>

	* libc/include/stdlib.h (__bsd_qsort_r): Declare.
	(qsort_r): Declare.
	* libc/search/Makefile.am (ELIX_2_SOURCES): Rename from ELIX_SOURCES.
	(ELIX_4_SOURCES): Define.  Add bsd_qsort_r.c and qsort_r.c.
	(libsearch_la_SOURCES): Adapt accordingly.
	(lib_a_SOURCES): Adapt accordingly.
	(CHEWOUT_FILES): Add qsort_r.def.
	* libc/search/Makefile.in: Regenerate.
	* libc/search/bsd_qsort_r.c: New file.
	* libc/search/qsort.c: Update from FreeBSD HEAD. Adapt for
	both BSD and GNU qsort_r flavors.
	* libc/search/qsort_r.c: New file.

Index: libc/include/stdlib.h
===================================================================
RCS file: /cvs/src/src/newlib/libc/include/stdlib.h,v
retrieving revision 1.52
diff -u -p -r1.52 stdlib.h
--- libc/include/stdlib.h	10 Oct 2014 14:43:19 -0000	1.52
+++ libc/include/stdlib.h	5 Dec 2014 00:53:32 -0000
@@ -248,6 +248,22 @@ int	_EXFUN(_system_r,(struct _reent *, c
 
 _VOID	_EXFUN(__eprintf,(const char *, const char *, unsigned int, const char *));
 
+/* There are two common qsort_r variants.  If you request
+   _BSD_SOURCE, you get the BSD version; otherwise you get the GNU
+   version.  We want that #undef qsort_r will still let you
+   invoke the underlying function, but that requires gcc support. */
+#ifdef _BSD_SOURCE
+# ifdef __GNUC__
+_VOID	_EXFUN(qsort_r,(_PTR __base, size_t __nmemb, size_t __size, _PTR __thunk, int (*_compar)(_PTR, const _PTR, const _PTR)))
+             __asm__ (__ASMNAME ("__bsd_qsort_r"));
+# else
+_VOID	_EXFUN(__bsd_qsort_r,(_PTR __base, size_t __nmemb, size_t __size, _PTR __thunk, int (*_compar)(_PTR, const _PTR, const _PTR)));
+#  define qsort_r __bsd_qsort_r
+# endif
+#elif __GNU_VISIBLE
+_VOID	_EXFUN(qsort_r,(_PTR __base, size_t __nmemb, size_t __size, int (*_compar)(const _PTR, const _PTR, _PTR), _PTR __thunk));
+#endif
+
 /* On platforms where long double equals double.  */
 #ifdef _HAVE_LONG_DOUBLE
 #if !defined(__STRICT_ANSI__) || \
Index: libc/search/Makefile.am
===================================================================
RCS file: /cvs/src/src/newlib/libc/search/Makefile.am,v
retrieving revision 1.8
diff -u -p -r1.8 Makefile.am
--- libc/search/Makefile.am	29 Jan 2010 23:04:21 -0000	1.8
+++ libc/search/Makefile.am	5 Dec 2014 00:53:33 -0000
@@ -14,9 +14,9 @@ GENERAL_SOURCES = \
 
 ## Following are EL/IX level 2 interfaces
 if ELIX_LEVEL_1
-ELIX_SOURCES =
+ELIX_2_SOURCES =
 else
-ELIX_SOURCES = \
+ELIX_2_SOURCES = \
 	hash.c \
 	hash_bigkey.c \
 	hash_buf.c \
@@ -32,15 +32,32 @@ ELIX_SOURCES = \
 	twalk.c
 endif
 
+## Following are EL/IX level 4 interfaces
+if ELIX_LEVEL_1
+ELIX_4_SOURCES =
+else
+if ELIX_LEVEL_2
+ELIX_4_SOURCES =
+else
+if ELIX_LEVEL_3
+ELIX_4_SOURCES =
+else
+ELIX_4_SOURCES = \
+	bsd_qsort_r.c \
+	qsort_r.c
+endif !ELIX_LEVEL_3
+endif !ELIX_LEVEL_2
+endif !ELIX_LEVEL_1
+
 libsearch_la_LDFLAGS = -Xcompiler -nostdlib
 
 if USE_LIBTOOL
 noinst_LTLIBRARIES = libsearch.la
-libsearch_la_SOURCES = $(GENERAL_SOURCES) $(ELIX_SOURCES)
+libsearch_la_SOURCES = $(GENERAL_SOURCES) $(ELIX_2_SOURCES) $(ELIX_4_SOURCES)
 noinst_DATA = objectlist.awk.in
 else
 noinst_LIBRARIES = lib.a
-lib_a_SOURCES = $(GENERAL_SOURCES) $(ELIX_SOURCES)
+lib_a_SOURCES = $(GENERAL_SOURCES) $(ELIX_2_SOURCES) $(ELIX_4_SOURCES)
 lib_a_CFLAGS = $(AM_CFLAGS)
 noinst_DATA =
 endif # USE_LIBTOOL
@@ -49,7 +66,8 @@ SUFFIXES = .def
 
 CHEWOUT_FILES = \
 	bsearch.def \
-	qsort.def
+	qsort.def \
+	qsort_r.def
 
 CHEW = ../../doc/makedoc -f $(srcdir)/../../doc/doc.str
 
Index: libc/search/Makefile.in
===================================================================
RCS file: /cvs/src/src/newlib/libc/search/Makefile.in,v
retrieving revision 1.26
diff -u -p -r1.26 Makefile.in
--- libc/search/Makefile.in	20 Dec 2012 21:10:06 -0000	1.26
+++ libc/search/Makefile.in	5 Dec 2014 00:53:33 -0000
@@ -86,18 +86,22 @@ am__objects_1 = lib_a-bsearch.$(OBJEXT) 
 @ELIX_LEVEL_1_FALSE@	lib_a-tfind.$(OBJEXT) \
 @ELIX_LEVEL_1_FALSE@	lib_a-tsearch.$(OBJEXT) \
 @ELIX_LEVEL_1_FALSE@	lib_a-twalk.$(OBJEXT)
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@am__objects_3 = lib_a-bsd_qsort_r.$(OBJEXT) \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	lib_a-qsort_r.$(OBJEXT)
 @USE_LIBTOOL_FALSE@am_lib_a_OBJECTS = $(am__objects_1) \
-@USE_LIBTOOL_FALSE@	$(am__objects_2)
+@USE_LIBTOOL_FALSE@	$(am__objects_2) $(am__objects_3)
 lib_a_OBJECTS = $(am_lib_a_OBJECTS)
 LTLIBRARIES = $(noinst_LTLIBRARIES)
 libsearch_la_LIBADD =
-am__objects_3 = bsearch.lo qsort.lo
-@ELIX_LEVEL_1_FALSE@am__objects_4 = hash.lo hash_bigkey.lo hash_buf.lo \
+am__objects_4 = bsearch.lo qsort.lo
+@ELIX_LEVEL_1_FALSE@am__objects_5 = hash.lo hash_bigkey.lo hash_buf.lo \
 @ELIX_LEVEL_1_FALSE@	hash_func.lo hash_log2.lo hash_page.lo \
 @ELIX_LEVEL_1_FALSE@	hcreate.lo hcreate_r.lo tdelete.lo \
 @ELIX_LEVEL_1_FALSE@	tdestroy.lo tfind.lo tsearch.lo twalk.lo
-@USE_LIBTOOL_TRUE@am_libsearch_la_OBJECTS = $(am__objects_3) \
-@USE_LIBTOOL_TRUE@	$(am__objects_4)
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@am__objects_6 = bsd_qsort_r.lo \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	qsort_r.lo
+@USE_LIBTOOL_TRUE@am_libsearch_la_OBJECTS = $(am__objects_4) \
+@USE_LIBTOOL_TRUE@	$(am__objects_5) $(am__objects_6)
 libsearch_la_OBJECTS = $(am_libsearch_la_OBJECTS)
 libsearch_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
@@ -278,7 +282,7 @@ GENERAL_SOURCES = \
 	page.h \
 	qsort.c
 
-@ELIX_LEVEL_1_FALSE@ELIX_SOURCES = \
+@ELIX_LEVEL_1_FALSE@ELIX_2_SOURCES = \
 @ELIX_LEVEL_1_FALSE@	hash.c \
 @ELIX_LEVEL_1_FALSE@	hash_bigkey.c \
 @ELIX_LEVEL_1_FALSE@	hash_buf.c \
@@ -293,19 +297,27 @@ GENERAL_SOURCES = \
 @ELIX_LEVEL_1_FALSE@	tsearch.c \
 @ELIX_LEVEL_1_FALSE@	twalk.c
 
-@ELIX_LEVEL_1_TRUE@ELIX_SOURCES = 
+@ELIX_LEVEL_1_TRUE@ELIX_2_SOURCES = 
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@ELIX_4_SOURCES = \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	bsd_qsort_r.c \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	qsort_r.c
+
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_TRUE@ELIX_4_SOURCES = 
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_TRUE@ELIX_4_SOURCES = 
+@ELIX_LEVEL_1_TRUE@ELIX_4_SOURCES = 
 libsearch_la_LDFLAGS = -Xcompiler -nostdlib
 @USE_LIBTOOL_TRUE@noinst_LTLIBRARIES = libsearch.la
-@USE_LIBTOOL_TRUE@libsearch_la_SOURCES = $(GENERAL_SOURCES) $(ELIX_SOURCES)
+@USE_LIBTOOL_TRUE@libsearch_la_SOURCES = $(GENERAL_SOURCES) $(ELIX_2_SOURCES) $(ELIX_4_SOURCES)
 @USE_LIBTOOL_FALSE@noinst_DATA = 
 @USE_LIBTOOL_TRUE@noinst_DATA = objectlist.awk.in
 @USE_LIBTOOL_FALSE@noinst_LIBRARIES = lib.a
-@USE_LIBTOOL_FALSE@lib_a_SOURCES = $(GENERAL_SOURCES) $(ELIX_SOURCES)
+@USE_LIBTOOL_FALSE@lib_a_SOURCES = $(GENERAL_SOURCES) $(ELIX_2_SOURCES) $(ELIX_4_SOURCES)
 @USE_LIBTOOL_FALSE@lib_a_CFLAGS = $(AM_CFLAGS)
 SUFFIXES = .def
 CHEWOUT_FILES = \
 	bsearch.def \
-	qsort.def
+	qsort.def \
+	qsort_r.def
 
 CHEW = ../../doc/makedoc -f $(srcdir)/../../doc/doc.str
 TARGETDOC = ../tmp.texi
@@ -469,6 +481,18 @@ lib_a-twalk.o: twalk.c
 lib_a-twalk.obj: twalk.c
 	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-twalk.obj `if test -f 'twalk.c'; then $(CYGPATH_W) 'twalk.c'; else $(CYGPATH_W) '$(srcdir)/twalk.c'; fi`
 
+lib_a-bsd_qsort_r.o: bsd_qsort_r.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-bsd_qsort_r.o `test -f 'bsd_qsort_r.c' || echo '$(srcdir)/'`bsd_qsort_r.c
+
+lib_a-bsd_qsort_r.obj: bsd_qsort_r.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-bsd_qsort_r.obj `if test -f 'bsd_qsort_r.c'; then $(CYGPATH_W) 'bsd_qsort_r.c'; else $(CYGPATH_W) '$(srcdir)/bsd_qsort_r.c'; fi`
+
+lib_a-qsort_r.o: qsort_r.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-qsort_r.o `test -f 'qsort_r.c' || echo '$(srcdir)/'`qsort_r.c
+
+lib_a-qsort_r.obj: qsort_r.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-qsort_r.obj `if test -f 'qsort_r.c'; then $(CYGPATH_W) 'qsort_r.c'; else $(CYGPATH_W) '$(srcdir)/qsort_r.c'; fi`
+
 mostlyclean-libtool:
 	-rm -f *.lo
 
Index: libc/search/bsd_qsort_r.c
===================================================================
RCS file: libc/search/bsd_qsort_r.c
diff -N libc/search/bsd_qsort_r.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libc/search/bsd_qsort_r.c	5 Dec 2014 00:53:33 -0000
@@ -0,0 +1,2 @@
+#define I_AM_BSD_QSORT_R
+#include "qsort.c"
Index: libc/search/qsort.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/search/qsort.c,v
retrieving revision 1.1
diff -u -p -r1.1 qsort.c
--- libc/search/qsort.c	20 Jun 2002 19:51:31 -0000	1.1
+++ libc/search/qsort.c	5 Dec 2014 00:53:33 -0000
@@ -53,11 +53,7 @@ PORTABILITY
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
@@ -75,13 +71,21 @@ PORTABILITY
  */
 
 #include <_ansi.h>
+#include <sys/cdefs.h>
 #include <stdlib.h>
 
 #ifndef __GNUC__
 #define inline
 #endif
 
-static inline char	*med3 _PARAMS((char *, char *, char *, int (*)()));
+#if defined(I_AM_BSD_QSORT_R)
+typedef int		 cmp_t(void *, const void *, const void *);
+#elif defined(I_AM_QSORT_R)
+typedef int		 cmp_t(const void *, const void *, void *);
+#else
+typedef int		 cmp_t(const void *, const void *);
+#endif
+static inline char	*med3 _PARAMS((char *, char *, char *, cmp_t *, void *));
 static inline void	 swapfunc _PARAMS((char *, char *, int, int));
 
 #define min(a, b)	(a) < (b) ? a : b
@@ -91,10 +95,10 @@ static inline void	 swapfunc _PARAMS((ch
  */
 #define swapcode(TYPE, parmi, parmj, n) { 		\
 	long i = (n) / sizeof (TYPE); 			\
-	register TYPE *pi = (TYPE *) (parmi); 		\
-	register TYPE *pj = (TYPE *) (parmj); 		\
+	TYPE *pi = (TYPE *) (parmi); 		\
+	TYPE *pj = (TYPE *) (parmj); 		\
 	do { 						\
-		register TYPE	t = *pi;		\
+		TYPE	t = *pi;		\
 		*pi++ = *pj;				\
 		*pj++ = t;				\
         } while (--i > 0);				\
@@ -110,7 +114,7 @@ _DEFUN(swapfunc, (a, b, n, swaptype),
 	int n _AND
 	int swaptype)
 {
-	if(swaptype <= 1) 
+	if(swaptype <= 1)
 		swapcode(long, a, b, n)
 	else
 		swapcode(char, a, b, n)
@@ -126,33 +130,67 @@ _DEFUN(swapfunc, (a, b, n, swaptype),
 
 #define vecswap(a, b, n) 	if ((n) > 0) swapfunc(a, b, n, swaptype)
 
+#if defined(I_AM_BSD_QSORT_R)
+#define	CMP(t, x, y) (cmp((t), (x), (y)))
+#elif defined(I_AM_QSORT_R)
+#define	CMP(t, x, y) (cmp((x), (y), (t)))
+#else
+#define	CMP(t, x, y) (cmp((x), (y)))
+#endif
+
 static inline char *
-_DEFUN(med3, (a, b, c, cmp),
+_DEFUN(med3, (a, b, c, cmp, thunk),
 	char *a _AND
 	char *b _AND
 	char *c _AND
-	int (*cmp)())
+	cmp_t *cmp _AND
+	void *thunk
+#if !defined(I_AM_BSD_QSORT_R) && !defined(I_AM_QSORT_R)
+__unused
+#endif
+)
 {
-	return cmp(a, b) < 0 ?
-	       (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))
-              :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ));
+	return CMP(thunk, a, b) < 0 ?
+	       (CMP(thunk, b, c) < 0 ? b : (CMP(thunk, a, c) < 0 ? c : a ))
+              :(CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c ));
 }
 
+#if defined(I_AM_BSD_QSORT_R)
+void
+_DEFUN(__bsd_qsort_r, (a, n, es, thunk, cmp),
+	void *a _AND
+	size_t n _AND
+	size_t es _AND
+	void *thunk _AND
+	cmp_t *cmp)
+#elif defined(I_AM_QSORT_R)
+void
+_DEFUN(qsort_r, (a, n, es, cmp, thunk),
+	void *a _AND
+	size_t n _AND
+	size_t es _AND
+	cmp_t *cmp _AND
+	void *thunk)
+#else
+#define thunk NULL
 void
 _DEFUN(qsort, (a, n, es, cmp),
 	void *a _AND
 	size_t n _AND
 	size_t es _AND
-	int (*cmp)())
+	cmp_t *cmp)
+#endif
 {
 	char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
-	int d, r, swaptype, swap_cnt;
+	size_t d, r;
+	int cmp_result;
+	int swaptype, swap_cnt;
 
 loop:	SWAPINIT(a, es);
 	swap_cnt = 0;
 	if (n < 7) {
 		for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
-			for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
+			for (pl = pm; pl > (char *) a && CMP(thunk, pl - es, pl) > 0;
 			     pl -= es)
 				swap(pl, pl - es);
 		return;
@@ -163,27 +201,27 @@ loop:	SWAPINIT(a, es);
 		pn = (char *) a + (n - 1) * es;
 		if (n > 40) {
 			d = (n / 8) * es;
-			pl = med3(pl, pl + d, pl + 2 * d, cmp);
-			pm = med3(pm - d, pm, pm + d, cmp);
-			pn = med3(pn - 2 * d, pn - d, pn, cmp);
+			pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk);
+			pm = med3(pm - d, pm, pm + d, cmp, thunk);
+			pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk);
 		}
-		pm = med3(pl, pm, pn, cmp);
+		pm = med3(pl, pm, pn, cmp, thunk);
 	}
 	swap(a, pm);
 	pa = pb = (char *) a + es;
 
 	pc = pd = (char *) a + (n - 1) * es;
 	for (;;) {
-		while (pb <= pc && (r = cmp(pb, a)) <= 0) {
-			if (r == 0) {
+		while (pb <= pc && (cmp_result = CMP(thunk, pb, a)) <= 0) {
+			if (cmp_result == 0) {
 				swap_cnt = 1;
 				swap(pa, pb);
 				pa += es;
 			}
 			pb += es;
 		}
-		while (pb <= pc && (r = cmp(pc, a)) >= 0) {
-			if (r == 0) {
+		while (pb <= pc && (cmp_result = CMP(thunk, pc, a)) >= 0) {
+			if (cmp_result == 0) {
 				swap_cnt = 1;
 				swap(pc, pd);
 				pd -= es;
@@ -199,7 +237,7 @@ loop:	SWAPINIT(a, es);
 	}
 	if (swap_cnt == 0) {  /* Switch to insertion sort */
 		for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
-			for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; 
+			for (pl = pm; pl > (char *) a && CMP(thunk, pl - es, pl) > 0;
 			     pl -= es)
 				swap(pl, pl - es);
 		return;
@@ -211,8 +249,14 @@ loop:	SWAPINIT(a, es);
 	r = min(pd - pc, pn - pd - es);
 	vecswap(pb, pn - r, r);
 	if ((r = pb - pa) > es)
+#if defined(I_AM_BSD_QSORT_R)
+		__bsd_qsort_r(a, r / es, es, thunk, cmp);
+#elif defined(I_AM_QSORT_R)
+		qsort_r(a, r / es, es, cmp, thunk);
+#else
 		qsort(a, r / es, es, cmp);
-	if ((r = pd - pc) > es) { 
+#endif
+	if ((r = pd - pc) > es) {
 		/* Iterate rather than recurse to save stack space */
 		a = pn - r;
 		n = r / es;
Index: libc/search/qsort_r.c
===================================================================
RCS file: libc/search/qsort_r.c
diff -N libc/search/qsort_r.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libc/search/qsort_r.c	5 Dec 2014 00:53:33 -0000
@@ -0,0 +1,56 @@
+/*
+FUNCTION
+<<qsort_r>>---sort an array
+
+INDEX
+	qsort_r
+
+ANSI_SYNOPSIS
+	#define _BSD_SOURCE
+	#include <stdlib.h>
+	void qsort_r(void *<[base]>, size_t <[nmemb]>, size_t <[size]>,
+		     void *<[thunk]>,
+		     int (*<[compar]>)(void*, const void *, const void *));
+
+	#define _GNU_SOURCE
+	#include <stdlib.h>
+	void qsort_r(void *<[base]>, size_t <[nmemb]>, size_t <[size]>,
+		     int (*<[compar]>)(const void *, const void *, void *),
+		     void *<[thunk]>);
+
+TRAD_SYNOPSIS
+	#include <stdlib.h>
+	qsort_r(<[base]>, <[nmemb]>, <[size]>, <[compar]>, <[thumb]>)
+	char *<[base]>;
+	size_t <[nmemb]>;
+	size_t <[size]>;
+	int (*<[compar]>)();
+	char *<[thumb]>;
+
+DESCRIPTION
+<<qsort_r>> sorts an array (beginning at <[base]>) of <[nmemb]> objects.
+<[size]> describes the size of each element of the array.
+
+You must supply a pointer to a comparison function, using the argument
+shown as <[compar]>.  (This permits sorting objects of unknown
+properties.)  There are two forms of this function, in each the
+comparison function is defined to accept three arguments, but in a
+different order.  Two are pointers to an element of the array starting at
+<[base]>, and another being an arbitrary pointer <[thunk]>.  The
+result of <<(*<[compar]>)>> must be negative if the first argument is
+less than the second, zero if the two arguments match, and positive if
+the first argument is greater than the second (where ``less than'' and
+``greater than'' refer to whatever arbitrary ordering is appropriate).
+
+The array is sorted in place; that is, when <<qsort_r>> returns, the
+array elements beginning at <[base]> have been reordered.
+
+RETURNS
+<<qsort_r>> does not return a result.
+
+PORTABILITY
+<<qsort_r>>, in various forms, appears in both BSD and glibc.
+*/
+
+#define I_AM_QSORT_R
+#include "qsort.c"


More information about the Newlib mailing list