Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 9 Sep 2002 13:36:13 -0400 (EDT)
From:      Garrett Wollman <wollman@lcs.mit.edu>
To:        standards@FreeBSD.org
Subject:   CFR: Jumbo stdlib.h/qsort_r patch
Message-ID:  <200209091736.g89HaDnh066298@khavrinen.lcs.mit.edu>

next in thread | raw e-mail | index | archive | help
This patch includes several changes which have gotten somewhat tangled
up with one another.  To wit:

- The compiler now signals whether it is prepared to compile `long
long'.  I'll dump this part in favor of obrien's patch.  This patchset
also includes kan's fixes to the compiler itself, which I found
necessary in order to build the world with the rest of these changes.

- The prototype of fts(3)'s user-supplied file comparison function is
updated to include an appropriate level of const poisoning.  Callers
of fts_open() are updated to match.

- The new function qsort_r is introduced, which passes a `thunk'
argument to the comparison function so that it can access private data
reentrantly.

- fts_sort() is updated to use qsort_r() to do the sorting, and call
the user comparison function through a trampoline function which has
the correct type signature for use with qsort_r().  This eliminates a
warning which has bothered me for years.

- An implementation of the C99 function _Exit() is added.  Right now,
it just calls _exit(), but I'm holding off on making _Exit() just an
outright alias for _exit().

- stdlib.h is updated with the new namespace macros.  Commented-out
declarations are added of the functions from 1003.1-2001 which we do
not yet implement.  Some misplaced declarations are duplicated here
from <unistd.h> for XSI.

-GAWollman


Index: bin/cp/cp.c
===================================================================
RCS file: /home/ncvs/src/bin/cp/cp.c,v
retrieving revision 1.40
diff -u -r1.40 cp.c
--- bin/cp/cp.c	23 Jul 2002 00:42:56 -0000	1.40
+++ bin/cp/cp.c	8 Sep 2002 05:18:41 -0000
@@ -92,7 +92,7 @@
 enum op { FILE_TO_FILE, FILE_TO_DIR, DIR_TO_DNE };
 
 static int copy(char *[], enum op, int);
-static int mastercmp(const FTSENT **, const FTSENT **);
+static int mastercmp(const FTSENT * const *, const FTSENT * const *);
 
 int
 main(int argc, char *argv[])
@@ -484,7 +484,7 @@
  *	files first reduces seeking.
  */
 int
-mastercmp(const FTSENT **a, const FTSENT **b)
+mastercmp(const FTSENT * const *a, const FTSENT * const *b)
 {
 	int a_info, b_info;
 
Index: bin/ls/ls.c
===================================================================
RCS file: /home/ncvs/src/bin/ls/ls.c,v
retrieving revision 1.65
diff -u -r1.65 ls.c
--- bin/ls/ls.c	25 Aug 2002 13:01:45 -0000	1.65
+++ bin/ls/ls.c	9 Sep 2002 03:14:02 -0000
@@ -82,7 +82,7 @@
 
 static void	 display(FTSENT *, FTSENT *);
 static u_quad_t	 makenines(u_long);
-static int	 mastercmp(const FTSENT **, const FTSENT **);
+static int	 mastercmp(const FTSENT * const *, const FTSENT * const *);
 static void	 traverse(int, char **, int);
 
 static void (*printfcn)(DISPLAY *);
@@ -759,7 +759,7 @@
  * All other levels use the sort function.  Error entries remain unsorted.
  */
 static int
-mastercmp(const FTSENT **a, const FTSENT **b)
+mastercmp(const FTSENT * const *a, const FTSENT * const *b)
 {
 	int a_info, b_info;
 
Index: contrib/gcc/calls.c
===================================================================
RCS file: /home/ncvs/src/contrib/gcc/calls.c,v
retrieving revision 1.1.1.8
diff -u -r1.1.1.8 calls.c
--- contrib/gcc/calls.c	13 May 2002 03:35:49 -0000	1.1.1.8
+++ contrib/gcc/calls.c	8 Sep 2002 03:48:41 -0000
@@ -4491,7 +4491,7 @@
 	     emit_push_insn for BLKmode is careful to avoid it.  */
 	  excess = (arg->size.constant - int_size_in_bytes (TREE_TYPE (pval))
 		    + partial * UNITS_PER_WORD);
-	  size_rtx = expr_size (pval);
+	  size_rtx = GEN_INT (int_size_in_bytes (TREE_TYPE (pval)));
 	}
 
       if ((flags & ECF_SIBCALL) && GET_CODE (arg->value) == MEM)
Index: contrib/gcc/loop.c
===================================================================
RCS file: /home/ncvs/src/contrib/gcc/loop.c,v
retrieving revision 1.1.1.13
diff -u -r1.1.1.13 loop.c
--- contrib/gcc/loop.c	1 Sep 2002 20:37:48 -0000	1.1.1.13
+++ contrib/gcc/loop.c	8 Sep 2002 03:48:41 -0000
@@ -9264,7 +9264,7 @@
 	{
 	case LE:
 	  if ((unsigned HOST_WIDE_INT) const_val != max_val >> 1)
-	    code = LT, op1 = GEN_INT (const_val + 1);
+	    code = LT, op1 = gen_int_mode (const_val + 1, GET_MODE (op0));
 	  break;
 
 	/* When cross-compiling, const_val might be sign-extended from
@@ -9273,17 +9273,17 @@
 	  if ((HOST_WIDE_INT) (const_val & max_val)
 	      != (((HOST_WIDE_INT) 1
 		   << (GET_MODE_BITSIZE (GET_MODE (op0)) - 1))))
-	    code = GT, op1 = GEN_INT (const_val - 1);
+	    code = GT, op1 = gen_int_mode (const_val - 1, GET_MODE (op0));
 	  break;
 
 	case LEU:
 	  if (uconst_val < max_val)
-	    code = LTU, op1 = GEN_INT (uconst_val + 1);
+	    code = LTU, op1 = gen_int_mode (uconst_val + 1, GET_MODE (op0));
 	  break;
 
 	case GEU:
 	  if (uconst_val != 0)
-	    code = GTU, op1 = GEN_INT (uconst_val - 1);
+	    code = GTU, op1 = gen_int_mode (uconst_val - 1, GET_MODE (op0));
 	  break;
 
 	default:
Index: contrib/gcc/config/freebsd-spec.h
===================================================================
RCS file: /home/ncvs/src/contrib/gcc/config/freebsd-spec.h,v
retrieving revision 1.2
diff -u -r1.2 freebsd-spec.h
--- contrib/gcc/config/freebsd-spec.h	10 May 2002 19:05:07 -0000	1.2
+++ contrib/gcc/config/freebsd-spec.h	8 Sep 2002 18:34:29 -0000
@@ -85,12 +85,13 @@
    the final CPP_PREDEFINES value.  */
 
 #define FBSD_CPP_PREDEFINES \
-  "-D__FreeBSD__=5 -D__FreeBSD_cc_version=500003 -Dunix -D__KPRINTF_ATTRIBUTE__ -Asystem=unix -Asystem=bsd -Asystem=FreeBSD"
+  "-D__FreeBSD__=5 -D__FreeBSD_cc_version=500004 -Dunix -D__KPRINTF_ATTRIBUTE__ -Asystem=unix -Asystem=bsd -Asystem=FreeBSD"
 #endif	/* ! FREEBSD_NATIVE */
 
 
 /* Provide a CPP_SPEC appropriate for FreeBSD.  We just deal with the GCC 
-   option `-posix', and PIC issues.  */
+   option `-posix', and PIC issues.  Also deal with the problem of
+   detecting support for the `long long' type. */
 
 #define FBSD_CPP_SPEC "							\
   %(cpp_cpu)								\
@@ -98,6 +99,8 @@
   %{munderscores: -D__UNDERSCORES__}					\
   %{maout: %{!mno-underscores: -D__UNDERSCORES__}}			\
   %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__}		\
+  %{!ansi:%{!std=*:-D__LONG_LONG_SUPPORTED}%{std=gnu*:-D__LONG_LONG_SUPPORTED}}\
+  %{std=c99:-D__LONG_LONG_SUPPORTED}\
   %{posix:-D_POSIX_SOURCE}"
 
 /* Provide a STARTFILE_SPEC appropriate for FreeBSD.  Here we add
Index: contrib/gcc/cp/cp-lang.c
===================================================================
RCS file: /home/ncvs/src/contrib/gcc/cp/cp-lang.c,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 cp-lang.c
--- contrib/gcc/cp/cp-lang.c	1 Sep 2002 20:38:06 -0000	1.1.1.2
+++ contrib/gcc/cp/cp-lang.c	8 Sep 2002 03:48:41 -0000
@@ -122,14 +122,8 @@
 {
   if (CLASS_TYPE_P (TREE_TYPE (exp)))
     {
-      /* The backend should not be interested in the size of an expression
-	 of a type with both of these set; all copies of such types must go
-	 through a constructor or assignment op.  */
-      if (TYPE_HAS_COMPLEX_INIT_REF (TREE_TYPE (exp))
-	  && TYPE_HAS_COMPLEX_ASSIGN_REF (TREE_TYPE (exp)))
-	abort ();
-      /* This would be wrong for a type with virtual bases, but they are
-	 caught by the abort above.  */
+      /* This would be wrong for a type with virtual bases, but they should
+	 not get here.  */
       return CLASSTYPE_SIZE_UNIT (TREE_TYPE (exp));
     }
   else
Index: gnu/lib/libdialog/gauge.c
===================================================================
RCS file: /home/ncvs/src/gnu/lib/libdialog/gauge.c,v
retrieving revision 1.4
diff -u -r1.4 gauge.c
--- gnu/lib/libdialog/gauge.c	30 May 2002 19:49:21 -0000	1.4
+++ gnu/lib/libdialog/gauge.c	8 Sep 2002 04:38:06 -0000
@@ -21,6 +21,7 @@
 __FBSDID("$FreeBSD: src/gnu/lib/libdialog/gauge.c,v 1.4 2002/05/30 19:49:21 wollman Exp $");
 
 #include <stdlib.h>
+#include <string.h>
 
 #include "dialog.h"
 
Index: include/fts.h
===================================================================
RCS file: /home/ncvs/src/include/fts.h,v
retrieving revision 1.6
diff -u -r1.6 fts.h
--- include/fts.h	26 Mar 2002 01:35:05 -0000	1.6
+++ include/fts.h	8 Sep 2002 04:15:13 -0000
@@ -47,7 +47,7 @@
 	int fts_pathlen;		/* sizeof(path) */
 	int fts_nitems;			/* elements in the sort array */
 	int (*fts_compar)		/* compare function */
-	    (const struct _ftsent **, const struct _ftsent **);
+	    (const struct _ftsent * const *, const struct _ftsent * const *);
 
 #define	FTS_COMFOLLOW	0x001		/* follow command line symlinks */
 #define	FTS_LOGICAL	0x002		/* logical walk */
@@ -122,7 +122,7 @@
 FTSENT	*fts_children(FTS *, int);
 int	 fts_close(FTS *);
 FTS	*fts_open(char * const *, int,
-	    int (*)(const FTSENT **, const FTSENT **));
+	    int (*)(const FTSENT * const *, const FTSENT * const *));
 FTSENT	*fts_read(FTS *);
 int	 fts_set(FTS *, FTSENT *, int);
 __END_DECLS
Index: include/stdlib.h
===================================================================
RCS file: /home/ncvs/src/include/stdlib.h,v
retrieving revision 1.40
diff -u -r1.40 stdlib.h
--- include/stdlib.h	1 Sep 2002 07:08:22 -0000	1.40
+++ include/stdlib.h	9 Sep 2002 00:24:00 -0000
@@ -40,7 +40,7 @@
 #include <sys/cdefs.h>
 #include <sys/_types.h>
 
-#if !defined(_ANSI_SOURCE) && !defined(_POSIX_SOURCE)
+#if __BSD_VISIBLE
 #ifndef _RUNE_T_DECLARED
 typedef	__rune_t	rune_t;
 #define	_RUNE_T_DECLARED
@@ -69,16 +69,6 @@
 	long rem;		/* remainder */
 } ldiv_t;
 
-#if !defined(_ANSI_SOURCE) && !defined(_POSIX_SOURCE)
-#ifdef __LONG_LONG_SUPPORTED
-/* LONGLONG */
-typedef struct {
-	long long quot;
-	long long rem;
-} lldiv_t;
-#endif
-#endif
-
 #ifndef NULL
 #define	NULL	0
 #endif
@@ -108,53 +98,138 @@
 long	 labs(long) __pure2;
 ldiv_t	 ldiv(long, long) __pure2;
 void	*malloc(size_t);
+int	 mblen(const char *, size_t);
+size_t	 mbstowcs(wchar_t *__restrict , const char *__restrict, size_t);
+int	 mbtowc(wchar_t *__restrict, const char *__restrict, size_t);
 void	 qsort(void *, size_t, size_t,
 	    int (*)(const void *, const void *));
 int	 rand(void);
 void	*realloc(void *, size_t);
 void	 srand(unsigned);
 double	 strtod(const char *__restrict, char **__restrict);
+/* float strtof(const char *__restrict, char **__restrict); */
 long	 strtol(const char *__restrict, char **__restrict, int);
+/* long double
+	 strtold(const char *__restrict, char **__restrict); */
 unsigned long
 	 strtoul(const char *__restrict, char **__restrict, int);
 int	 system(const char *);
 
-int	 mblen(const char *, size_t);
-size_t	 mbstowcs(wchar_t *__restrict , const char *__restrict, size_t);
 int	 wctomb(char *, wchar_t);
-int	 mbtowc(wchar_t *__restrict, const char *__restrict, size_t);
 size_t	 wcstombs(char *__restrict, const wchar_t *__restrict, size_t);
 
-#if !defined(_ANSI_SOURCE) && !defined(_POSIX_SOURCE)
-extern const char *_malloc_options;
-extern void (*_malloc_message)(const char *p1, const char *p2, const char *p3, const char *p4);
+/*
+ * Functions added in C99 which we make conditionally available in the
+ * BSD^C89 namespace if the compiler supports `long long'.
+ * The #if test is more complicated than it ought to be because
+ * __BSD_VISIBLE implies __ISO_C_VISIBLE == 1999 *even if* `long long'
+ * is not supported in the compilation environment (which therefore means
+ * that it can't really be ISO C99).
+ *
+ * (The only other extension made by C99 in thie header is _Exit().)
+ */
+#if __ISO_C_VISIBLE >= 1999
+#ifdef __LONG_LONG_SUPPORTED
+/* LONGLONG */
+typedef struct {
+	long long quot;
+	long long rem;
+} lldiv_t;
 
-int	 putenv(const char *);
+/* LONGLONG */
+long long
+	 atoll(const char *);
+/* LONGLONG */
+long long
+	 llabs(long long) __pure2;
+/* LONGLONG */
+lldiv_t	 lldiv(long long, long long) __pure2;
+/* LONGLONG */
+long long	 
+	 strtoll(const char *__restrict, char **__restrict, int);
+/* LONGLONG */
+unsigned long long
+	 strtoull(const char *__restrict, char **__restrict, int);
+#endif /* __LONG_LONG_SUPPORTED */
+
+void	_Exit(int) __dead2;
+#endif /* __ISO_C_VISIBLE >= 1999 */
+
+/*
+ * Extensions made by POSIX relative to C.  We don't know yet which edition
+ * of POSIX made these extensions, so assume they've always been there until
+ * research can be done.
+ */
+#if __POSIX_VISIBLE /* >= ??? */
+/* int	 posix_memalign(void **, size_t, size_t); (ADV) */
+int	 rand_r(unsigned *);			/* (TSF) */
 int	 setenv(const char *, const char *, int);
+void	 unsetenv(const char *);
+#endif
 
+/*
+ * The only changes to the XSI namespace in revision 6 were the deletion
+ * of the ttyslot() and valloc() functions, which FreeBSD never declared
+ * in this header.  For revision 7, ecvt(), fcvt(), and gcvt(), which
+ * FreeBSD also does not have, and mktemp(), are to be deleted.
+ */
+#if __XSI_VISIBLE
+/* XXX XSI requires pollution from <sys/wait.h> here.  We'd rather not. */
+/* long	 a64l(const char *); */
 double	 drand48(void);
+/* char	*ecvt(double, int, int *__restrict, int *__restrict); */
 double	 erand48(unsigned short[3]);
+/* char	*fcvt(double, int, int *__restrict, int *__restrict); */
+/* char	*gcvt(double, int, int *__restrict, int *__restrict); */
+#ifndef _GETSUBOPT_DECLARED
+int	 getsubopt(char **, char *const *, char **);
+#define	_GETSUBOPT_DECLARED
+#endif
+/* int	 grantpt(int); */
+char	*initstate(unsigned long /* XSI requires u_int */, char *, long);
 long	 jrand48(unsigned short[3]);
+/* char	*l64a(long); */
 void	 lcong48(unsigned short[7]);
 long	 lrand48(void);
+#ifndef _MKSTEMP_DECLARED
+int	 mkstemp(char *);
+#define	_MKSTEMP_DECLARED
+#endif
+#ifndef _MKTEMP_DECLARED
+char	*mktemp(char *);
+#define _MKTEMP_DECLARED
+#endif
 long	 mrand48(void);
 long	 nrand48(unsigned short[3]);
+/* int	 posix_openpt(int); */
+/* char	*ptsname(int); */
+int	 putenv(const char *);
+long	 random(void);
+char	*realpath(const char *, char resolved_path[]);
 unsigned short
 	*seed48(unsigned short[3]);
+#ifndef _SETKEY_DECLARED
+int	 setkey(const char *);
+#define	_SETKEY_DECLARED
+#endif
+char	*setstate(/* const */ char *);
 void	 srand48(long);
+void	 srandom(unsigned long);
+/* int	 unlockpt(int); */
+#endif /* __XSI_VISIBLE */
+
+
+#if __BSD_VISIBLE
+extern const char *_malloc_options;
+extern void (*_malloc_message)(const char *, const char *, const char *, const char *);
 
 void	*alloca(size_t);		/* built-in for gcc */
-					/* getcap(3) functions */
 __uint32_t
 	 arc4random(void);
 void	 arc4random_addrandom(unsigned char *dat, int datlen);
 void	 arc4random_stir(void);
-#ifdef __LONG_LONG_SUPPORTED
-/* LONGLONG */
-long long
-	 atoll(const char *);
-#endif
 char	*getbsize(int *, long *);
+					/* getcap(3) functions */
 char	*cgetcap(char *, const char *, int);
 int	 cgetclose(void);
 int	 cgetent(char **, char **, const char *);
@@ -173,42 +248,23 @@
 	 getprogname(void);
 
 int	 heapsort(void *, size_t, size_t, int (*)(const void *, const void *));
-char	*initstate(unsigned long, char *, long);
-#ifdef __LONG_LONG_SUPPORTED
-/* LONGLONG */
-long long
-	 llabs(long long) __pure2;
-lldiv_t	 lldiv(long long, long long) __pure2;
-#endif
 int	 mergesort(void *, size_t, size_t, int (*)(const void *, const void *));
+void	 qsort_r(void *, size_t, size_t, void *,
+	    int (*)(void *, const void *, const void *));
 int	 radixsort(const unsigned char **, int, const unsigned char *,
 	    unsigned);
+void    *reallocf(void *, size_t);
 int	 sradixsort(const unsigned char **, int, const unsigned char *,
 	    unsigned);
-int	 rand_r(unsigned *);
-long	 random(void);
-void    *reallocf(void *, size_t);
-char	*realpath(const char *, char resolved_path[]);
 void	 setprogname(const char *);
-char	*setstate(char *);
 void	 sranddev(void);
-void	 srandom(unsigned long);
 void	 srandomdev(void);
-#ifdef __LONG_LONG_SUPPORTED
-/* LONGLONG */
-long long	 
-	 strtoll(const char *__restrict, char **__restrict, int);
-#endif
+
+/* Deprecated interfaces, to be removed in FreeBSD 6.0. */
 __int64_t	 strtoq(const char *, char **, int);
-#ifdef __LONG_LONG_SUPPORTED
-/* LONGLONG */
-unsigned long long
-	 strtoull(const char *__restrict, char **__restrict, int);
-#endif
 __uint64_t
 	 strtouq(const char *, char **, int);
-void	 unsetenv(const char *);
-#endif /* !_ANSI_SOURCE && !_POSIX_SOURCE */
+#endif /* __BSD_VISIBLE */
 __END_DECLS
 
 #endif /* !_STDLIB_H_ */
Index: include/unistd.h
===================================================================
RCS file: /home/ncvs/src/include/unistd.h,v
retrieving revision 1.56
diff -u -r1.56 unistd.h
--- include/unistd.h	21 Aug 2002 16:19:55 -0000	1.56
+++ include/unistd.h	8 Sep 2002 18:51:36 -0000
@@ -254,9 +254,15 @@
 int	 issetugid(void);
 char	*mkdtemp(char *);
 int	 mknod(const char *, mode_t, dev_t);
+#ifndef _MKSTEMP_DECLARED
 int	 mkstemp(char *);
+#define	_MKSTEMP_DECLARED
+#endif
 int	 mkstemps(char *, int);
+#ifndef _MKTEMP_DECLARED
 char	*mktemp(char *);
+#define	_MKTEMP_DECLARED
+#endif
 int	 nfsclnt(int, void *);
 int	 nfssvc(int, void *);
 int	 profil(char *, size_t, vm_offset_t, int);
@@ -281,7 +287,10 @@
 int	 setgroups(int, const gid_t *);
 void	 sethostid(long);
 int	 sethostname(const char *, int);
+#ifndef _SETKEY_DECLARED
 int	 setkey(const char *);
+#define	_SETKEY_DECLARED
+#endif
 int	 setlogin(const char *);
 void	*setmode(const char *);
 int	 setresgid(gid_t, gid_t, gid_t);
@@ -299,7 +308,10 @@
 void	*valloc(size_t);			/* obsoleted by malloc() */
 
 extern char *suboptarg;			/* getsubopt(3) external variable */
+#ifndef _GETSUBOPT_DECLARED
 int	 getsubopt(char **, char * const *, char **);
+#define	_GETSUBOPT_DECLARED
+#endif
 extern int optreset;			/* getopt(3) external variable */
 #endif /* __BSD_VISIBLE */
 __END_DECLS
Index: lib/libc/gen/fts.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/gen/fts.c,v
retrieving revision 1.20
diff -u -r1.20 fts.c
--- lib/libc/gen/fts.c	1 Feb 2002 01:32:19 -0000	1.20
+++ lib/libc/gen/fts.c	8 Sep 2002 04:45:19 -0000
@@ -81,7 +81,7 @@
 fts_open(argv, options, compar)
 	char * const *argv;
 	int options;
-	int (*compar)(const FTSENT **, const FTSENT **);
+	int (*compar)(const FTSENT * const *, const FTSENT * const *);
 {
 	FTS *sp;
 	FTSENT *p, *root;
@@ -96,7 +96,7 @@
 	}
 
 	/* Allocate/initialize the stream */
-	if ((sp = malloc((u_int)sizeof(FTS))) == NULL)
+	if ((sp = malloc(sizeof(FTS))) == NULL)
 		return (NULL);
 	memset(sp, 0, sizeof(FTS));
 	sp->fts_compar = compar;
@@ -907,6 +907,28 @@
 	return (FTS_DEFAULT);
 }
 
+/*
+ * The comparison function takes pointers to pointers to FTSENT structures.
+ * Qsort wants a comparison function that takes pointers to void.
+ * Rather than break the API, we use a trampoline function in conjunction
+ * with qsort_r() to deal with the difference in types at a small cost
+ * in efficiency.  If FTSENT had a pointer to its parent FTS, we could do
+ * this with regular qsort instead of qsort_r.
+ *
+ * XXX Rather than going to this effort, we could just accept the
+ * undefined-but-unlikely-to-ever-fail behavior and just use the union
+ * hack to suppress the compiler warning from calling qsort() with the
+ * wrong function pointer type.
+ */
+static int
+fts_compar_thunked(void *thunk, const void *a, const void *b)
+{
+	FTS *parent;
+
+	parent = thunk;
+	return (*parent->fts_compar)(a, b);
+}
+
 static FTSENT *
 fts_sort(sp, head, nitems)
 	FTS *sp;
@@ -932,7 +954,8 @@
 	}
 	for (ap = sp->fts_array, p = head; p; p = p->fts_link)
 		*ap++ = p;
-	qsort((void *)sp->fts_array, nitems, sizeof(FTSENT *), sp->fts_compar);
+	qsort_r((void *)sp->fts_array, nitems, sizeof(FTSENT *), sp,
+	    fts_compar_thunked);
 	for (head = *(ap = sp->fts_array); --nitems; ++ap)
 		ap[0]->fts_link = ap[1];
 	ap[0]->fts_link = NULL;
Index: lib/libc/gen/getgrouplist.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/gen/getgrouplist.c,v
retrieving revision 1.11
diff -u -r1.11 getgrouplist.c
--- lib/libc/gen/getgrouplist.c	22 Mar 2002 21:52:05 -0000	1.11
+++ lib/libc/gen/getgrouplist.c	8 Sep 2002 04:10:33 -0000
@@ -85,6 +85,7 @@
 			}
 		}
 skip:
+		;
 	}
 	endgrent();
 	*grpcnt = ngroups;
Index: lib/libc/stdlib/Makefile.inc
===================================================================
RCS file: /home/ncvs/src/lib/libc/stdlib/Makefile.inc,v
retrieving revision 1.36
diff -u -r1.36 Makefile.inc
--- lib/libc/stdlib/Makefile.inc	2 Dec 2001 18:27:40 -0000	1.36
+++ lib/libc/stdlib/Makefile.inc	8 Sep 2002 03:04:48 -0000
@@ -4,11 +4,11 @@
 # machine-independent stdlib sources
 .PATH: ${.CURDIR}/../libc/${MACHINE_ARCH}/stdlib ${.CURDIR}/../libc/stdlib
 
-MISRCS+=abort.c abs.c atexit.c atof.c atoi.c atol.c atoll.c \
+MISRCS+=_Exit.c abort.c abs.c atexit.c atof.c atoi.c atol.c atoll.c \
 	bsearch.c calloc.c div.c exit.c getenv.c getopt.c \
 	getsubopt.c hcreate.c heapsort.c imaxabs.c imaxdiv.c \
 	labs.c ldiv.c llabs.c lldiv.c malloc.c merge.c putenv.c \
-	qsort.c radixsort.c rand.c random.c reallocf.c realpath.c \
+	qsort.c qsort_r.c radixsort.c rand.c random.c reallocf.c realpath.c \
 	setenv.c strfmon.c strhash.c strtod.c strtoimax.c strtol.c strtoll.c \
 	strtoq.c strtoul.c strtoull.c strtoumax.c strtouq.c system.c \
 	tdelete.c tfind.c tsearch.c twalk.c
@@ -26,9 +26,10 @@
 	realpath.3 strfmon.3 strtod.3 strtol.3 strtoul.3 system.3 tsearch.3
 
 MLINKS+=atol.3 atoll.3
+MLINKS+=exit.3 _Exit.3
 MLINKS+=getenv.3 putenv.3 getenv.3 setenv.3 getenv.3 unsetenv.3
 MLINKS+=hcreate.3 hdestroy.3 hcreate.3 hsearch.3
-MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3
+MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3 qsort.3 qsort_r.3
 MLINKS+=rand.3 rand_r.3 rand.3 srand.3 rand.3 sranddev.3
 MLINKS+=random.3 initstate.3 random.3 setstate.3 random.3 srandom.3 \
 	random.3 srandomdev.3
Index: lib/libc/stdlib/exit.3
===================================================================
RCS file: /home/ncvs/src/lib/libc/stdlib/exit.3,v
retrieving revision 1.10
diff -u -r1.10 exit.3
--- lib/libc/stdlib/exit.3	7 Sep 2001 14:46:35 -0000	1.10
+++ lib/libc/stdlib/exit.3	8 Sep 2002 02:02:48 -0000
@@ -36,11 +36,12 @@
 .\"     @(#)exit.3	8.1 (Berkeley) 6/4/93
 .\" $FreeBSD: src/lib/libc/stdlib/exit.3,v 1.10 2001/09/07 14:46:35 asmodai Exp $
 .\"
-.Dd June 4, 1993
+.Dd September 7, 2002
 .Dt EXIT 3
 .Os
 .Sh NAME
 .Nm exit
+.Nm _Exit
 .Nd perform normal program termination
 .Sh LIBRARY
 .Lb libc
@@ -48,12 +49,18 @@
 .In stdlib.h
 .Ft void
 .Fn exit "int status"
+.Ft void
+.Fn _Exit "int status"
 .Sh DESCRIPTION
-.Fn Exit
-terminates a process.
+The
+.Fn exit
+and
+.Fn _Exit
+functions terminate a process.
 .Pp
-Before termination it performs the following functions in the
-order listed:
+Before termination,
+.Fn exit
+performs the following functions in the order listed:
 .Bl -enum -offset indent
 .It
 Call the functions registered with the
@@ -69,23 +76,43 @@
 function.
 .El
 .Pp
-Passing arbitrary values back to the environment as
-.Ar status
-is considered bad style;
-you should use the values
-.Dv EXIT_SUCCESS
+The
+.Fn _Exit
+function terminates without calling the functions registered with the
+.Xr atexit 3
+function, and may or may not perform the other actions listed.
+Both functions make the low-order eight bits of the
+.Fa status
+argument available to a parent process which has called a
+.Xr wait 2 Ns -family
+function.
+.Pp
+The C Standard
+.Pq St -isoC
+defines the values
+.Li 0 ,
+.Dv EXIT_SUCCESS ,
 and
-.Dv EXIT_FAILURE .
-If portability is not a concern, you may
-use the values described in
-.Xr sysexits 3 .
+.Dv EXIT_FAILURE
+as possible values of
+.Fa status .
+Passing arbitrary integer values for
+.Fa status
+is considered bad style.
+Cooperating processes may use other values;
+in a program which might be called by a mail transfer agent, the
+the values described in
+.Xr sysexits 3
+may be used to provide more information to the parent process.
 .Sh RETURN VALUES
 The
 .Fn exit
-function
-never returns.
+and
+.Fn _Exit
+functions never return.
 .Sh SEE ALSO
 .Xr _exit 2 ,
+.Xr wait 2 ,
 .Xr atexit 3 ,
 .Xr intro 3 ,
 .Xr sysexits 3 ,
@@ -93,6 +120,7 @@
 .Sh STANDARDS
 The
 .Fn exit
-function
-conforms to
+and
+.Fn _Exit
+functions conform to
 .St -isoC .
Index: lib/libc/stdlib/qsort.3
===================================================================
RCS file: /home/ncvs/src/lib/libc/stdlib/qsort.3,v
retrieving revision 1.10
diff -u -r1.10 qsort.3
--- lib/libc/stdlib/qsort.3	7 Sep 2001 14:46:35 -0000	1.10
+++ lib/libc/stdlib/qsort.3	8 Sep 2002 03:16:04 -0000
@@ -36,11 +36,11 @@
 .\"     @(#)qsort.3	8.1 (Berkeley) 6/4/93
 .\" $FreeBSD: src/lib/libc/stdlib/qsort.3,v 1.10 2001/09/07 14:46:35 asmodai Exp $
 .\"
-.Dd June 4, 1993
+.Dd September 7, 2002
 .Dt QSORT 3
 .Os
 .Sh NAME
-.Nm qsort , heapsort , mergesort
+.Nm qsort , qsort_r , heapsort , mergesort
 .Nd sort functions
 .Sh LIBRARY
 .Lb libc
@@ -48,6 +48,14 @@
 .In stdlib.h
 .Ft void
 .Fn qsort "void *base" "size_t nmemb" "size_t size" "int (*compar)(const void *, const void *)"
+.Ft void
+.Fo qsort_r
+.Fa "void *base"
+.Fa "size_t nmemb"
+.Fa "size_t size"
+.Fa "void *thunk"
+.Fa "int (*compar)(void *, const void *, const void *)"
+.Fc
 .Ft int
 .Fn heapsort "void *base" "size_t nmemb" "size_t size" "int (*compar)(const void *, const void *)"
 .Ft int
@@ -94,24 +102,40 @@
 greater than zero if the first argument is considered to be respectively
 less than, equal to, or greater than the second.
 .Pp
-The functions
-.Fn qsort
+The
+.Fn qsort_r
+function behaves identically to
+.Fn qsort ,
+except that it takes an additional argument,
+.Fa thunk ,
+which is passed unchanged as the first argument to function pointed to
+.Fa compar .
+This allows the comparison function to access additional
+data without using global variables, and thus 
+.Fn qsort_r
+is suitable for use in functions which must be reentrant.
+.Pp
+The algorithms implemented by
+.Fn qsort ,
+.Fn qsort_r ,
 and
 .Fn heapsort
 are
 .Em not
 stable, that is, if two members compare as equal, their order in
 the sorted array is undefined.
-The function
+The
 .Fn mergesort
-is stable.
+algorithm is stable.
 .Pp
 The
 .Fn qsort
-function is an implementation of C.A.R. Hoare's ``quicksort'' algorithm,
+and
+.Fn qsort_r
+functions are an implementation of C.A.R. Hoare's ``quicksort'' algorithm,
 a variant of partition-exchange sorting; in particular, see D.E. Knuth's
 Algorithm Q.
-.Fn Qsort
+.Sy Quicksort
 takes O N lg N average time.
 This implementation uses median selection to avoid its
 O N**2 worst-case behavior.
@@ -120,7 +144,7 @@
 .Fn heapsort
 function is an implementation of J.W.J. William's ``heapsort'' algorithm,
 a variant of selection sorting; in particular, see D.E. Knuth's Algorithm H.
-.Fn Heapsort
+.Sy Heapsort
 takes O N lg N worst-case time.
 Its
 .Em only
@@ -151,8 +175,10 @@
 .Sh RETURN VALUES
 The
 .Fn qsort
-function
-returns no value.
+and
+.Fn qsort_r
+functions
+return no value.
 .Pp
 .Rv -std heapsort mergesort
 .Sh ERRORS
Index: lib/libc/stdlib/qsort.c
===================================================================
RCS file: /home/ncvs/src/lib/libc/stdlib/qsort.c,v
retrieving revision 1.11
diff -u -r1.11 qsort.c
--- lib/libc/stdlib/qsort.c	22 Mar 2002 21:53:10 -0000	1.11
+++ lib/libc/stdlib/qsort.c	8 Sep 2002 04:11:34 -0000
@@ -39,8 +39,12 @@
 
 #include <stdlib.h>
 
+#ifdef I_AM_QSORT_R
+typedef int		 cmp_t(void *, const void *, const void *);
+#else
 typedef int		 cmp_t(const void *, const void *);
-static inline char	*med3(char *, char *, char *, cmp_t *);
+#endif
+static inline char	*med3(char *, char *, char *, cmp_t *, void *);
 static inline void	 swapfunc(char *, char *, int, int);
 
 #define min(a, b)	(a) < (b) ? a : b
@@ -83,21 +87,32 @@
 
 #define vecswap(a, b, n) 	if ((n) > 0) swapfunc(a, b, n, swaptype)
 
+#ifdef I_AM_QSORT_R
+#define	CMP(t, x, y) (cmp((t), (x), (y)))
+#else
+#define	CMP(t, x, y) (cmp((x), (y)))
+#endif
+
 static inline char *
-med3(a, b, c, cmp)
-	char *a, *b, *c;
-	cmp_t *cmp;
+med3(char *a, char *b, char *c, cmp_t *cmp, void *thunk
+#ifndef 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 ));
 }
 
+#ifdef I_AM_QSORT_R
+void
+qsort_r(void *a, size_t n, size_t es, void *thunk, cmp_t *cmp)
+#else
+#define thunk NULL
 void
-qsort(a, n, es, cmp)
-	void *a;
-	size_t n, es;
-	cmp_t *cmp;
+qsort(void *a, size_t n, size_t es, cmp_t *cmp)
+#endif
 {
 	char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
 	int d, r, swaptype, swap_cnt;
@@ -106,7 +121,8 @@
 	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;
@@ -117,18 +133,18 @@
 		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) {
+		while (pb <= pc && (r = CMP(thunk, pb, a)) <= 0) {
 			if (r == 0) {
 				swap_cnt = 1;
 				swap(pa, pb);
@@ -136,7 +152,7 @@
 			}
 			pb += es;
 		}
-		while (pb <= pc && (r = cmp(pc, a)) >= 0) {
+		while (pb <= pc && (r = CMP(thunk, pc, a)) >= 0) {
 			if (r == 0) {
 				swap_cnt = 1;
 				swap(pc, pd);
@@ -153,7 +169,8 @@
 	}
 	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;
@@ -165,7 +182,11 @@
 	r = min(pd - pc, pn - pd - es);
 	vecswap(pb, pn - r, r);
 	if ((r = pb - pa) > es)
+#ifdef I_AM_QSORT_R
+		qsort_r(a, r / es, es, thunk, cmp);
+#else
 		qsort(a, r / es, es, cmp);
+#endif
 	if ((r = pd - pc) > es) {
 		/* Iterate rather than recurse to save stack space */
 		a = pn - r;
Index: sys/sys/cdefs.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/cdefs.h,v
retrieving revision 1.59
diff -u -r1.59 cdefs.h
--- sys/sys/cdefs.h	15 Jul 2002 16:44:07 -0000	1.59
+++ sys/sys/cdefs.h	8 Sep 2002 18:37:11 -0000
@@ -133,9 +133,23 @@
 #define	__func__	NULL
 #endif
 
-/* XXX: should use `#if __STDC_VERSION__ >= 199901'. */
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+/*
+ * GCC versions before 3.1 (3.0?) don't complain about `long long' except in
+ * strict C90 mode.  GCC 3.1 and later do complain, but don't define anything
+ * that would let us know if they were in C90 mode -- but will tell us
+ * if they are in C99 mode, which does support `long long'.  As a further
+ * complication, we need to support `long long' for GCC 3.2 in non-strict C89
+ * mode, and there is no way to distinguish the modes.
+ * In FreeBSD-native GCC, __FreeBSD_cc_version >= 500004, we have hacked
+ * the preprocessing spec so that the compiler just tells us automatically.
+ */
+#if (__GNUC__ < 3 || __GNUC__ == 3 && __GNUC_MINOR__ < 1)
+#ifndef __STRICT_ANSI__
 #define	__LONG_LONG_SUPPORTED
+#endif
+#endif
+#if __STDC_VERSION__ >= 199901 && __FreeBSD_cc_version < 500004
+#define __LONG_LONG_SUPPORTED
 #endif
 
 /*
Index: usr.bin/find/find.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/find/find.c,v
retrieving revision 1.14
diff -u -r1.14 find.c
--- usr.bin/find/find.c	2 Jun 2002 12:57:41 -0000	1.14
+++ usr.bin/find/find.c	9 Sep 2002 01:10:08 -0000
@@ -56,7 +56,7 @@
 
 #include "find.h"
 
-static int	find_compare(const FTSENT **s1, const FTSENT **s2);
+static int find_compare(const FTSENT * const *s1, const FTSENT * const *s2);
 
 /*
  * find_compare --
@@ -66,7 +66,7 @@
  */
 static int
 find_compare(s1, s2)
-	const FTSENT **s1, **s2;
+	const FTSENT * const *s1, * const *s2;
 {
 
 	return (strcoll((*s1)->fts_name, (*s2)->fts_name));
Index: usr.sbin/ctm/ctm_dequeue/ctm_dequeue.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/ctm/ctm_dequeue/ctm_dequeue.c,v
retrieving revision 1.10
diff -u -r1.10 ctm_dequeue.c
--- usr.sbin/ctm/ctm_dequeue/ctm_dequeue.c	9 Jul 2001 09:23:58 -0000	1.10
+++ usr.sbin/ctm/ctm_dequeue/ctm_dequeue.c	9 Sep 2002 03:14:56 -0000
@@ -53,7 +53,7 @@
 
 #define DEFAULT_NUM	1	/* Default number of pieces mailed per run. */
 
-int fts_sort(const FTSENT **, const FTSENT **);
+int fts_sort(const FTSENT * const *, const FTSENT * const *);
 int run_sendmail(int ifd);
 
 int
@@ -156,7 +156,7 @@
 }
 
 int
-fts_sort(const FTSENT ** a, const FTSENT ** b)
+fts_sort(const FTSENT * const * a, const FTSENT * const * b)
 {
     if ((*a)->fts_info != FTS_F)
 	return(0);
Index: usr.sbin/mtree/create.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/mtree/create.c,v
retrieving revision 1.26
diff -u -r1.26 create.c
--- usr.sbin/mtree/create.c	15 Jul 2002 12:17:31 -0000	1.26
+++ usr.sbin/mtree/create.c	9 Sep 2002 02:24:11 -0000
@@ -80,7 +80,7 @@
 static mode_t mode;
 static u_long flags = 0xffffffff;
 
-static int	dsort(const FTSENT **, const FTSENT **);
+static int	dsort(const FTSENT * const *, const FTSENT * const *);
 static void	output(int, int *, const char *, ...) __printflike(3, 4);
 static int	statd(FTS *, FTSENT *, uid_t *, gid_t *, mode_t *, u_long *);
 static void	statf(int, FTSENT *);
@@ -398,7 +398,7 @@
 
 static int
 dsort(a, b)
-	const FTSENT **a, **b;
+	const FTSENT * const *a, * const *b;
 {
 	if (S_ISDIR((*a)->fts_statp->st_mode)) {
 		if (!S_ISDIR((*b)->fts_statp->st_mode))
Index: usr.sbin/pkg_install/lib/match.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/pkg_install/lib/match.c,v
retrieving revision 1.12
diff -u -r1.12 match.c
--- usr.sbin/pkg_install/lib/match.c	22 May 2002 10:33:25 -0000	1.12
+++ usr.sbin/pkg_install/lib/match.c	9 Sep 2002 03:12:24 -0000
@@ -40,7 +40,7 @@
 static int rex_match(const char *, const char *);
 struct store *storecreate(struct store *);
 static int storeappend(struct store *, const char *);
-static int fname_cmp(const FTSENT **, const FTSENT **);
+static int fname_cmp(const FTSENT * const *, const FTSENT * const *);
 
 /*
  * Function to query names of installed packages.
@@ -337,7 +337,7 @@
 }
 
 static int
-fname_cmp(const FTSENT **a, const FTSENT **b)
+fname_cmp(const FTSENT * const *a, const FTSENT * const *b)
 {
     return strcmp((*a)->fts_name, (*b)->fts_name);
 }

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-standards" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200209091736.g89HaDnh066298>