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>
index | next in thread | raw e-mail
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
help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200209091736.g89HaDnh066298>
