From owner-freebsd-standards Mon Sep 9 10:36:58 2002 Delivered-To: freebsd-standards@freebsd.org Received: from mx1.FreeBSD.org (mx1.FreeBSD.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 8EEEC37B400 for ; Mon, 9 Sep 2002 10:36:15 -0700 (PDT) Received: from khavrinen.lcs.mit.edu (khavrinen.lcs.mit.edu [18.24.4.193]) by mx1.FreeBSD.org (Postfix) with ESMTP id 3806C43E4A for ; Mon, 9 Sep 2002 10:36:14 -0700 (PDT) (envelope-from wollman@khavrinen.lcs.mit.edu) Received: from khavrinen.lcs.mit.edu (localhost [IPv6:::1]) by khavrinen.lcs.mit.edu (8.12.3/8.12.5) with ESMTP id g89HaDVo066301 (version=TLSv1/SSLv3 cipher=EDH-RSA-DES-CBC3-SHA bits=168 verify=OK) for ; Mon, 9 Sep 2002 13:36:13 -0400 (EDT) (envelope-from wollman@khavrinen.lcs.mit.edu) Received: (from wollman@localhost) by khavrinen.lcs.mit.edu (8.12.3/8.12.5/Submit) id g89HaDnh066298; Mon, 9 Sep 2002 13:36:13 -0400 (EDT) (envelope-from wollman) Date: Mon, 9 Sep 2002 13:36:13 -0400 (EDT) From: Garrett Wollman Message-Id: <200209091736.g89HaDnh066298@khavrinen.lcs.mit.edu> To: standards@FreeBSD.org Subject: CFR: Jumbo stdlib.h/qsort_r patch Sender: owner-freebsd-standards@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG 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 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 +#include #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 #include -#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 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 +#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