diff options
Diffstat (limited to 'lib/libc/stdlib')
99 files changed, 0 insertions, 20797 deletions
diff --git a/lib/libc/stdlib/Makefile.inc b/lib/libc/stdlib/Makefile.inc deleted file mode 100644 index ee4c4e2..0000000 --- a/lib/libc/stdlib/Makefile.inc +++ /dev/null @@ -1,53 +0,0 @@ -# from @(#)Makefile.inc 8.3 (Berkeley) 2/4/95 -# $FreeBSD$ - -# machine-independent stdlib sources -.PATH: ${.CURDIR}/${LIBC_ARCH}/stdlib ${.CURDIR}/stdlib - -MISRCS+=_Exit.c a64l.c abort.c abs.c atexit.c atof.c atoi.c atol.c atoll.c \ - bsearch.c div.c exit.c getenv.c getopt.c getopt_long.c \ - getsubopt.c hcreate.c heapsort.c imaxabs.c imaxdiv.c \ - insque.c l64a.c labs.c ldiv.c llabs.c lldiv.c lsearch.c malloc.c \ - merge.c ptsname.c qsort.c qsort_r.c radixsort.c rand.c random.c \ - reallocf.c realpath.c remque.c sigwait.c strfmon.c strtoimax.c \ - strtol.c strtoll.c strtoq.c strtoul.c strtonum.c strtoull.c \ - strtoumax.c strtouq.c system.c tdelete.c tfind.c tsearch.c twalk.c - -SYM_MAPS+= ${.CURDIR}/stdlib/Symbol.map - -# machine-dependent stdlib sources -.sinclude "${.CURDIR}/${LIBC_ARCH}/stdlib/Makefile.inc" - -MAN+= a64l.3 abort.3 abs.3 alloca.3 atexit.3 atof.3 atoi.3 atol.3 bsearch.3 \ - div.3 exit.3 getenv.3 getopt.3 getopt_long.3 getsubopt.3 \ - hcreate.3 imaxabs.3 imaxdiv.3 insque.3 labs.3 ldiv.3 llabs.3 lldiv.3 \ - lsearch.3 malloc.3 memory.3 posix_memalign.3 ptsname.3 qsort.3 \ - radixsort.3 rand.3 random.3 \ - realpath.3 strfmon.3 strtod.3 strtol.3 strtonum.3 strtoul.3 system.3 \ - tsearch.3 - -MLINKS+=a64l.3 l64a.3 a64l.3 l64a_r.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+=getopt_long.3 getopt_long_only.3 -MLINKS+=hcreate.3 hdestroy.3 hcreate.3 hsearch.3 -MLINKS+=insque.3 remque.3 -MLINKS+=lsearch.3 lfind.3 -MLINKS+=ptsname.3 grantpt.3 ptsname.3 unlockpt.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 -MLINKS+=radixsort.3 sradixsort.3 -MLINKS+=strtod.3 strtof.3 strtod.3 strtold.3 -MLINKS+=strtol.3 strtoll.3 strtol.3 strtoq.3 strtol.3 strtoimax.3 -MLINKS+=strtoul.3 strtoull.3 strtoul.3 strtouq.3 strtoul.3 strtoumax.3 -MLINKS+=malloc.3 calloc.3 malloc.3 free.3 malloc.3 malloc.conf.5 \ - malloc.3 realloc.3 malloc.3 reallocf.3 malloc.3 malloc_usable_size.3 -MLINKS+=tsearch.3 tdelete.3 tsearch.3 tfind.3 tsearch.3 twalk.3 - -.if defined(MALLOC_PRODUCTION) -CFLAGS+= -DMALLOC_PRODUCTION -.endif - diff --git a/lib/libc/stdlib/Symbol.map b/lib/libc/stdlib/Symbol.map deleted file mode 100644 index d159bed..0000000 --- a/lib/libc/stdlib/Symbol.map +++ /dev/null @@ -1,101 +0,0 @@ -/* - * $FreeBSD$ - */ - -FBSD_1.0 { - _Exit; - a64l; - abort; - abs; - atexit; - __cxa_atexit; - __cxa_finalize; - atof; - atoi; - atol; - atoll; - bsearch; - div; - __isthreaded; - exit; - getenv; - opterr; - optind; - optopt; - optreset; - optarg; - getopt; - getopt_long; - getopt_long_only; - suboptarg; - getsubopt; - grantpt; - ptsname; - unlockpt; - hcreate; - hdestroy; - hsearch; - heapsort; - imaxabs; - imaxdiv; - insque; - l64a; - l64a_r; - labs; - ldiv; - llabs; - lldiv; - lsearch; - lfind; - _malloc_options; - _malloc_message; - malloc; - posix_memalign; - calloc; - realloc; - free; - malloc_usable_size; - mergesort; - putenv; - qsort_r; - qsort; - radixsort; - sradixsort; - rand_r; - rand; - srand; - sranddev; - srandom; - srandomdev; - initstate; - setstate; - random; - reallocf; - realpath; - remque; - setenv; - unsetenv; - strfmon; - strtoimax; - strtol; - strtoll; - strtonum; - strtoq; - strtoul; - strtoull; - strtoumax; - strtouq; - system; - tdelete; - tfind; - tsearch; - twalk; -}; - -FBSDprivate_1.0 { - _malloc_thread_cleanup; - _malloc_prefork; - _malloc_postfork; - __system; - _system; -}; diff --git a/lib/libc/stdlib/_Exit.c b/lib/libc/stdlib/_Exit.c deleted file mode 100644 index e7f0f51..0000000 --- a/lib/libc/stdlib/_Exit.c +++ /dev/null @@ -1,22 +0,0 @@ -/* - * This file is in the public domain. Written by Garrett A. Wollman, - * 2002-09-07. - * - * $FreeBSD$ - */ - -#include <stdlib.h> -#include <unistd.h> - -/* - * ISO C99 added this function to provide for Standard C applications - * which needed something like POSIX _exit(). A new interface was created - * in case it turned out that _exit() was insufficient to meet the - * requirements of ISO C. (That's probably not the case, but here - * is where you would put the extra code if it were.) - */ -void -_Exit(int code) -{ - _exit(code); -} diff --git a/lib/libc/stdlib/a64l.3 b/lib/libc/stdlib/a64l.3 deleted file mode 100644 index 61fbffd..0000000 --- a/lib/libc/stdlib/a64l.3 +++ /dev/null @@ -1,187 +0,0 @@ -.\" Copyright (c) 2005 Tom Rhodes -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" Portions of this text are reprinted and reproduced in electronic form -.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology -- -.\" Portable Operating System Interface (POSIX), The Open Group Base -.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of -.\" Electrical and Electronics Engineers, Inc and The Open Group. In the -.\" event of any discrepancy between this version and the original IEEE and -.\" The Open Group Standard, the original IEEE and The Open Group Standard is -.\" the referee document. The original Standard can be obtained online at -.\" http://www.opengroup.org/unix/online.html. -.\" -.\" $FreeBSD$ -.\" -.Dd November 20, 2005 -.Dt A64L 3 -.Os -.Sh NAME -.Nm a64l , -.Nm l64a , -.Nm l64a_r -.Nd "convert between a long integer and a base-64 ASCII string" -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In stdlib.h -.Ft long -.Fn a64l "const char *s" -.Ft char * -.Fn l64a "long int l" -.Ft int -.Fn l64a_r "long int l" "char *buffer" "int buflen" -.Sh DESCRIPTION -These functions are used to maintain numbers stored in radix-64 -.Tn ASCII -characters. -This is a notation by which 32-bit integers can be represented by -up to six characters; each character represents a digit in -radix-64 notation. -If the type long contains more than 32 bits, only the low-order -32 bits are used for these operations. -.Pp -The characters used to represent -.Dq digits -are -.Ql .\& -for 0, -.Ql / -for 1, -.Ql 0 -- -.Ql 9 -for 2 - 11, -.Ql A -- -.Ql Z -for 12 - 37, and -.Ql a -- -.Ql z -for 38 - 63. -.Pp -The -.Fn a64l -function takes a pointer to a radix-64 representation, in which the first -digit is the least significant, and returns a corresponding -.Vt long -value. -If the string pointed to by -.Fa s -contains more than six characters, -.Fn a64l -uses the first six. -If the first six characters of the string contain a null terminator, -.Fn a64l -uses only characters preceding the null terminator. -The -.Fn a64l -function scans the character string from left to right with the least -significant digit on the left, decoding each character as a 6-bit -radix-64 number. -If the type long contains more than 32 bits, the resulting value is -sign-extended. -The behavior of -.Fn a64l -is unspecified if -.Fa s -is a null pointer or the string pointed to by -.Fa s -was not generated by a previous call to -.Fn l64a . -.Pp -The -.Fn l64a -function takes a -.Vt long -argument and returns a pointer to the corresponding -radix-64 representation. -The behavior of -.Fn l64a -is unspecified if value is negative. -.Pp -The value returned by -.Fn l64a -is a pointer into a static buffer. -Subsequent calls to -.Fn l64a -may overwrite the buffer. -.Pp -The -.Fn l64a_r -function performs a conversion identical to that of -.Fn l64a -and stores the resulting representation in the memory area pointed to by -.Fa buffer , -consuming at most -.Fa buflen -characters including the terminating -.Dv NUL -character. -.Sh RETURN VALUES -On successful completion, -.Fn a64l -returns the -.Vt long -value resulting from conversion of the input string. -If a string pointed to by -.Fa s -is an empty string, -.Fn a64l -returns 0. -.Pp -The -.Fn l64a -function returns a pointer to the radix-64 representation. -If value is 0, -.Fn l64a -returns a pointer to an empty string. -.Sh SEE ALSO -.Xr strtoul 3 -.Sh HISTORY -The -.Fn a64l , -.Fn l64a , -and -.Fn l64a_r -functions are derived from -.Nx -with modifications. -They appeared in -.Fx 6.1 . -.Sh AUTHORS -The -.Fn a64l , -.Fn l64a , -and -.Fn l64a_r -functions -were added to -.Fx -by -.An Tom Rhodes Aq trhodes@FreeBSD.org . -Almost all of this manual page came from the -.Tn POSIX -standard. diff --git a/lib/libc/stdlib/a64l.c b/lib/libc/stdlib/a64l.c deleted file mode 100644 index a130dcb..0000000 --- a/lib/libc/stdlib/a64l.c +++ /dev/null @@ -1,46 +0,0 @@ -/*- - * Written by J.T. Conklin <jtc@netbsd.org>. - * Public domain. - */ - -#if 0 -#if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: a64l.c,v 1.8 2000/01/22 22:19:19 mycroft Exp $"); -#endif /* not lint */ -#endif - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stdlib.h> -#include <inttypes.h> - -#define ADOT 46 /* ASCII '.' */ -#define ASLASH 47 /* ASCII '/' */ -#define A0 48 /* ASCII '0' */ -#define AA 65 /* ASCII 'A' */ -#define Aa 97 /* ASCII 'a' */ - -long -a64l(const char *s) -{ - long shift; - int digit, i, value; - - value = 0; - shift = 0; - for (i = 0; *s != '\0' && i < 6; i++, s++) { - if (*s <= ASLASH) - digit = *s - ASLASH + 1; - else if (*s <= A0 + 9) - digit = *s - A0 + 2; - else if (*s <= AA + 25) - digit = *s - AA + 12; - else - digit = *s - Aa + 38; - - value |= digit << shift; - shift += 6; - } - return (value); -} diff --git a/lib/libc/stdlib/abort.3 b/lib/libc/stdlib/abort.3 deleted file mode 100644 index b939e9c2..0000000 --- a/lib/libc/stdlib/abort.3 +++ /dev/null @@ -1,79 +0,0 @@ -.\" Copyright (c) 1990, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the American National Standards Committee X3, on Information -.\" Processing Systems. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)abort.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD$ -.\" -.Dd June 4, 1993 -.Dt ABORT 3 -.Os -.Sh NAME -.Nm abort -.Nd cause abnormal program termination -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In stdlib.h -.Ft void -.Fn abort void -.Sh DESCRIPTION -The -.Fn abort -function causes abnormal program termination to occur, unless the -signal -.Dv SIGABRT -is being caught and the signal handler does not return. -.Pp -Any open streams are flushed and closed. -.Sh IMPLEMENTATION NOTES -The -.Fn abort -function is thread-safe. -It is unknown if it is async-cancel-safe. -.Sh RETURN VALUES -The -.Fn abort -function -never returns. -.Sh SEE ALSO -.Xr sigaction 2 , -.Xr exit 3 -.Sh STANDARDS -The -.Fn abort -function -conforms to -.St -p1003.1-90 . -The -.Fn abort -function also conforms to -.St -isoC-99 -with the implementation specific details as noted above. diff --git a/lib/libc/stdlib/abort.c b/lib/libc/stdlib/abort.c deleted file mode 100644 index eba53e5..0000000 --- a/lib/libc/stdlib/abort.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 1985, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)abort.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include "namespace.h" -#include <signal.h> -#include <stdlib.h> -#include <stddef.h> -#include <unistd.h> -#include <pthread.h> -#include "un-namespace.h" - -#include "libc_private.h" - -void -abort() -{ - struct sigaction act; - - /* - * POSIX requires we flush stdio buffers on abort. - * XXX ISO C requires that abort() be async-signal-safe. - */ - if (__cleanup) - (*__cleanup)(); - - sigfillset(&act.sa_mask); - /* - * Don't block SIGABRT to give any handler a chance; we ignore - * any errors -- ISO C doesn't allow abort to return anyway. - */ - sigdelset(&act.sa_mask, SIGABRT); - (void)_sigprocmask(SIG_SETMASK, &act.sa_mask, NULL); - (void)raise(SIGABRT); - - /* - * If SIGABRT was ignored, or caught and the handler returns, do - * it again, only harder. - */ - act.sa_handler = SIG_DFL; - act.sa_flags = 0; - sigfillset(&act.sa_mask); - (void)_sigaction(SIGABRT, &act, NULL); - sigdelset(&act.sa_mask, SIGABRT); - (void)_sigprocmask(SIG_SETMASK, &act.sa_mask, NULL); - (void)raise(SIGABRT); - exit(1); -} diff --git a/lib/libc/stdlib/abs.3 b/lib/libc/stdlib/abs.3 deleted file mode 100644 index 4f02122..0000000 --- a/lib/libc/stdlib/abs.3 +++ /dev/null @@ -1,75 +0,0 @@ -.\" Copyright (c) 1990, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the American National Standards Committee X3, on Information -.\" Processing Systems. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)abs.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD$ -.\" -.Dd November 14, 2001 -.Dt ABS 3 -.Os -.Sh NAME -.Nm abs -.Nd integer absolute value function -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In stdlib.h -.Ft int -.Fn abs "int j" -.Sh DESCRIPTION -The -.Fn abs -function -computes -the absolute value of the integer -.Fa j . -.Sh RETURN VALUES -The -.Fn abs -function -returns -the absolute value. -.Sh SEE ALSO -.Xr cabs 3 , -.Xr fabs 3 , -.Xr floor 3 , -.Xr hypot 3 , -.Xr imaxabs 3 , -.Xr labs 3 , -.Xr llabs 3 , -.Xr math 3 -.Sh STANDARDS -The -.Fn abs -function conforms to -.St -isoC-99 . -.Sh BUGS -The absolute value of the most negative integer remains negative. diff --git a/lib/libc/stdlib/abs.c b/lib/libc/stdlib/abs.c deleted file mode 100644 index 5ca9596..0000000 --- a/lib/libc/stdlib/abs.c +++ /dev/null @@ -1,43 +0,0 @@ -/*- - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)abs.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stdlib.h> - -int -abs(j) - int j; -{ - return(j < 0 ? -j : j); -} diff --git a/lib/libc/stdlib/alloca.3 b/lib/libc/stdlib/alloca.3 deleted file mode 100644 index 9559444..0000000 --- a/lib/libc/stdlib/alloca.3 +++ /dev/null @@ -1,88 +0,0 @@ -.\" Copyright (c) 1980, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)alloca.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD$ -.\" -.Dd September 5, 2006 -.Dt ALLOCA 3 -.Os -.Sh NAME -.Nm alloca -.Nd memory allocator -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In stdlib.h -.Ft void * -.Fn alloca "size_t size" -.Sh DESCRIPTION -The -.Fn alloca -function -allocates -.Fa size -bytes of space in the stack frame of the caller. -This temporary space is automatically freed on -return. -.Sh RETURN VALUES -The -.Fn alloca -function returns a pointer to the beginning of the allocated space. -.Sh SEE ALSO -.Xr brk 2 , -.Xr calloc 3 , -.Xr getpagesize 3 , -.Xr malloc 3 , -.Xr realloc 3 -.Sh HISTORY -The -.Fn alloca -function appeared in -.At 32v . -.\" .Bx ?? . -.\" The function appeared in 32v, pwb and pwb.2 and in 3bsd 4bsd -.\" The first man page (or link to a man page that I can find at the -.\" moment is 4.3... -.Sh BUGS -The -.Fn alloca -function -is machine and compiler dependent; -its use is discouraged. -.Pp -The -.Fn alloca -function is slightly unsafe because it cannot ensure that the pointer -returned points to a valid and usable block of memory. -The allocation made may exceed the bounds of the stack, or even go -further into other objects in memory, and -.Fn alloca -cannot determine such an error. -Avoid -.Fn alloca -with large unbounded allocations. diff --git a/lib/libc/stdlib/atexit.3 b/lib/libc/stdlib/atexit.3 deleted file mode 100644 index 3c44b8d..0000000 --- a/lib/libc/stdlib/atexit.3 +++ /dev/null @@ -1,88 +0,0 @@ -.\" Copyright (c) 1990, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" Chris Torek and the American National Standards Committee X3, -.\" on Information Processing Systems. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)atexit.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD$ -.\" -.Dd September 6, 2002 -.Dt ATEXIT 3 -.Os -.Sh NAME -.Nm atexit -.Nd register a function to be called on exit -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In stdlib.h -.Ft int -.Fn atexit "void (*function)(void)" -.Sh DESCRIPTION -The -.Fn atexit -function -registers the given -.Fa function -to be called at program exit, whether via -.Xr exit 3 -or via return from the program's -.Fn main . -Functions so registered are called in reverse order; -no arguments are passed. -.Pp -These functions must not call -.Fn exit ; -if it should be necessary to terminate the process while in such a -function, the -.Xr _exit 2 -function should be used. -(Alternatively, the function may cause abnormal -process termination, for example by calling -.Xr abort 3 . ) -.Pp -At least 32 functions can always be registered, -and more are allowed as long as sufficient memory can be allocated. -.\" XXX {ATEXIT_MAX} is not implemented yet -.Sh RETURN VALUES -.Rv -std atexit -.Sh ERRORS -.Bl -tag -width Er -.It Bq Er ENOMEM -No memory was available to add the function to the list. -The existing list of functions is unmodified. -.El -.Sh SEE ALSO -.Xr exit 3 -.Sh STANDARDS -The -.Fn atexit -function -conforms to -.St -isoC . diff --git a/lib/libc/stdlib/atexit.c b/lib/libc/stdlib/atexit.c deleted file mode 100644 index 511172a..0000000 --- a/lib/libc/stdlib/atexit.c +++ /dev/null @@ -1,205 +0,0 @@ -/*- - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Chris Torek. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)atexit.c 8.2 (Berkeley) 7/3/94"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include "namespace.h" -#include <link.h> -#include <stddef.h> -#include <stdlib.h> -#include <unistd.h> -#include <pthread.h> -#include "atexit.h" -#include "un-namespace.h" - -#include "libc_private.h" - -#define ATEXIT_FN_EMPTY 0 -#define ATEXIT_FN_STD 1 -#define ATEXIT_FN_CXA 2 - -static pthread_mutex_t atexit_mutex = PTHREAD_MUTEX_INITIALIZER; - -#define _MUTEX_LOCK(x) if (__isthreaded) _pthread_mutex_lock(x) -#define _MUTEX_UNLOCK(x) if (__isthreaded) _pthread_mutex_unlock(x) -#define _MUTEX_DESTROY(x) if (__isthreaded) _pthread_mutex_destroy(x) - -struct atexit { - struct atexit *next; /* next in list */ - int ind; /* next index in this table */ - struct atexit_fn { - int fn_type; /* ATEXIT_? from above */ - union { - void (*std_func)(void); - void (*cxa_func)(void *); - } fn_ptr; /* function pointer */ - void *fn_arg; /* argument for CXA callback */ - void *fn_dso; /* shared module handle */ - } fns[ATEXIT_SIZE]; /* the table itself */ -}; - -static struct atexit *__atexit; /* points to head of LIFO stack */ - -/* - * Register the function described by 'fptr' to be called at application - * exit or owning shared object unload time. This is a helper function - * for atexit and __cxa_atexit. - */ -static int -atexit_register(struct atexit_fn *fptr) -{ - static struct atexit __atexit0; /* one guaranteed table */ - struct atexit *p; - - _MUTEX_LOCK(&atexit_mutex); - if ((p = __atexit) == NULL) - __atexit = p = &__atexit0; - else while (p->ind >= ATEXIT_SIZE) { - struct atexit *old__atexit; - old__atexit = __atexit; - _MUTEX_UNLOCK(&atexit_mutex); - if ((p = (struct atexit *)malloc(sizeof(*p))) == NULL) - return (-1); - _MUTEX_LOCK(&atexit_mutex); - if (old__atexit != __atexit) { - /* Lost race, retry operation */ - _MUTEX_UNLOCK(&atexit_mutex); - free(p); - _MUTEX_LOCK(&atexit_mutex); - p = __atexit; - continue; - } - p->ind = 0; - p->next = __atexit; - __atexit = p; - } - p->fns[p->ind++] = *fptr; - _MUTEX_UNLOCK(&atexit_mutex); - return 0; -} - -/* - * Register a function to be performed at exit. - */ -int -atexit(void (*func)(void)) -{ - struct atexit_fn fn; - int error; - - fn.fn_type = ATEXIT_FN_STD; - fn.fn_ptr.std_func = func; - fn.fn_arg = NULL; - fn.fn_dso = NULL; - - error = atexit_register(&fn); - return (error); -} - -/* - * Register a function to be performed at exit or when an shared object - * with given dso handle is unloaded dynamically. - */ -int -__cxa_atexit(void (*func)(void *), void *arg, void *dso) -{ - struct atexit_fn fn; - int error; - - fn.fn_type = ATEXIT_FN_CXA; - fn.fn_ptr.cxa_func = func; - fn.fn_arg = arg; - fn.fn_dso = dso; - - error = atexit_register(&fn); - return (error); -} - -#pragma weak __pthread_cxa_finalize -void __pthread_cxa_finalize(const struct dl_phdr_info *); - -/* - * Call all handlers registered with __cxa_atexit for the shared - * object owning 'dso'. Note: if 'dso' is NULL, then all remaining - * handlers are called. - */ -void -__cxa_finalize(void *dso) -{ - struct dl_phdr_info phdr_info; - struct atexit *p; - struct atexit_fn fn; - int n, has_phdr; - - if (dso != NULL) - has_phdr = _rtld_addr_phdr(dso, &phdr_info); - else - has_phdr = 0; - - _MUTEX_LOCK(&atexit_mutex); - for (p = __atexit; p; p = p->next) { - for (n = p->ind; --n >= 0;) { - if (p->fns[n].fn_type == ATEXIT_FN_EMPTY) - continue; /* already been called */ - fn = p->fns[n]; - if (dso != NULL && dso != fn.fn_dso) { - /* wrong DSO ? */ - if (!has_phdr || !__elf_phdr_match_addr( - &phdr_info, fn.fn_ptr.cxa_func)) - continue; - } - /* - Mark entry to indicate that this particular handler - has already been called. - */ - p->fns[n].fn_type = ATEXIT_FN_EMPTY; - _MUTEX_UNLOCK(&atexit_mutex); - - /* Call the function of correct type. */ - if (fn.fn_type == ATEXIT_FN_CXA) - fn.fn_ptr.cxa_func(fn.fn_arg); - else if (fn.fn_type == ATEXIT_FN_STD) - fn.fn_ptr.std_func(); - _MUTEX_LOCK(&atexit_mutex); - } - } - _MUTEX_UNLOCK(&atexit_mutex); - if (dso == NULL) - _MUTEX_DESTROY(&atexit_mutex); - - if (has_phdr && &__pthread_cxa_finalize != NULL) - __pthread_cxa_finalize(&phdr_info); -} diff --git a/lib/libc/stdlib/atexit.h b/lib/libc/stdlib/atexit.h deleted file mode 100644 index f34194f..0000000 --- a/lib/libc/stdlib/atexit.h +++ /dev/null @@ -1,36 +0,0 @@ -/*- - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)atexit.h 8.2 (Berkeley) 7/3/94 - * $FreeBSD$ - */ - -/* must be at least 32 to guarantee ANSI conformance */ -#define ATEXIT_SIZE 32 - -void __cxa_finalize(void *dso); diff --git a/lib/libc/stdlib/atof.3 b/lib/libc/stdlib/atof.3 deleted file mode 100644 index abf5b7c..0000000 --- a/lib/libc/stdlib/atof.3 +++ /dev/null @@ -1,95 +0,0 @@ -.\" Copyright (c) 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the American National Standards Committee X3, on Information -.\" Processing Systems. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)atof.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD$ -.\" -.Dd June 4, 1993 -.Dt ATOF 3 -.Os -.Sh NAME -.Nm atof -.Nd convert -.Tn ASCII -string to double -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In stdlib.h -.Ft double -.Fn atof "const char *nptr" -.Sh DESCRIPTION -The -.Fn atof -function converts the initial portion of the string pointed to by -.Fa nptr -to -.Vt double -representation. -.Pp -It is equivalent to: -.Bd -literal -offset indent -strtod(nptr, (char **)NULL); -.Ed -.Pp -The decimal point -character is defined in the program's locale (category -.Dv LC_NUMERIC ) . -.Sh IMPLEMENTATION NOTES -The -.Fn atof -function is not thread-safe and also not async-cancel-safe. -.Pp -The -.Fn atof -function has been deprecated by -.Fn strtod -and should not be used in new code. -.Sh ERRORS -The function -.Fn atof -need not affect the value of -.Va errno -on an error. -.Sh SEE ALSO -.Xr atoi 3 , -.Xr atol 3 , -.Xr strtod 3 , -.Xr strtol 3 , -.Xr strtoul 3 -.Sh STANDARDS -The -.Fn atof -function conforms to -.St -p1003.1-90 , -.St -isoC , -and -.St -isoC-99 . diff --git a/lib/libc/stdlib/atof.c b/lib/libc/stdlib/atof.c deleted file mode 100644 index 51e482e..0000000 --- a/lib/libc/stdlib/atof.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)atof.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stdlib.h> - -double -atof(ascii) - const char *ascii; -{ - return strtod(ascii, (char **)NULL); -} diff --git a/lib/libc/stdlib/atoi.3 b/lib/libc/stdlib/atoi.3 deleted file mode 100644 index b0d1d38..0000000 --- a/lib/libc/stdlib/atoi.3 +++ /dev/null @@ -1,87 +0,0 @@ -.\" Copyright (c) 1990, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the American National Standards Committee X3, on Information -.\" Processing Systems. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)atoi.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD$ -.\" -.Dd June 4, 1993 -.Dt ATOI 3 -.Os -.Sh NAME -.Nm atoi -.Nd convert -.Tn ASCII -string to integer -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In stdlib.h -.Ft int -.Fn atoi "const char *nptr" -.Sh DESCRIPTION -The -.Fn atoi -function converts the initial portion of the string pointed to by -.Fa nptr -to -.Vt int -representation. -.Pp -It is equivalent to: -.Bd -literal -offset indent -(int)strtol(nptr, (char **)NULL, 10); -.Ed -.Pp -The -.Fn atoi -function has been deprecated by -.Fn strtol -and should not be used in new code. -.Sh ERRORS -The function -.Fn atoi -need not affect the value of -.Va errno -on an error. -.Sh SEE ALSO -.Xr atof 3 , -.Xr atol 3 , -.Xr strtod 3 , -.Xr strtol 3 , -.Xr strtoul 3 -.Sh STANDARDS -The -.Fn atoi -function conforms to -.St -p1003.1-90 , -.St -isoC , -and -.St -isoC-99 . diff --git a/lib/libc/stdlib/atoi.c b/lib/libc/stdlib/atoi.c deleted file mode 100644 index 0ffcd03..0000000 --- a/lib/libc/stdlib/atoi.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)atoi.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stdlib.h> - -int -atoi(str) - const char *str; -{ - return (int)strtol(str, (char **)NULL, 10); -} diff --git a/lib/libc/stdlib/atol.3 b/lib/libc/stdlib/atol.3 deleted file mode 100644 index cc49fe2..0000000 --- a/lib/libc/stdlib/atol.3 +++ /dev/null @@ -1,135 +0,0 @@ -.\" Copyright (c) 1990, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the American National Standards Committee X3, on Information -.\" Processing Systems. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)atol.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD$ -.\" -.Dd February 1, 2009 -.Dt ATOL 3 -.Os -.Sh NAME -.Nm atol , atoll -.Nd convert -.Tn ASCII -string to -.Vt long -or -.Vt "long long" -integer -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In stdlib.h -.Ft long -.Fn atol "const char *nptr" -.Ft "long long" -.Fn atoll "const char *nptr" -.Sh DESCRIPTION -The -.Fn atol -function converts the initial portion of the string pointed to by -.Fa nptr -to -.Vt long -integer -representation. -.Pp -It is equivalent to: -.Pp -.Dl "strtol(nptr, (char **)NULL, 10);" -.Pp -The -.Fn atoll -function converts the initial portion of the string pointed to by -.Fa nptr -to -.Vt "long long" -integer -representation. -.Pp -It is equivalent to: -.Pp -.Dl "strtoll(nptr, (char **)NULL, 10);" -.Sh COMPATIBILITY -The -.Fx -implementations of the -.Fn atol -and -.Fn atoll -functions are thin wrappers around -.Fn strtol -and -.Fn stroll -respectively, so these functions will affect the value of -.Va errno -in the same way that the -.Fn strtol -and -.Fn stroll -functions are able to. -This behavior of -.Fn atol -and -.Fn atoll -is not required by -.St -isoC -or -.St -isoC-99 , -but it is allowed by all of -.St -isoC , St -isoC-99 -and -.St -p1003.1-2001 . -.Sh ERRORS -The functions -.Fn atol -and -.Fn atoll -may affect the value of -.Va errno -on an error. -.Sh SEE ALSO -.Xr atof 3 , -.Xr atoi 3 , -.Xr strtod 3 , -.Xr strtol 3 , -.Xr strtoul 3 -.Sh STANDARDS -The -.Fn atol -function -conforms to -.St -isoC . -The -.Fn atoll -function -conforms to -.St -isoC-99 . diff --git a/lib/libc/stdlib/atol.c b/lib/libc/stdlib/atol.c deleted file mode 100644 index c9cf2e8..0000000 --- a/lib/libc/stdlib/atol.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)atol.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stdlib.h> - -long -atol(str) - const char *str; -{ - return strtol(str, (char **)NULL, 10); -} diff --git a/lib/libc/stdlib/atoll.c b/lib/libc/stdlib/atoll.c deleted file mode 100644 index 203c174..0000000 --- a/lib/libc/stdlib/atoll.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stdlib.h> - -long long -atoll(str) - const char *str; -{ - return strtoll(str, (char **)NULL, 10); -} diff --git a/lib/libc/stdlib/bsearch.3 b/lib/libc/stdlib/bsearch.3 deleted file mode 100644 index b3591f8e..0000000 --- a/lib/libc/stdlib/bsearch.3 +++ /dev/null @@ -1,89 +0,0 @@ -.\" Copyright (c) 1990, 1991, 1993, 1994 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the American National Standards Committee X3, on Information -.\" Processing Systems. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)bsearch.3 8.3 (Berkeley) 4/19/94 -.\" $FreeBSD$ -.\" -.Dd April 19, 1994 -.Dt BSEARCH 3 -.Os -.Sh NAME -.Nm bsearch -.Nd binary search of a sorted table -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In stdlib.h -.Ft void * -.Fn bsearch "const void *key" "const void *base" "size_t nmemb" "size_t size" "int (*compar) (const void *, const void *)" -.Sh DESCRIPTION -The -.Fn bsearch -function searches an array of -.Fa nmemb -objects, the initial member of which is -pointed to by -.Fa base , -for a member that matches the object pointed to by -.Fa key . -The size of each member of the array is specified by -.Fa size . -.Pp -The contents of the array should be in ascending sorted order according -to the comparison function referenced by -.Fa compar . -The -.Fa compar -routine -is expected to have -two arguments which point to the -.Fa key -object and to an array member, in that order, and should return an integer -less than, equal to, or greater than zero if the -.Fa key -object is found, respectively, to be less than, to match, or be -greater than the array member. -.Sh RETURN VALUES -The -.Fn bsearch -function returns a pointer to a matching member of the array, or a null -pointer if no match is found. -If two members compare as equal, which member is matched is unspecified. -.Sh SEE ALSO -.Xr db 3 , -.Xr lsearch 3 , -.Xr qsort 3 -.\" .Xr tsearch 3 -.Sh STANDARDS -The -.Fn bsearch -function conforms to -.St -isoC . diff --git a/lib/libc/stdlib/bsearch.c b/lib/libc/stdlib/bsearch.c deleted file mode 100644 index ff02168..0000000 --- a/lib/libc/stdlib/bsearch.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)bsearch.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stddef.h> -#include <stdlib.h> - -/* - * Perform a binary search. - * - * The code below is a bit sneaky. After a comparison fails, we - * divide the work in half by moving either left or right. If lim - * is odd, moving left simply involves halving lim: e.g., when lim - * is 5 we look at item 2, so we change lim to 2 so that we will - * look at items 0 & 1. If lim is even, the same applies. If lim - * is odd, moving right again involes halving lim, this time moving - * the base up one item past p: e.g., when lim is 5 we change base - * to item 3 and make lim 2 so that we will look at items 3 and 4. - * If lim is even, however, we have to shrink it by one before - * halving: e.g., when lim is 4, we still looked at item 2, so we - * have to make lim 3, then halve, obtaining 1, so that we will only - * look at item 3. - */ -void * -bsearch(key, base0, nmemb, size, compar) - const void *key; - const void *base0; - size_t nmemb; - size_t size; - int (*compar)(const void *, const void *); -{ - const char *base = base0; - size_t lim; - int cmp; - const void *p; - - for (lim = nmemb; lim != 0; lim >>= 1) { - p = base + (lim >> 1) * size; - cmp = (*compar)(key, p); - if (cmp == 0) - return ((void *)p); - if (cmp > 0) { /* key > p: move right */ - base = (char *)p + size; - lim--; - } /* else move left */ - } - return (NULL); -} diff --git a/lib/libc/stdlib/div.3 b/lib/libc/stdlib/div.3 deleted file mode 100644 index 46a145f..0000000 --- a/lib/libc/stdlib/div.3 +++ /dev/null @@ -1,68 +0,0 @@ -.\" Copyright (c) 1990, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" Chris Torek. -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)div.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD$ -.\" -.Dd November 14, 2001 -.Dt DIV 3 -.Os -.Sh NAME -.Nm div -.Nd return quotient and remainder from division -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In stdlib.h -.Ft div_t -.Fn div "int num" "int denom" -.Sh DESCRIPTION -The -.Fn div -function -computes the value -.Fa num/denom -and returns the quotient and remainder in a structure named -.Fa div_t -that contains two -.Vt int -members named -.Va quot -and -.Va rem . -.Sh SEE ALSO -.Xr imaxdiv 3 , -.Xr ldiv 3 , -.Xr lldiv 3 -.Sh STANDARDS -The -.Fn div -function -conforms to -.St -isoC-99 . diff --git a/lib/libc/stdlib/div.c b/lib/libc/stdlib/div.c deleted file mode 100644 index ef93d73..0000000 --- a/lib/libc/stdlib/div.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Chris Torek. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)div.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stdlib.h> /* div_t */ - -div_t -div(num, denom) - int num, denom; -{ - div_t r; - - r.quot = num / denom; - r.rem = num % denom; - /* - * The ANSI standard says that |r.quot| <= |n/d|, where - * n/d is to be computed in infinite precision. In other - * words, we should always truncate the quotient towards - * 0, never -infinity. - * - * Machine division and remainer may work either way when - * one or both of n or d is negative. If only one is - * negative and r.quot has been truncated towards -inf, - * r.rem will have the same sign as denom and the opposite - * sign of num; if both are negative and r.quot has been - * truncated towards -inf, r.rem will be positive (will - * have the opposite sign of num). These are considered - * `wrong'. - * - * If both are num and denom are positive, r will always - * be positive. - * - * This all boils down to: - * if num >= 0, but r.rem < 0, we got the wrong answer. - * In that case, to get the right answer, add 1 to r.quot and - * subtract denom from r.rem. - */ - if (num >= 0 && r.rem < 0) { - r.quot++; - r.rem -= denom; - } - return (r); -} diff --git a/lib/libc/stdlib/exit.3 b/lib/libc/stdlib/exit.3 deleted file mode 100644 index a864ccb..0000000 --- a/lib/libc/stdlib/exit.3 +++ /dev/null @@ -1,130 +0,0 @@ -.\" Copyright (c) 1990, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the American National Standards Committee X3, on Information -.\" Processing Systems. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)exit.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD$ -.\" -.Dd September 9, 2002 -.Dt EXIT 3 -.Os -.Sh NAME -.Nm exit , _Exit -.Nd perform normal program termination -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In stdlib.h -.Ft void -.Fn exit "int status" -.Ft void -.Fn _Exit "int status" -.Sh DESCRIPTION -The -.Fn exit -and -.Fn _Exit -functions terminate a process. -.Pp -Before termination, -.Fn exit -performs the following functions in the order listed: -.Bl -enum -offset indent -.It -Call the functions registered with the -.Xr atexit 3 -function, in the reverse order of their registration. -.It -Flush all open output streams. -.It -Close all open streams. -.It -Unlink all files created with the -.Xr tmpfile 3 -function. -.El -.Pp -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-99 -defines the values -.Li 0 , -.Dv EXIT_SUCCESS , -and -.Dv EXIT_FAILURE -as possible values of -.Fa status . -Cooperating processes may use other values; -in a program which might be called by a mail transfer agent, the -values described in -.Xr sysexits 3 -may be used to provide more information to the parent process. -.Pp -Note that -.Fn exit -does nothing to prevent bottomless recursion should a function registered -using -.Xr atexit 3 -itself call -.Fn exit . -Such functions must call -.Fn _Exit -instead (although this has other effects as well which may not be desired). -.Sh RETURN VALUES -The -.Fn exit -and -.Fn _Exit -functions -never return. -.Sh SEE ALSO -.Xr _exit 2 , -.Xr wait 2 , -.Xr atexit 3 , -.Xr intro 3 , -.Xr sysexits 3 , -.Xr tmpfile 3 -.Sh STANDARDS -The -.Fn exit -and -.Fn _Exit -functions conform to -.St -isoC-99 . diff --git a/lib/libc/stdlib/exit.c b/lib/libc/stdlib/exit.c deleted file mode 100644 index 26c346a..0000000 --- a/lib/libc/stdlib/exit.c +++ /dev/null @@ -1,71 +0,0 @@ -/*- - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)exit.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include "namespace.h" -#include <stdlib.h> -#include <unistd.h> -#include "un-namespace.h" - -#include "atexit.h" -#include "libc_private.h" - -void (*__cleanup)(void); - -/* - * This variable is zero until a process has created a thread. - * It is used to avoid calling locking functions in libc when they - * are not required. By default, libc is intended to be(come) - * thread-safe, but without a (significant) penalty to non-threaded - * processes. - */ -int __isthreaded = 0; - -/* - * Exit, flushing stdio buffers if necessary. - */ -void -exit(status) - int status; -{ - /* Ensure that the auto-initialization routine is linked in: */ - extern int _thread_autoinit_dummy_decl; - - _thread_autoinit_dummy_decl = 1; - - __cxa_finalize(NULL); - if (__cleanup) - (*__cleanup)(); - _exit(status); -} diff --git a/lib/libc/stdlib/getenv.3 b/lib/libc/stdlib/getenv.3 deleted file mode 100644 index fd7d856..0000000 --- a/lib/libc/stdlib/getenv.3 +++ /dev/null @@ -1,229 +0,0 @@ -.\" Copyright (c) 1988, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the American National Standards Committee X3, on Information -.\" Processing Systems. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)getenv.3 8.2 (Berkeley) 12/11/93 -.\" $FreeBSD$ -.\" -.Dd June 20, 2007 -.Dt GETENV 3 -.Os -.Sh NAME -.Nm getenv , -.Nm putenv , -.Nm setenv , -.Nm unsetenv -.Nd environment variable functions -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In stdlib.h -.Ft char * -.Fn getenv "const char *name" -.Ft int -.Fn setenv "const char *name" "const char *value" "int overwrite" -.Ft int -.Fn putenv "char *string" -.Ft int -.Fn unsetenv "const char *name" -.Sh DESCRIPTION -These functions set, unset and fetch environment variables from the -host -.Em environment list . -.Pp -The -.Fn getenv -function obtains the current value of the environment variable, -.Fa name . -The application should not modify the string pointed -to by the -.Fn getenv -function. -.Pp -The -.Fn setenv -function inserts or resets the environment variable -.Fa name -in the current environment list. -If the variable -.Fa name -does not exist in the list, -it is inserted with the given -.Fa value . -If the variable does exist, the argument -.Fa overwrite -is tested; if -.Fa overwrite -is zero, the -variable is not reset, otherwise it is reset -to the given -.Fa value . -.Pp -The -.Fn putenv -function takes an argument of the form ``name=value'' and -puts it directly into the current environment, -so altering the argument shall change the environment. -If the variable -.Fa name -does not exist in the list, -it is inserted with the given -.Fa value . -If the variable -.Fa name -does exist, it is reset to the given -.Fa value . -.Pp -The -.Fn unsetenv -function -deletes all instances of the variable name pointed to by -.Fa name -from the list. -.Pp -If corruption (e.g., a name without a value) is detected while making a copy of -environ for internal usage, then -.Fn setenv , -.Fn unsetenv -and -.Fn putenv -will output a warning to stderr about the issue, drop the corrupt entry and -complete the task without error. -.Sh RETURN VALUES -The -.Fn getenv -function returns the value of the environment variable as a -.Dv NUL Ns --terminated string. -If the variable -.Fa name -is not in the current environment, -.Dv NULL -is returned. -.Pp -.Rv -std setenv putenv unsetenv -.Sh ERRORS -.Bl -tag -width Er -.It Bq Er EINVAL -The function -.Fn getenv , -.Fn setenv -or -.Fn unsetenv -failed because the -.Fa name -is a -.Dv NULL -pointer, points to an empty string, or points to a string containing an -.Dq Li \&= -character. -.Pp -The function -.Fn putenv -failed because -.Fa string -is a -.Dv NULL -pointer, -.Fa string is without an -.Dq Li \&= -character or -.Dq Li \&= -is the first character in -.Fa string . -This does not follow the -.Tn POSIX -specification. -.It Bq Er ENOMEM -The function -.Fn setenv , -.Fn unsetenv -or -.Fn putenv -failed because they were unable to allocate memory for the environment. -.El -.Sh SEE ALSO -.Xr csh 1 , -.Xr sh 1 , -.Xr execve 2 , -.Xr environ 7 -.Sh STANDARDS -The -.Fn getenv -function conforms to -.St -isoC . -The -.Fn setenv , -.Fn putenv -and -.Fn unsetenv -functions conforms to -.St -p1003.1-2001 . -.Sh HISTORY -The functions -.Fn setenv -and -.Fn unsetenv -appeared in -.At v7 . -The -.Fn putenv -function appeared in -.Bx 4.3 Reno . -.Pp -Until -.Fx 7.0 , -.Fn putenv -would make a copy of -.Fa string -and insert it into the environment using -.Fn setenv . -This was changed to use -.Fa string -as the memory location of the ``name=value'' pair to follow the -.Tn POSIX -specification. -.Sh BUGS -Successive calls to -.Fn setenv -that assign a larger-sized -.Fa value -than any previous value to the same -.Fa name -will result in a memory leak. -The -.Fx -semantics for this function -(namely, that the contents of -.Fa value -are copied and that old values remain accessible indefinitely) make this -bug unavoidable. -Future versions may eliminate one or both of these -semantic guarantees in order to fix the bug. diff --git a/lib/libc/stdlib/getenv.c b/lib/libc/stdlib/getenv.c deleted file mode 100644 index b7826d7..0000000 --- a/lib/libc/stdlib/getenv.c +++ /dev/null @@ -1,686 +0,0 @@ -/*- - * Copyright (c) 2007-2009 Sean C. Farley <scf@FreeBSD.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification, immediately at the beginning of the file. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - - -#include "namespace.h" -#include <sys/types.h> -#include <errno.h> -#include <stdbool.h> -#include <stddef.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include "un-namespace.h" - - -static const char CorruptEnvFindMsg[] = "environment corrupt; unable to find "; -static const char CorruptEnvValueMsg[] = - "environment corrupt; missing value for "; - - -/* - * Standard environ. environ variable is exposed to entire process. - * - * origEnviron: Upon cleanup on unloading of library or failure, this - * allows environ to return to as it was before. - * environSize: Number of variables environ can hold. Can only - * increase. - * intEnviron: Internally-built environ. Exposed via environ during - * (re)builds of the environment. - */ -extern char **environ; -static char **origEnviron; -static char **intEnviron = NULL; -static int environSize = 0; - -/* - * Array of environment variables built from environ. Each element records: - * name: Pointer to name=value string - * name length: Length of name not counting '=' character - * value: Pointer to value within same string as name - * value size: Size (not length) of space for value not counting the - * nul character - * active state: true/false value to signify whether variable is active. - * Useful since multiple variables with the same name can - * co-exist. At most, one variable can be active at any - * one time. - * putenv: Created from putenv() call. This memory must not be - * reused. - */ -static struct envVars { - size_t nameLen; - size_t valueSize; - char *name; - char *value; - bool active; - bool putenv; -} *envVars = NULL; - -/* - * Environment array information. - * - * envActive: Number of active variables in array. - * envVarsSize: Size of array. - * envVarsTotal: Number of total variables in array (active or not). - */ -static int envActive = 0; -static int envVarsSize = 0; -static int envVarsTotal = 0; - - -/* Deinitialization of new environment. */ -static void __attribute__ ((destructor)) __clean_env_destructor(void); - - -/* - * A simple version of warnx() to avoid the bloat of including stdio in static - * binaries. - */ -static void -__env_warnx(const char *msg, const char *name, size_t nameLen) -{ - static const char nl[] = "\n"; - static const char progSep[] = ": "; - - _write(STDERR_FILENO, _getprogname(), strlen(_getprogname())); - _write(STDERR_FILENO, progSep, sizeof(progSep) - 1); - _write(STDERR_FILENO, msg, strlen(msg)); - _write(STDERR_FILENO, name, nameLen); - _write(STDERR_FILENO, nl, sizeof(nl) - 1); - - return; -} - - -/* - * Inline strlen() for performance. Also, perform check for an equals sign. - * Cheaper here than peforming a strchr() later. - */ -static inline size_t -__strleneq(const char *str) -{ - const char *s; - - for (s = str; *s != '\0'; ++s) - if (*s == '=') - return (0); - - return (s - str); -} - - -/* - * Comparison of an environment name=value to a name. - */ -static inline bool -strncmpeq(const char *nameValue, const char *name, size_t nameLen) -{ - if (strncmp(nameValue, name, nameLen) == 0 && nameValue[nameLen] == '=') - return (true); - - return (false); -} - - -/* - * Using environment, returns pointer to value associated with name, if any, - * else NULL. If the onlyActive flag is set to true, only variables that are - * active are returned else all are. - */ -static inline char * -__findenv(const char *name, size_t nameLen, int *envNdx, bool onlyActive) -{ - int ndx; - - /* - * Find environment variable from end of array (more likely to be - * active). A variable created by putenv is always active, or it is not - * tracked in the array. - */ - for (ndx = *envNdx; ndx >= 0; ndx--) - if (envVars[ndx].putenv) { - if (strncmpeq(envVars[ndx].name, name, nameLen)) { - *envNdx = ndx; - return (envVars[ndx].name + nameLen + - sizeof ("=") - 1); - } - } else if ((!onlyActive || envVars[ndx].active) && - (envVars[ndx].nameLen == nameLen && - strncmpeq(envVars[ndx].name, name, nameLen))) { - *envNdx = ndx; - return (envVars[ndx].value); - } - - return (NULL); -} - - -/* - * Using environ, returns pointer to value associated with name, if any, else - * NULL. Used on the original environ passed into the program. - */ -static char * -__findenv_environ(const char *name, size_t nameLen) -{ - int envNdx; - - /* Find variable within environ. */ - for (envNdx = 0; environ[envNdx] != NULL; envNdx++) - if (strncmpeq(environ[envNdx], name, nameLen)) - return (&(environ[envNdx][nameLen + sizeof("=") - 1])); - - return (NULL); -} - - -/* - * Remove variable added by putenv() from variable tracking array. - */ -static void -__remove_putenv(int envNdx) -{ - envVarsTotal--; - if (envVarsTotal > envNdx) - memmove(&(envVars[envNdx]), &(envVars[envNdx + 1]), - (envVarsTotal - envNdx) * sizeof (*envVars)); - memset(&(envVars[envVarsTotal]), 0, sizeof (*envVars)); - - return; -} - - -/* - * Deallocate the environment built from environ as well as environ then set - * both to NULL. Eases debugging of memory leaks. - */ -static void -__clean_env(bool freeVars) -{ - int envNdx; - - /* Deallocate environment and environ if created by *env(). */ - if (envVars != NULL) { - for (envNdx = envVarsTotal - 1; envNdx >= 0; envNdx--) - /* Free variables or deactivate them. */ - if (envVars[envNdx].putenv) { - if (!freeVars) - __remove_putenv(envNdx); - } else { - if (freeVars) - free(envVars[envNdx].name); - else - envVars[envNdx].active = false; - } - if (freeVars) { - free(envVars); - envVars = NULL; - } else - envActive = 0; - - /* Restore original environ if it has not updated by program. */ - if (origEnviron != NULL) { - if (environ == intEnviron) - environ = origEnviron; - free(intEnviron); - intEnviron = NULL; - environSize = 0; - } - } - - return; -} - - -/* - * Using the environment, rebuild the environ array for use by other C library - * calls that depend upon it. - */ -static int -__rebuild_environ(int newEnvironSize) -{ - char **tmpEnviron; - int envNdx; - int environNdx; - int tmpEnvironSize; - - /* Resize environ. */ - if (newEnvironSize > environSize) { - tmpEnvironSize = newEnvironSize * 2; - tmpEnviron = realloc(intEnviron, sizeof (*intEnviron) * - (tmpEnvironSize + 1)); - if (tmpEnviron == NULL) - return (-1); - environSize = tmpEnvironSize; - intEnviron = tmpEnviron; - } - envActive = newEnvironSize; - - /* Assign active variables to environ. */ - for (envNdx = envVarsTotal - 1, environNdx = 0; envNdx >= 0; envNdx--) - if (envVars[envNdx].active) - intEnviron[environNdx++] = envVars[envNdx].name; - intEnviron[environNdx] = NULL; - - /* Always set environ which may have been replaced by program. */ - environ = intEnviron; - - return (0); -} - - -/* - * Enlarge new environment. - */ -static inline bool -__enlarge_env(void) -{ - int newEnvVarsSize; - struct envVars *tmpEnvVars; - - envVarsTotal++; - if (envVarsTotal > envVarsSize) { - newEnvVarsSize = envVarsTotal * 2; - tmpEnvVars = realloc(envVars, sizeof (*envVars) * - newEnvVarsSize); - if (tmpEnvVars == NULL) { - envVarsTotal--; - return (false); - } - envVarsSize = newEnvVarsSize; - envVars = tmpEnvVars; - } - - return (true); -} - - -/* - * Using environ, build an environment for use by standard C library calls. - */ -static int -__build_env(void) -{ - char **env; - int activeNdx; - int envNdx; - int savedErrno; - size_t nameLen; - - /* Check for non-existant environment. */ - if (environ == NULL || environ[0] == NULL) - return (0); - - /* Count environment variables. */ - for (env = environ, envVarsTotal = 0; *env != NULL; env++) - envVarsTotal++; - envVarsSize = envVarsTotal * 2; - - /* Create new environment. */ - envVars = calloc(1, sizeof (*envVars) * envVarsSize); - if (envVars == NULL) - goto Failure; - - /* Copy environ values and keep track of them. */ - for (envNdx = envVarsTotal - 1; envNdx >= 0; envNdx--) { - envVars[envNdx].putenv = false; - envVars[envNdx].name = - strdup(environ[envVarsTotal - envNdx - 1]); - if (envVars[envNdx].name == NULL) - goto Failure; - envVars[envNdx].value = strchr(envVars[envNdx].name, '='); - if (envVars[envNdx].value != NULL) { - envVars[envNdx].value++; - envVars[envNdx].valueSize = - strlen(envVars[envNdx].value); - } else { - __env_warnx(CorruptEnvValueMsg, envVars[envNdx].name, - strlen(envVars[envNdx].name)); - errno = EFAULT; - goto Failure; - } - - /* - * Find most current version of variable to make active. This - * will prevent multiple active variables from being created - * during this initialization phase. - */ - nameLen = envVars[envNdx].value - envVars[envNdx].name - 1; - envVars[envNdx].nameLen = nameLen; - activeNdx = envVarsTotal - 1; - if (__findenv(envVars[envNdx].name, nameLen, &activeNdx, - false) == NULL) { - __env_warnx(CorruptEnvFindMsg, envVars[envNdx].name, - nameLen); - errno = EFAULT; - goto Failure; - } - envVars[activeNdx].active = true; - } - - /* Create a new environ. */ - origEnviron = environ; - environ = NULL; - if (__rebuild_environ(envVarsTotal) == 0) - return (0); - -Failure: - savedErrno = errno; - __clean_env(true); - errno = savedErrno; - - return (-1); -} - - -/* - * Destructor function with default argument to __clean_env(). - */ -static void -__clean_env_destructor(void) -{ - __clean_env(true); - - return; -} - - -/* - * Returns the value of a variable or NULL if none are found. - */ -char * -getenv(const char *name) -{ - int envNdx; - size_t nameLen; - - /* Check for malformed name. */ - if (name == NULL || (nameLen = __strleneq(name)) == 0) { - errno = EINVAL; - return (NULL); - } - - /* - * Variable search order: - * 1. Check for an empty environ. This allows an application to clear - * the environment. - * 2. Search the external environ array. - * 3. Search the internal environment. - * - * Since malloc() depends upon getenv(), getenv() must never cause the - * internal environment storage to be generated. - */ - if (environ == NULL || environ[0] == NULL) - return (NULL); - else if (envVars == NULL || environ != intEnviron) - return (__findenv_environ(name, nameLen)); - else { - envNdx = envVarsTotal - 1; - return (__findenv(name, nameLen, &envNdx, true)); - } -} - - -/* - * Set the value of a variable. Older settings are labeled as inactive. If an - * older setting has enough room to store the new value, it will be reused. No - * previous variables are ever freed here to avoid causing a segmentation fault - * in a user's code. - * - * The variables nameLen and valueLen are passed into here to allow the caller - * to calculate the length by means besides just strlen(). - */ -static int -__setenv(const char *name, size_t nameLen, const char *value, int overwrite) -{ - bool reuse; - char *env; - int envNdx; - int newEnvActive; - size_t valueLen; - - /* Find existing environment variable large enough to use. */ - envNdx = envVarsTotal - 1; - newEnvActive = envActive; - valueLen = strlen(value); - reuse = false; - if (__findenv(name, nameLen, &envNdx, false) != NULL) { - /* Deactivate entry if overwrite is allowed. */ - if (envVars[envNdx].active) { - if (overwrite == 0) - return (0); - envVars[envNdx].active = false; - newEnvActive--; - } - - /* putenv() created variable cannot be reused. */ - if (envVars[envNdx].putenv) - __remove_putenv(envNdx); - - /* Entry is large enough to reuse. */ - else if (envVars[envNdx].valueSize >= valueLen) - reuse = true; - } - - /* Create new variable if none was found of sufficient size. */ - if (! reuse) { - /* Enlarge environment. */ - envNdx = envVarsTotal; - if (!__enlarge_env()) - return (-1); - - /* Create environment entry. */ - envVars[envNdx].name = malloc(nameLen + sizeof ("=") + - valueLen); - if (envVars[envNdx].name == NULL) { - envVarsTotal--; - return (-1); - } - envVars[envNdx].nameLen = nameLen; - envVars[envNdx].valueSize = valueLen; - - /* Save name of name/value pair. */ - env = stpcpy(envVars[envNdx].name, name); - if ((envVars[envNdx].name)[nameLen] != '=') - env = stpcpy(env, "="); - } - else - env = envVars[envNdx].value; - - /* Save value of name/value pair. */ - strcpy(env, value); - envVars[envNdx].value = env; - envVars[envNdx].active = true; - newEnvActive++; - - /* No need to rebuild environ if an active variable was reused. */ - if (reuse && newEnvActive == envActive) - return (0); - else - return (__rebuild_environ(newEnvActive)); -} - - -/* - * If the program attempts to replace the array of environment variables - * (environ) environ or sets the first varible to NULL, then deactivate all - * variables and merge in the new list from environ. - */ -static int -__merge_environ(void) -{ - char **env; - char *equals; - - /* - * Internally-built environ has been replaced or cleared (detected by - * using the count of active variables against a NULL as the first value - * in environ). Clean up everything. - */ - if (intEnviron != NULL && (environ != intEnviron || (envActive > 0 && - environ[0] == NULL))) { - /* Deactivate all environment variables. */ - if (envActive > 0) { - origEnviron = NULL; - __clean_env(false); - } - - /* - * Insert new environ into existing, yet deactivated, - * environment array. - */ - origEnviron = environ; - if (origEnviron != NULL) - for (env = origEnviron; *env != NULL; env++) { - if ((equals = strchr(*env, '=')) == NULL) { - __env_warnx(CorruptEnvValueMsg, *env, - strlen(*env)); - errno = EFAULT; - return (-1); - } - if (__setenv(*env, equals - *env, equals + 1, - 1) == -1) - return (-1); - } - } - - return (0); -} - - -/* - * The exposed setenv() that peforms a few tests before calling the function - * (__setenv()) that does the actual work of inserting a variable into the - * environment. - */ -int -setenv(const char *name, const char *value, int overwrite) -{ - size_t nameLen; - - /* Check for malformed name. */ - if (name == NULL || (nameLen = __strleneq(name)) == 0) { - errno = EINVAL; - return (-1); - } - - /* Initialize environment. */ - if (__merge_environ() == -1 || (envVars == NULL && __build_env() == -1)) - return (-1); - - return (__setenv(name, nameLen, value, overwrite)); -} - - -/* - * Insert a "name=value" string into the environment. Special settings must be - * made to keep setenv() from reusing this memory block and unsetenv() from - * allowing it to be tracked. - */ -int -putenv(char *string) -{ - char *equals; - int envNdx; - int newEnvActive; - size_t nameLen; - - /* Check for malformed argument. */ - if (string == NULL || (equals = strchr(string, '=')) == NULL || - (nameLen = equals - string) == 0) { - errno = EINVAL; - return (-1); - } - - /* Initialize environment. */ - if (__merge_environ() == -1 || (envVars == NULL && __build_env() == -1)) - return (-1); - - /* Deactivate previous environment variable. */ - envNdx = envVarsTotal - 1; - newEnvActive = envActive; - if (__findenv(string, nameLen, &envNdx, true) != NULL) { - /* Reuse previous putenv slot. */ - if (envVars[envNdx].putenv) { - envVars[envNdx].name = string; - return (__rebuild_environ(envActive)); - } else { - newEnvActive--; - envVars[envNdx].active = false; - } - } - - /* Enlarge environment. */ - envNdx = envVarsTotal; - if (!__enlarge_env()) - return (-1); - - /* Create environment entry. */ - envVars[envNdx].name = string; - envVars[envNdx].nameLen = -1; - envVars[envNdx].value = NULL; - envVars[envNdx].valueSize = -1; - envVars[envNdx].putenv = true; - envVars[envNdx].active = true; - newEnvActive++; - - return (__rebuild_environ(newEnvActive)); -} - - -/* - * Unset variable with the same name by flagging it as inactive. No variable is - * ever freed. - */ -int -unsetenv(const char *name) -{ - int envNdx; - size_t nameLen; - - /* Check for malformed name. */ - if (name == NULL || (nameLen = __strleneq(name)) == 0) { - errno = EINVAL; - return (-1); - } - - /* Initialize environment. */ - if (__merge_environ() == -1 || (envVars == NULL && __build_env() == -1)) - return (-1); - - /* Deactivate specified variable. */ - envNdx = envVarsTotal - 1; - if (__findenv(name, nameLen, &envNdx, true) != NULL) { - envVars[envNdx].active = false; - if (envVars[envNdx].putenv) - __remove_putenv(envNdx); - __rebuild_environ(envActive - 1); - } - - return (0); -} diff --git a/lib/libc/stdlib/getopt.3 b/lib/libc/stdlib/getopt.3 deleted file mode 100644 index 3fe4453..0000000 --- a/lib/libc/stdlib/getopt.3 +++ /dev/null @@ -1,306 +0,0 @@ -.\" $NetBSD: getopt.3,v 1.31 2003/09/23 10:26:54 wiz Exp $ -.\" -.\" Copyright (c) 1988, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)getopt.3 8.5 (Berkeley) 4/27/95 -.\" $FreeBSD$ -.\" -.Dd April 27, 1995 -.Dt GETOPT 3 -.Os -.Sh NAME -.Nm getopt -.Nd get option character from command line argument list -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In unistd.h -.Vt extern char *optarg ; -.Vt extern int optind ; -.Vt extern int optopt ; -.Vt extern int opterr ; -.Vt extern int optreset ; -.Ft int -.Fn getopt "int argc" "char * const argv[]" "const char *optstring" -.Sh DESCRIPTION -The -.Fn getopt -function incrementally parses a command line argument list -.Fa argv -and returns the next -.Em known -option character. -An option character is -.Em known -if it has been specified in the string of accepted option characters, -.Fa optstring . -.Pp -The option string -.Fa optstring -may contain the following elements: individual characters, and -characters followed by a colon to indicate an option argument -is to follow. -For example, an option string -.Li \&"x" -recognizes an option -.Dq Fl x , -and an option string -.Li \&"x:" -recognizes an option and argument -.Dq Fl x Ar argument . -It does not matter to -.Fn getopt -if a following argument has leading white space. -.Pp -On return from -.Fn getopt , -.Va optarg -points to an option argument, if it is anticipated, -and the variable -.Va optind -contains the index to the next -.Fa argv -argument for a subsequent call -to -.Fn getopt . -The variable -.Va optopt -saves the last -.Em known -option character returned by -.Fn getopt . -.Pp -The variables -.Va opterr -and -.Va optind -are both initialized to 1. -The -.Va optind -variable may be set to another value before a set of calls to -.Fn getopt -in order to skip over more or less argv entries. -.Pp -In order to use -.Fn getopt -to evaluate multiple sets of arguments, or to evaluate a single set of -arguments multiple times, -the variable -.Va optreset -must be set to 1 before the second and each additional set of calls to -.Fn getopt , -and the variable -.Va optind -must be reinitialized. -.Pp -The -.Fn getopt -function returns \-1 when the argument list is exhausted. -The interpretation of options in the argument list may be cancelled -by the option -.Ql -- -(double dash) which causes -.Fn getopt -to signal the end of argument processing and return \-1. -When all options have been processed (i.e., up to the first non-option -argument), -.Fn getopt -returns \-1. -.Sh RETURN VALUES -The -.Fn getopt -function returns the next known option character in -.Fa optstring . -If -.Fn getopt -encounters a character not found in -.Fa optstring -or if it detects a missing option argument, -it returns -.Ql \&? -(question mark). -If -.Fa optstring -has a leading -.Ql \&: -then a missing option argument causes -.Ql \&: -to be returned instead of -.Ql \&? . -In either case, the variable -.Va optopt -is set to the character that caused the error. -The -.Fn getopt -function returns \-1 when the argument list is exhausted. -.Sh EXAMPLES -.Bd -literal -compact -#include <unistd.h> -int bflag, ch, fd; - -bflag = 0; -while ((ch = getopt(argc, argv, "bf:")) != -1) { - switch (ch) { - case 'b': - bflag = 1; - break; - case 'f': - if ((fd = open(optarg, O_RDONLY, 0)) \*[Lt] 0) { - (void)fprintf(stderr, - "myname: %s: %s\en", optarg, strerror(errno)); - exit(1); - } - break; - case '?': - default: - usage(); - } -} -argc -= optind; -argv += optind; -.Ed -.Sh DIAGNOSTICS -If the -.Fn getopt -function encounters a character not found in the string -.Fa optstring -or detects -a missing option argument it writes an error message to the -.Dv stderr -and returns -.Ql \&? . -Setting -.Va opterr -to a zero will disable these error messages. -If -.Fa optstring -has a leading -.Ql \&: -then a missing option argument causes a -.Ql \&: -to be returned in addition to suppressing any error messages. -.Pp -Option arguments are allowed to begin with -.Dq Li \- ; -this is reasonable but reduces the amount of error checking possible. -.Sh SEE ALSO -.Xr getopt 1 , -.Xr getopt_long 3 , -.Xr getsubopt 3 -.Sh STANDARDS -The -.Va optreset -variable was added to make it possible to call the -.Fn getopt -function multiple times. -This is an extension to the -.St -p1003.2 -specification. -.Sh HISTORY -The -.Fn getopt -function appeared in -.Bx 4.3 . -.Sh BUGS -The -.Fn getopt -function was once specified to return -.Dv EOF -instead of \-1. -This was changed by -.St -p1003.2-92 -to decouple -.Fn getopt -from -.In stdio.h . -.Pp -A single dash -.Dq Li - -may be specified as a character in -.Fa optstring , -however it should -.Em never -have an argument associated with it. -This allows -.Fn getopt -to be used with programs that expect -.Dq Li - -as an option flag. -This practice is wrong, and should not be used in any current development. -It is provided for backward compatibility -.Em only . -Care should be taken not to use -.Ql \&- -as the first character in -.Fa optstring -to avoid a semantic conflict with -.Tn GNU -.Fn getopt , -which assigns different meaning to an -.Fa optstring -that begins with a -.Ql \&- . -By default, a single dash causes -.Fn getopt -to return \-1. -.Pp -It is also possible to handle digits as option letters. -This allows -.Fn getopt -to be used with programs that expect a number -.Pq Dq Li \&-\&3 -as an option. -This practice is wrong, and should not be used in any current development. -It is provided for backward compatibility -.Em only . -The following code fragment works in most cases. -.Bd -literal -offset indent -int ch; -long length; -char *p, *ep; - -while ((ch = getopt(argc, argv, "0123456789")) != -1) - switch (ch) { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - p = argv[optind - 1]; - if (p[0] == '-' \*[Am]\*[Am] p[1] == ch \*[Am]\*[Am] !p[2]) { - length = ch - '0'; - ep = ""; - } else if (argv[optind] \*[Am]\*[Am] argv[optind][1] == ch) { - length = strtol((p = argv[optind] + 1), - \*[Am]ep, 10); - optind++; - optreset = 1; - } else - usage(); - if (*ep != '\e0') - errx(EX_USAGE, "illegal number -- %s", p); - break; - } -.Ed diff --git a/lib/libc/stdlib/getopt.c b/lib/libc/stdlib/getopt.c deleted file mode 100644 index 4d319a4..0000000 --- a/lib/libc/stdlib/getopt.c +++ /dev/null @@ -1,135 +0,0 @@ -/* $NetBSD: getopt.c,v 1.26 2003/08/07 16:43:40 agc Exp $ */ - -/* - * Copyright (c) 1987, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)getopt.c 8.3 (Berkeley) 4/27/95"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include "namespace.h" -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include "un-namespace.h" - -#include "libc_private.h" - -int opterr = 1, /* if error message should be printed */ - optind = 1, /* index into parent argv vector */ - optopt, /* character checked for validity */ - optreset; /* reset getopt */ -char *optarg; /* argument associated with option */ - -#define BADCH (int)'?' -#define BADARG (int)':' -#define EMSG "" - -/* - * getopt -- - * Parse argc/argv argument vector. - */ -int -getopt(nargc, nargv, ostr) - int nargc; - char * const nargv[]; - const char *ostr; -{ - static char *place = EMSG; /* option letter processing */ - char *oli; /* option letter list index */ - - if (optreset || *place == 0) { /* update scanning pointer */ - optreset = 0; - place = nargv[optind]; - if (optind >= nargc || *place++ != '-') { - /* Argument is absent or is not an option */ - place = EMSG; - return (-1); - } - optopt = *place++; - if (optopt == '-' && *place == 0) { - /* "--" => end of options */ - ++optind; - place = EMSG; - return (-1); - } - if (optopt == 0) { - /* Solitary '-', treat as a '-' option - if the program (eg su) is looking for it. */ - place = EMSG; - if (strchr(ostr, '-') == NULL) - return (-1); - optopt = '-'; - } - } else - optopt = *place++; - - /* See if option letter is one the caller wanted... */ - if (optopt == ':' || (oli = strchr(ostr, optopt)) == NULL) { - if (*place == 0) - ++optind; - if (opterr && *ostr != ':') - (void)fprintf(stderr, - "%s: illegal option -- %c\n", _getprogname(), - optopt); - return (BADCH); - } - - /* Does this option need an argument? */ - if (oli[1] != ':') { - /* don't need argument */ - optarg = NULL; - if (*place == 0) - ++optind; - } else { - /* Option-argument is either the rest of this argument or the - entire next argument. */ - if (*place) - optarg = place; - else if (nargc > ++optind) - optarg = nargv[optind]; - else { - /* option-argument absent */ - place = EMSG; - if (*ostr == ':') - return (BADARG); - if (opterr) - (void)fprintf(stderr, - "%s: option requires an argument -- %c\n", - _getprogname(), optopt); - return (BADCH); - } - place = EMSG; - ++optind; - } - return (optopt); /* return option letter */ -} diff --git a/lib/libc/stdlib/getopt_long.3 b/lib/libc/stdlib/getopt_long.3 deleted file mode 100644 index 72f6534..0000000 --- a/lib/libc/stdlib/getopt_long.3 +++ /dev/null @@ -1,506 +0,0 @@ -.\" $OpenBSD: getopt_long.3,v 1.10 2004/01/06 23:44:28 fgsch Exp $ -.\" $NetBSD: getopt_long.3,v 1.14 2003/08/07 16:43:40 agc Exp $ -.\" -.\" Copyright (c) 1988, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)getopt.3 8.5 (Berkeley) 4/27/95 -.\" $FreeBSD$ -.\" -.Dd April 1, 2000 -.Dt GETOPT_LONG 3 -.Os -.Sh NAME -.Nm getopt_long , -.Nm getopt_long_only -.Nd get long options from command line argument list -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In getopt.h -.Vt extern char *optarg ; -.Vt extern int optind ; -.Vt extern int optopt ; -.Vt extern int opterr ; -.Vt extern int optreset ; -.Ft int -.Fo getopt_long -.Fa "int argc" "char * const *argv" "const char *optstring" -.Fa "const struct option *longopts" "int *longindex" -.Fc -.Ft int -.Fo getopt_long_only -.Fa "int argc" "char * const *argv" "const char *optstring" -.Fa "const struct option *longopts" "int *longindex" -.Fc -.Sh DESCRIPTION -The -.Fn getopt_long -function is similar to -.Xr getopt 3 -but it accepts options in two forms: words and characters. -The -.Fn getopt_long -function provides a superset of the functionality of -.Xr getopt 3 . -The -.Fn getopt_long -function -can be used in two ways. -In the first way, every long option understood -by the program has a corresponding short option, and the option -structure is only used to translate from long options to short -options. -When used in this fashion, -.Fn getopt_long -behaves identically to -.Xr getopt 3 . -This is a good way to add long option processing to an existing program -with the minimum of rewriting. -.Pp -In the second mechanism, a long option sets a flag in the -.Vt option -structure passed, or will store a pointer to the command line argument -in the -.Vt option -structure passed to it for options that take arguments. -Additionally, -the long option's argument may be specified as a single argument with -an equal sign, e.g., -.Pp -.Dl "myprogram --myoption=somevalue" -.Pp -When a long option is processed, the call to -.Fn getopt_long -will return 0. -For this reason, long option processing without -shortcuts is not backwards compatible with -.Xr getopt 3 . -.Pp -It is possible to combine these methods, providing for long options -processing with short option equivalents for some options. -Less -frequently used options would be processed as long options only. -.Pp -The -.Fn getopt_long -call requires a structure to be initialized describing the long -options. -The structure is: -.Bd -literal -offset indent -struct option { - char *name; - int has_arg; - int *flag; - int val; -}; -.Ed -.Pp -The -.Va name -field should contain the option name without the leading double dash. -.Pp -The -.Va has_arg -field should be one of: -.Pp -.Bl -tag -width ".Dv optional_argument" -offset indent -compact -.It Dv no_argument -no argument to the option is expect -.It Dv required_argument -an argument to the option is required -.It Dv optional_argument -an argument to the option may be presented. -.El -.Pp -If -.Va flag -is not -.Dv NULL , -then the integer pointed to by it will be set to the -value in the -.Va val -field. -If the -.Va flag -field is -.Dv NULL , -then the -.Va val -field will be returned. -Setting -.Va flag -to -.Dv NULL -and setting -.Va val -to the corresponding short option will make this function act just -like -.Xr getopt 3 . -.Pp -If the -.Fa longindex -field is not -.Dv NULL , -then the integer pointed to by it will be set to the index of the long -option relative to -.Fa longopts . -.Pp -The last element of the -.Fa longopts -array has to be filled with zeroes. -.Pp -The -.Fn getopt_long_only -function behaves identically to -.Fn getopt_long -with the exception that long options may start with -.Ql - -in addition to -.Ql -- . -If an option starting with -.Ql - -does not match a long option but does match a single-character option, -the single-character option is returned. -.Sh RETURN VALUES -If the -.Fa flag -field in -.Vt "struct option" -is -.Dv NULL , -.Fn getopt_long -and -.Fn getopt_long_only -return the value specified in the -.Fa val -field, which is usually just the corresponding short option. -If -.Fa flag -is not -.Dv NULL , -these functions return 0 and store -.Fa val -in the location pointed to by -.Fa flag . -These functions return -.Ql \&: -if there was a missing option argument, -.Ql \&? -if the user specified an unknown or ambiguous option, and -\-1 when the argument list has been exhausted. -.Sh ENVIRONMENT -.Bl -tag -width ".Ev POSIXLY_CORRECT" -.It Ev POSIXLY_CORRECT -If set, option processing stops when the first non-option is found and -a leading -.Ql - -or -.Ql + -in the -.Fa optstring -is ignored. -.El -.Sh EXAMPLES -.Bd -literal -compact -int bflag, ch, fd; -int daggerset; - -/* options descriptor */ -static struct option longopts[] = { - { "buffy", no_argument, NULL, 'b' }, - { "fluoride", required_argument, NULL, 'f' }, - { "daggerset", no_argument, \*[Am]daggerset, 1 }, - { NULL, 0, NULL, 0 } -}; - -bflag = 0; -while ((ch = getopt_long(argc, argv, "bf:", longopts, NULL)) != -1) - switch (ch) { - case 'b': - bflag = 1; - break; - case 'f': - if ((fd = open(optarg, O_RDONLY, 0)) == -1) - err(1, "unable to open %s", optarg); - break; - case 0: - if (daggerset) { - fprintf(stderr,"Buffy will use her dagger to " - "apply fluoride to dracula's teeth\en"); - } - break; - default: - usage(); -} -argc -= optind; -argv += optind; -.Ed -.Sh IMPLEMENTATION DIFFERENCES -This section describes differences to the -.Tn GNU -implementation -found in glibc-2.1.3: -.Bl -bullet -.\" .It -.\" Handling of -.\" .Ql - -.\" as first char of option string in presence of -.\" environment variable -.\" .Ev POSIXLY_CORRECT : -.\" .Bl -tag -width ".Bx" -.\" .It Tn GNU -.\" ignores -.\" .Ev POSIXLY_CORRECT -.\" and returns non-options as -.\" arguments to option '\e1'. -.\" .It Bx -.\" honors -.\" .Ev POSIXLY_CORRECT -.\" and stops at the first non-option. -.\" .El -.\" .It -.\" Handling of -.\" .Ql - -.\" within the option string (not the first character): -.\" .Bl -tag -width ".Bx" -.\" .It Tn GNU -.\" treats a -.\" .Ql - -.\" on the command line as a non-argument. -.\" .It Bx -.\" a -.\" .Ql - -.\" within the option string matches a -.\" .Ql - -.\" (single dash) on the command line. -.\" This functionality is provided for backward compatibility with -.\" programs, such as -.\" .Xr su 1 , -.\" that use -.\" .Ql - -.\" as an option flag. -.\" This practice is wrong, and should not be used in any current development. -.\" .El -.\" .It -.\" Handling of -.\" .Ql :: -.\" in options string in presence of -.\" .Ev POSIXLY_CORRECT : -.\" .Bl -tag -width ".Bx" -.\" .It Both -.\" .Tn GNU -.\" and -.\" .Bx -.\" ignore -.\" .Ev POSIXLY_CORRECT -.\" here and take -.\" .Ql :: -.\" to -.\" mean the preceding option takes an optional argument. -.\" .El -.\" .It -.\" Return value in case of missing argument if first character -.\" (after -.\" .Ql + -.\" or -.\" .Ql - ) -.\" in option string is not -.\" .Ql \&: : -.\" .Bl -tag -width ".Bx" -.\" .It Tn GNU -.\" returns -.\" .Ql \&? -.\" .It Bx -.\" returns -.\" .Ql \&: -.\" (since -.\" .Bx Ns 's -.\" .Fn getopt -.\" does). -.\" .El -.\" .It -.\" Handling of -.\" .Ql --a -.\" in getopt: -.\" .Bl -tag -width ".Bx" -.\" .It Tn GNU -.\" parses this as option -.\" .Ql - , -.\" option -.\" .Ql a . -.\" .It Bx -.\" parses this as -.\" .Ql -- , -.\" and returns \-1 (ignoring the -.\" .Ql a ) . -.\" (Because the original -.\" .Fn getopt -.\" does.) -.\" .El -.It -Setting of -.Va optopt -for long options with -.Va flag -!= -.Dv NULL : -.Bl -tag -width ".Bx" -.It Tn GNU -sets -.Va optopt -to -.Va val . -.It Bx -sets -.Va optopt -to 0 (since -.Va val -would never be returned). -.El -.\" .It -.\" Handling of -.\" .Ql -W -.\" with -.\" .Ql W; -.\" in option string in -.\" .Fn getopt -.\" (not -.\" .Fn getopt_long ) : -.\" .Bl -tag -width ".Bx" -.\" .It Tn GNU -.\" causes a segfault. -.\" .It Bx -.\" no special handling is done; -.\" .Ql W; -.\" is interpreted as two separate options, neither of which take an argument. -.\" .El -.It -Setting of -.Va optarg -for long options without an argument that are -invoked via -.Ql -W -.Ql ( W; -in option string): -.Bl -tag -width ".Bx" -.It Tn GNU -sets -.Va optarg -to the option name (the argument of -.Ql -W ) . -.It Bx -sets -.Va optarg -to -.Dv NULL -(the argument of the long option). -.El -.It -Handling of -.Ql -W -with an argument that is not (a prefix to) a known -long option -.Ql ( W; -in option string): -.Bl -tag -width ".Bx" -.It Tn GNU -returns -.Ql -W -with -.Va optarg -set to the unknown option. -.It Bx -treats this as an error (unknown option) and returns -.Ql \&? -with -.Va optopt -set to 0 and -.Va optarg -set to -.Dv NULL -(as -.Tn GNU Ns 's -man page documents). -.El -.\" .It -.\" The error messages are different. -.It -.Bx -does not permute the argument vector at the same points in -the calling sequence as -.Tn GNU -does. -The aspects normally used by -the caller (ordering after \-1 is returned, value of -.Va optind -relative -to current positions) are the same, though. -(We do fewer variable swaps.) -.El -.Sh SEE ALSO -.Xr getopt 3 -.Sh HISTORY -The -.Fn getopt_long -and -.Fn getopt_long_only -functions first appeared in the -.Tn GNU -libiberty library. -The first -.Bx -implementation of -.Fn getopt_long -appeared in -.Nx 1.5 , -the first -.Bx -implementation of -.Fn getopt_long_only -in -.Ox 3.3 . -.Fx -first included -.Fn getopt_long -in -.Fx 5.0 , -.Fn getopt_long_only -in -.Fx 5.2 . -.Sh BUGS -The -.Fa argv -argument is not really -.Vt const -as its elements may be permuted (unless -.Ev POSIXLY_CORRECT -is set). -.Pp -The implementation can completely replace -.Xr getopt 3 , -but right now we are using separate code. diff --git a/lib/libc/stdlib/getopt_long.c b/lib/libc/stdlib/getopt_long.c deleted file mode 100644 index bf7a04a..0000000 --- a/lib/libc/stdlib/getopt_long.c +++ /dev/null @@ -1,625 +0,0 @@ -/* $OpenBSD: getopt_long.c,v 1.21 2006/09/22 17:22:05 millert Exp $ */ -/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ - -/* - * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Sponsored in part by the Defense Advanced Research Projects - * Agency (DARPA) and Air Force Research Laboratory, Air Force - * Materiel Command, USAF, under agreement number F39502-99-1-0512. - */ -/*- - * Copyright (c) 2000 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Dieter Baron and Thomas Klausner. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#if 0 -#if defined(LIBC_SCCS) && !defined(lint) -static char *rcsid = "$OpenBSD: getopt_long.c,v 1.16 2004/02/04 18:17:25 millert Exp $"; -#endif /* LIBC_SCCS and not lint */ -#endif -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <err.h> -#include <errno.h> -#include <getopt.h> -#include <stdlib.h> -#include <string.h> - -#define GNU_COMPATIBLE /* Be more compatible, configure's use us! */ - -#if 0 /* we prefer to keep our getopt(3) */ -#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */ -#endif - -#ifdef REPLACE_GETOPT -int opterr = 1; /* if error message should be printed */ -int optind = 1; /* index into parent argv vector */ -int optopt = '?'; /* character checked for validity */ -int optreset; /* reset getopt */ -char *optarg; /* argument associated with option */ -#endif - -#define PRINT_ERROR ((opterr) && (*options != ':')) - -#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ -#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ -#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ - -/* return values */ -#define BADCH (int)'?' -#define BADARG ((*options == ':') ? (int)':' : (int)'?') -#define INORDER (int)1 - -#define EMSG "" - -#ifdef GNU_COMPATIBLE -#define NO_PREFIX (-1) -#define D_PREFIX 0 -#define DD_PREFIX 1 -#define W_PREFIX 2 -#endif - -static int getopt_internal(int, char * const *, const char *, - const struct option *, int *, int); -static int parse_long_options(char * const *, const char *, - const struct option *, int *, int, int); -static int gcd(int, int); -static void permute_args(int, int, int, char * const *); - -static char *place = EMSG; /* option letter processing */ - -/* XXX: set optreset to 1 rather than these two */ -static int nonopt_start = -1; /* first non option argument (for permute) */ -static int nonopt_end = -1; /* first option after non options (for permute) */ - -/* Error messages */ -static const char recargchar[] = "option requires an argument -- %c"; -static const char illoptchar[] = "illegal option -- %c"; /* From P1003.2 */ -#ifdef GNU_COMPATIBLE -static int dash_prefix = NO_PREFIX; -static const char gnuoptchar[] = "invalid option -- %c"; - -static const char recargstring[] = "option `%s%s' requires an argument"; -static const char ambig[] = "option `%s%.*s' is ambiguous"; -static const char noarg[] = "option `%s%.*s' doesn't allow an argument"; -static const char illoptstring[] = "unrecognized option `%s%s'"; -#else -static const char recargstring[] = "option requires an argument -- %s"; -static const char ambig[] = "ambiguous option -- %.*s"; -static const char noarg[] = "option doesn't take an argument -- %.*s"; -static const char illoptstring[] = "unknown option -- %s"; -#endif - -/* - * Compute the greatest common divisor of a and b. - */ -static int -gcd(int a, int b) -{ - int c; - - c = a % b; - while (c != 0) { - a = b; - b = c; - c = a % b; - } - - return (b); -} - -/* - * Exchange the block from nonopt_start to nonopt_end with the block - * from nonopt_end to opt_end (keeping the same order of arguments - * in each block). - */ -static void -permute_args(int panonopt_start, int panonopt_end, int opt_end, - char * const *nargv) -{ - int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; - char *swap; - - /* - * compute lengths of blocks and number and size of cycles - */ - nnonopts = panonopt_end - panonopt_start; - nopts = opt_end - panonopt_end; - ncycle = gcd(nnonopts, nopts); - cyclelen = (opt_end - panonopt_start) / ncycle; - - for (i = 0; i < ncycle; i++) { - cstart = panonopt_end+i; - pos = cstart; - for (j = 0; j < cyclelen; j++) { - if (pos >= panonopt_end) - pos -= nnonopts; - else - pos += nopts; - swap = nargv[pos]; - /* LINTED const cast */ - ((char **) nargv)[pos] = nargv[cstart]; - /* LINTED const cast */ - ((char **)nargv)[cstart] = swap; - } - } -} - -/* - * parse_long_options -- - * Parse long options in argc/argv argument vector. - * Returns -1 if short_too is set and the option does not match long_options. - */ -static int -parse_long_options(char * const *nargv, const char *options, - const struct option *long_options, int *idx, int short_too, int flags) -{ - char *current_argv, *has_equal; -#ifdef GNU_COMPATIBLE - char *current_dash; -#endif - size_t current_argv_len; - int i, match, exact_match, second_partial_match; - - current_argv = place; -#ifdef GNU_COMPATIBLE - switch (dash_prefix) { - case D_PREFIX: - current_dash = "-"; - break; - case DD_PREFIX: - current_dash = "--"; - break; - case W_PREFIX: - current_dash = "-W "; - break; - default: - current_dash = ""; - break; - } -#endif - match = -1; - exact_match = 0; - second_partial_match = 0; - - optind++; - - if ((has_equal = strchr(current_argv, '=')) != NULL) { - /* argument found (--option=arg) */ - current_argv_len = has_equal - current_argv; - has_equal++; - } else - current_argv_len = strlen(current_argv); - - for (i = 0; long_options[i].name; i++) { - /* find matching long option */ - if (strncmp(current_argv, long_options[i].name, - current_argv_len)) - continue; - - if (strlen(long_options[i].name) == current_argv_len) { - /* exact match */ - match = i; - exact_match = 1; - break; - } - /* - * If this is a known short option, don't allow - * a partial match of a single character. - */ - if (short_too && current_argv_len == 1) - continue; - - if (match == -1) /* first partial match */ - match = i; - else if ((flags & FLAG_LONGONLY) || - long_options[i].has_arg != - long_options[match].has_arg || - long_options[i].flag != long_options[match].flag || - long_options[i].val != long_options[match].val) - second_partial_match = 1; - } - if (!exact_match && second_partial_match) { - /* ambiguous abbreviation */ - if (PRINT_ERROR) - warnx(ambig, -#ifdef GNU_COMPATIBLE - current_dash, -#endif - (int)current_argv_len, - current_argv); - optopt = 0; - return (BADCH); - } - if (match != -1) { /* option found */ - if (long_options[match].has_arg == no_argument - && has_equal) { - if (PRINT_ERROR) - warnx(noarg, -#ifdef GNU_COMPATIBLE - current_dash, -#endif - (int)current_argv_len, - current_argv); - /* - * XXX: GNU sets optopt to val regardless of flag - */ - if (long_options[match].flag == NULL) - optopt = long_options[match].val; - else - optopt = 0; -#ifdef GNU_COMPATIBLE - return (BADCH); -#else - return (BADARG); -#endif - } - if (long_options[match].has_arg == required_argument || - long_options[match].has_arg == optional_argument) { - if (has_equal) - optarg = has_equal; - else if (long_options[match].has_arg == - required_argument) { - /* - * optional argument doesn't use next nargv - */ - optarg = nargv[optind++]; - } - } - if ((long_options[match].has_arg == required_argument) - && (optarg == NULL)) { - /* - * Missing argument; leading ':' indicates no error - * should be generated. - */ - if (PRINT_ERROR) - warnx(recargstring, -#ifdef GNU_COMPATIBLE - current_dash, -#endif - current_argv); - /* - * XXX: GNU sets optopt to val regardless of flag - */ - if (long_options[match].flag == NULL) - optopt = long_options[match].val; - else - optopt = 0; - --optind; - return (BADARG); - } - } else { /* unknown option */ - if (short_too) { - --optind; - return (-1); - } - if (PRINT_ERROR) - warnx(illoptstring, -#ifdef GNU_COMPATIBLE - current_dash, -#endif - current_argv); - optopt = 0; - return (BADCH); - } - if (idx) - *idx = match; - if (long_options[match].flag) { - *long_options[match].flag = long_options[match].val; - return (0); - } else - return (long_options[match].val); -} - -/* - * getopt_internal -- - * Parse argc/argv argument vector. Called by user level routines. - */ -static int -getopt_internal(int nargc, char * const *nargv, const char *options, - const struct option *long_options, int *idx, int flags) -{ - char *oli; /* option letter list index */ - int optchar, short_too; - int posixly_correct; /* no static, can be changed on the fly */ - - if (options == NULL) - return (-1); - - /* - * Disable GNU extensions if POSIXLY_CORRECT is set or options - * string begins with a '+'. - */ - posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); -#ifdef GNU_COMPATIBLE - if (*options == '-') - flags |= FLAG_ALLARGS; - else if (posixly_correct || *options == '+') - flags &= ~FLAG_PERMUTE; -#else - if (posixly_correct || *options == '+') - flags &= ~FLAG_PERMUTE; - else if (*options == '-') - flags |= FLAG_ALLARGS; -#endif - if (*options == '+' || *options == '-') - options++; - - /* - * XXX Some GNU programs (like cvs) set optind to 0 instead of - * XXX using optreset. Work around this braindamage. - */ - if (optind == 0) - optind = optreset = 1; - - optarg = NULL; - if (optreset) - nonopt_start = nonopt_end = -1; -start: - if (optreset || !*place) { /* update scanning pointer */ - optreset = 0; - if (optind >= nargc) { /* end of argument vector */ - place = EMSG; - if (nonopt_end != -1) { - /* do permutation, if we have to */ - permute_args(nonopt_start, nonopt_end, - optind, nargv); - optind -= nonopt_end - nonopt_start; - } - else if (nonopt_start != -1) { - /* - * If we skipped non-options, set optind - * to the first of them. - */ - optind = nonopt_start; - } - nonopt_start = nonopt_end = -1; - return (-1); - } - if (*(place = nargv[optind]) != '-' || -#ifdef GNU_COMPATIBLE - place[1] == '\0') { -#else - (place[1] == '\0' && strchr(options, '-') == NULL)) { -#endif - place = EMSG; /* found non-option */ - if (flags & FLAG_ALLARGS) { - /* - * GNU extension: - * return non-option as argument to option 1 - */ - optarg = nargv[optind++]; - return (INORDER); - } - if (!(flags & FLAG_PERMUTE)) { - /* - * If no permutation wanted, stop parsing - * at first non-option. - */ - return (-1); - } - /* do permutation */ - if (nonopt_start == -1) - nonopt_start = optind; - else if (nonopt_end != -1) { - permute_args(nonopt_start, nonopt_end, - optind, nargv); - nonopt_start = optind - - (nonopt_end - nonopt_start); - nonopt_end = -1; - } - optind++; - /* process next argument */ - goto start; - } - if (nonopt_start != -1 && nonopt_end == -1) - nonopt_end = optind; - - /* - * If we have "-" do nothing, if "--" we are done. - */ - if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { - optind++; - place = EMSG; - /* - * We found an option (--), so if we skipped - * non-options, we have to permute. - */ - if (nonopt_end != -1) { - permute_args(nonopt_start, nonopt_end, - optind, nargv); - optind -= nonopt_end - nonopt_start; - } - nonopt_start = nonopt_end = -1; - return (-1); - } - } - - /* - * Check long options if: - * 1) we were passed some - * 2) the arg is not just "-" - * 3) either the arg starts with -- we are getopt_long_only() - */ - if (long_options != NULL && place != nargv[optind] && - (*place == '-' || (flags & FLAG_LONGONLY))) { - short_too = 0; -#ifdef GNU_COMPATIBLE - dash_prefix = D_PREFIX; -#endif - if (*place == '-') { - place++; /* --foo long option */ -#ifdef GNU_COMPATIBLE - dash_prefix = DD_PREFIX; -#endif - } else if (*place != ':' && strchr(options, *place) != NULL) - short_too = 1; /* could be short option too */ - - optchar = parse_long_options(nargv, options, long_options, - idx, short_too, flags); - if (optchar != -1) { - place = EMSG; - return (optchar); - } - } - - if ((optchar = (int)*place++) == (int)':' || - (optchar == (int)'-' && *place != '\0') || - (oli = strchr(options, optchar)) == NULL) { - /* - * If the user specified "-" and '-' isn't listed in - * options, return -1 (non-option) as per POSIX. - * Otherwise, it is an unknown option character (or ':'). - */ - if (optchar == (int)'-' && *place == '\0') - return (-1); - if (!*place) - ++optind; -#ifdef GNU_COMPATIBLE - if (PRINT_ERROR) - warnx(posixly_correct ? illoptchar : gnuoptchar, - optchar); -#else - if (PRINT_ERROR) - warnx(illoptchar, optchar); -#endif - optopt = optchar; - return (BADCH); - } - if (long_options != NULL && optchar == 'W' && oli[1] == ';') { - /* -W long-option */ - if (*place) /* no space */ - /* NOTHING */; - else if (++optind >= nargc) { /* no arg */ - place = EMSG; - if (PRINT_ERROR) - warnx(recargchar, optchar); - optopt = optchar; - return (BADARG); - } else /* white space */ - place = nargv[optind]; -#ifdef GNU_COMPATIBLE - dash_prefix = W_PREFIX; -#endif - optchar = parse_long_options(nargv, options, long_options, - idx, 0, flags); - place = EMSG; - return (optchar); - } - if (*++oli != ':') { /* doesn't take argument */ - if (!*place) - ++optind; - } else { /* takes (optional) argument */ - optarg = NULL; - if (*place) /* no white space */ - optarg = place; - else if (oli[1] != ':') { /* arg not optional */ - if (++optind >= nargc) { /* no arg */ - place = EMSG; - if (PRINT_ERROR) - warnx(recargchar, optchar); - optopt = optchar; - return (BADARG); - } else - optarg = nargv[optind]; - } - place = EMSG; - ++optind; - } - /* dump back option letter */ - return (optchar); -} - -#ifdef REPLACE_GETOPT -/* - * getopt -- - * Parse argc/argv argument vector. - * - * [eventually this will replace the BSD getopt] - */ -int -getopt(int nargc, char * const *nargv, const char *options) -{ - - /* - * We don't pass FLAG_PERMUTE to getopt_internal() since - * the BSD getopt(3) (unlike GNU) has never done this. - * - * Furthermore, since many privileged programs call getopt() - * before dropping privileges it makes sense to keep things - * as simple (and bug-free) as possible. - */ - return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); -} -#endif /* REPLACE_GETOPT */ - -/* - * getopt_long -- - * Parse argc/argv argument vector. - */ -int -getopt_long(int nargc, char * const *nargv, const char *options, - const struct option *long_options, int *idx) -{ - - return (getopt_internal(nargc, nargv, options, long_options, idx, - FLAG_PERMUTE)); -} - -/* - * getopt_long_only -- - * Parse argc/argv argument vector. - */ -int -getopt_long_only(int nargc, char * const *nargv, const char *options, - const struct option *long_options, int *idx) -{ - - return (getopt_internal(nargc, nargv, options, long_options, idx, - FLAG_PERMUTE|FLAG_LONGONLY)); -} diff --git a/lib/libc/stdlib/getsubopt.3 b/lib/libc/stdlib/getsubopt.3 deleted file mode 100644 index b624eff..0000000 --- a/lib/libc/stdlib/getsubopt.3 +++ /dev/null @@ -1,145 +0,0 @@ -.\" Copyright (c) 1990, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)getsubopt.3 8.1 (Berkeley) 6/9/93 -.\" $FreeBSD$ -.\" -.Dd June 9, 1993 -.Dt GETSUBOPT 3 -.Os -.Sh NAME -.Nm getsubopt -.Nd get sub options from an argument -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In stdlib.h -.Vt extern char *suboptarg ; -.Ft int -.Fn getsubopt "char **optionp" "char * const *tokens" "char **valuep" -.Sh DESCRIPTION -The -.Fn getsubopt -function -parses a string containing tokens delimited by one or more tab, space or -comma -.Pq Ql \&, -characters. -It is intended for use in parsing groups of option arguments provided -as part of a utility command line. -.Pp -The argument -.Fa optionp -is a pointer to a pointer to the string. -The argument -.Fa tokens -is a pointer to a -.Dv NULL Ns -terminated -array of pointers to strings. -.Pp -The -.Fn getsubopt -function -returns the zero-based offset of the pointer in the -.Fa tokens -array referencing a string which matches the first token -in the string, or, \-1 if the string contains no tokens or -.Fa tokens -does not contain a matching string. -.Pp -If the token is of the form ``name=value'', the location referenced by -.Fa valuep -will be set to point to the start of the ``value'' portion of the token. -.Pp -On return from -.Fn getsubopt , -.Fa optionp -will be set to point to the start of the next token in the string, -or the null at the end of the string if no more tokens are present. -The external variable -.Fa suboptarg -will be set to point to the start of the current token, or -.Dv NULL -if no -tokens were present. -The argument -.Fa valuep -will be set to point to the ``value'' portion of the token, or -.Dv NULL -if no ``value'' portion was present. -.Sh EXAMPLES -.Bd -literal -compact -char *tokens[] = { - #define ONE 0 - "one", - #define TWO 1 - "two", - NULL -}; - -\&... - -extern char *optarg, *suboptarg; -char *options, *value; - -while ((ch = getopt(argc, argv, "ab:")) != \-1) { - switch(ch) { - case 'a': - /* process ``a'' option */ - break; - case 'b': - options = optarg; - while (*options) { - switch(getsubopt(&options, tokens, &value)) { - case ONE: - /* process ``one'' sub option */ - break; - case TWO: - /* process ``two'' sub option */ - if (!value) - error("no value for two"); - i = atoi(value); - break; - case \-1: - if (suboptarg) - error("illegal sub option %s", - suboptarg); - else - error("missing sub option"); - break; - } - break; - } -.Ed -.Sh SEE ALSO -.Xr getopt 3 , -.Xr strsep 3 -.Sh HISTORY -The -.Fn getsubopt -function first appeared in -.Bx 4.4 . diff --git a/lib/libc/stdlib/getsubopt.c b/lib/libc/stdlib/getsubopt.c deleted file mode 100644 index 6d0ab75..0000000 --- a/lib/libc/stdlib/getsubopt.c +++ /dev/null @@ -1,97 +0,0 @@ -/*- - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)getsubopt.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stdlib.h> -#include <string.h> - -/* - * The SVID interface to getsubopt provides no way of figuring out which - * part of the suboptions list wasn't matched. This makes error messages - * tricky... The extern variable suboptarg is a pointer to the token - * which didn't match. - */ -char *suboptarg; - -int -getsubopt(optionp, tokens, valuep) - char **optionp, **valuep; - char * const *tokens; -{ - int cnt; - char *p; - - suboptarg = *valuep = NULL; - - if (!optionp || !*optionp) - return(-1); - - /* skip leading white-space, commas */ - for (p = *optionp; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p); - - if (!*p) { - *optionp = p; - return(-1); - } - - /* save the start of the token, and skip the rest of the token. */ - for (suboptarg = p; - *++p && *p != ',' && *p != '=' && *p != ' ' && *p != '\t';); - - if (*p) { - /* - * If there's an equals sign, set the value pointer, and - * skip over the value part of the token. Terminate the - * token. - */ - if (*p == '=') { - *p = '\0'; - for (*valuep = ++p; - *p && *p != ',' && *p != ' ' && *p != '\t'; ++p); - if (*p) - *p++ = '\0'; - } else - *p++ = '\0'; - /* Skip any whitespace or commas after this token. */ - for (; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p); - } - - /* set optionp for next round. */ - *optionp = p; - - for (cnt = 0; *tokens; ++tokens, ++cnt) - if (!strcmp(suboptarg, *tokens)) - return(cnt); - return(-1); -} diff --git a/lib/libc/stdlib/hcreate.3 b/lib/libc/stdlib/hcreate.3 deleted file mode 100644 index 2466c9f..0000000 --- a/lib/libc/stdlib/hcreate.3 +++ /dev/null @@ -1,258 +0,0 @@ -.\"- -.\" Copyright (c) 1999 The NetBSD Foundation, Inc. -.\" All rights reserved. -.\" -.\" This code is derived from software contributed to The NetBSD Foundation -.\" by Klaus Klein. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS -.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS -.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -.\" POSSIBILITY OF SUCH DAMAGE. -.\" -.\" $FreeBSD$ -.\" -.Dd July 6, 2008 -.Dt HCREATE 3 -.Os -.Sh NAME -.Nm hcreate , hdestroy , hsearch -.Nd manage hash search table -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In search.h -.Ft int -.Fn hcreate "size_t nel" -.Ft void -.Fn hdestroy void -.Ft ENTRY * -.Fn hsearch "ENTRY item" "ACTION action" -.Sh DESCRIPTION -The -.Fn hcreate , -.Fn hdestroy , -and -.Fn hsearch -functions manage hash search tables. -.Pp -The -.Fn hcreate -function allocates sufficient space for the table, and the application should -ensure it is called before -.Fn hsearch -is used. -The -.Fa nel -argument is an estimate of the maximum -number of entries that the table should contain. -This number may be adjusted upward by the -algorithm in order to obtain certain mathematically favorable circumstances. -.Pp -The -.Fn hdestroy -function disposes of the search table, and may be followed by another call to -.Fn hcreate . -After the call to -.Fn hdestroy , -the data can no longer be considered accessible. -The -.Fn hdestroy -function calls -.Xr free 3 -for each comparison key in the search table -but not the data item associated with the key. -.Pp -The -.Fn hsearch -function is a hash-table search routine. -It returns a pointer into a hash table -indicating the location at which an entry can be found. -The -.Fa item -argument is a structure of type -.Vt ENTRY -(defined in the -.In search.h -header) containing two pointers: -.Fa item.key -points to the comparison key (a -.Vt "char *" ) , -and -.Fa item.data -(a -.Vt "void *" ) -points to any other data to be associated with -that key. -The comparison function used by -.Fn hsearch -is -.Xr strcmp 3 . -The -.Fa action -argument is a -member of an enumeration type -.Vt ACTION -indicating the disposition of the entry if it cannot be -found in the table. -.Dv ENTER -indicates that the -.Fa item -should be inserted in the table at an -appropriate point. -.Dv FIND -indicates that no entry should be made. -Unsuccessful resolution is -indicated by the return of a -.Dv NULL -pointer. -.Pp -The comparison key (passed to -.Fn hsearch -as -.Fa item.key ) -must be allocated using -.Xr malloc 3 -if -.Fa action -is -.Dv ENTER -and -.Fn hdestroy -is called. -.Sh RETURN VALUES -The -.Fn hcreate -function returns 0 if the table creation failed and the global variable -.Va errno -is set to indicate the error; -otherwise, a non-zero value is returned. -.Pp -The -.Fn hdestroy -function does not return a value. -.Pp -The -.Fn hsearch -function returns a -.Dv NULL -pointer if either the -.Fa action -is -.Dv FIND -and the -.Fa item -could not be found or the -.Fa action -is -.Dv ENTER -and the table is full. -.Sh EXAMPLES -The following example reads in strings followed by two numbers -and stores them in a hash table, discarding duplicates. -It then reads in strings and finds the matching entry in the hash -table and prints it out. -.Bd -literal -#include <stdio.h> -#include <search.h> -#include <string.h> -#include <stdlib.h> - -struct info { /* This is the info stored in the table */ - int age, room; /* other than the key. */ -}; - -#define NUM_EMPL 5000 /* # of elements in search table. */ - -int -main(void) -{ - char str[BUFSIZ]; /* Space to read string */ - struct info info_space[NUM_EMPL]; /* Space to store employee info. */ - struct info *info_ptr = info_space; /* Next space in info_space. */ - ENTRY item; - ENTRY *found_item; /* Name to look for in table. */ - char name_to_find[30]; - int i = 0; - - /* Create table; no error checking is performed. */ - (void) hcreate(NUM_EMPL); - - while (scanf("%s%d%d", str, &info_ptr->age, - &info_ptr->room) != EOF && i++ < NUM_EMPL) { - /* Put information in structure, and structure in item. */ - item.key = strdup(str); - item.data = info_ptr; - info_ptr++; - /* Put item into table. */ - (void) hsearch(item, ENTER); - } - - /* Access table. */ - item.key = name_to_find; - while (scanf("%s", item.key) != EOF) { - if ((found_item = hsearch(item, FIND)) != NULL) { - /* If item is in the table. */ - (void)printf("found %s, age = %d, room = %d\en", - found_item->key, - ((struct info *)found_item->data)->age, - ((struct info *)found_item->data)->room); - } else - (void)printf("no such employee %s\en", name_to_find); - } - hdestroy(); - return 0; -} -.Ed -.Sh ERRORS -The -.Fn hcreate -and -.Fn hsearch -functions may fail if: -.Bl -tag -width Er -.It Bq Er ENOMEM -Insufficient storage space is available. -.It Bq Er EINVAL -A table already exists. -.El -.Sh SEE ALSO -.Xr bsearch 3 , -.Xr lsearch 3 , -.Xr malloc 3 , -.Xr strcmp 3 , -.Xr tsearch 3 -.Sh STANDARDS -The -.Fn hcreate , -.Fn hdestroy , -and -.Fn hsearch -functions conform to -.St -xpg4.2 . -.Sh HISTORY -The -.Fn hcreate , -.Fn hdestroy , -and -.Fn hsearch -functions first appeared in -.At V . -.Sh BUGS -The interface permits the use of only one hash table at a time. diff --git a/lib/libc/stdlib/hcreate.c b/lib/libc/stdlib/hcreate.c deleted file mode 100644 index c68fe1b..0000000 --- a/lib/libc/stdlib/hcreate.c +++ /dev/null @@ -1,185 +0,0 @@ -/* $NetBSD: hcreate.c,v 1.2 2001/02/19 21:26:04 ross Exp $ */ - -/* - * Copyright (c) 2001 Christopher G. Demetriou - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the - * NetBSD Project. See http://www.netbsd.org/ for - * information about NetBSD. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>> - */ - -/* - * hcreate() / hsearch() / hdestroy() - * - * SysV/XPG4 hash table functions. - * - * Implementation done based on NetBSD manual page and Solaris manual page, - * plus my own personal experience about how they're supposed to work. - * - * I tried to look at Knuth (as cited by the Solaris manual page), but - * nobody had a copy in the office, so... - */ - -#include <sys/cdefs.h> -#if 0 -#if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: hcreate.c,v 1.2 2001/02/19 21:26:04 ross Exp $"); -#endif /* LIBC_SCCS and not lint */ -#endif -__FBSDID("$FreeBSD$"); - -#include <sys/types.h> -#include <sys/queue.h> -#include <errno.h> -#include <search.h> -#include <stdlib.h> -#include <string.h> - -/* - * DO NOT MAKE THIS STRUCTURE LARGER THAN 32 BYTES (4 ptrs on 64-bit - * ptr machine) without adjusting MAX_BUCKETS_LG2 below. - */ -struct internal_entry { - SLIST_ENTRY(internal_entry) link; - ENTRY ent; -}; -SLIST_HEAD(internal_head, internal_entry); - -#define MIN_BUCKETS_LG2 4 -#define MIN_BUCKETS (1 << MIN_BUCKETS_LG2) - -/* - * max * sizeof internal_entry must fit into size_t. - * assumes internal_entry is <= 32 (2^5) bytes. - */ -#define MAX_BUCKETS_LG2 (sizeof (size_t) * 8 - 1 - 5) -#define MAX_BUCKETS ((size_t)1 << MAX_BUCKETS_LG2) - -/* Default hash function, from db/hash/hash_func.c */ -extern u_int32_t (*__default_hash)(const void *, size_t); - -static struct internal_head *htable; -static size_t htablesize; - -int -hcreate(size_t nel) -{ - size_t idx; - unsigned int p2; - - /* Make sure this is not called when a table already exists. */ - if (htable != NULL) { - errno = EINVAL; - return 0; - } - - /* If nel is too small, make it min sized. */ - if (nel < MIN_BUCKETS) - nel = MIN_BUCKETS; - - /* If it is too large, cap it. */ - if (nel > MAX_BUCKETS) - nel = MAX_BUCKETS; - - /* If it is not a power of two in size, round up. */ - if ((nel & (nel - 1)) != 0) { - for (p2 = 0; nel != 0; p2++) - nel >>= 1; - nel = 1 << p2; - } - - /* Allocate the table. */ - htablesize = nel; - htable = malloc(htablesize * sizeof htable[0]); - if (htable == NULL) { - errno = ENOMEM; - return 0; - } - - /* Initialize it. */ - for (idx = 0; idx < htablesize; idx++) - SLIST_INIT(&htable[idx]); - - return 1; -} - -void -hdestroy(void) -{ - struct internal_entry *ie; - size_t idx; - - if (htable == NULL) - return; - - for (idx = 0; idx < htablesize; idx++) { - while (!SLIST_EMPTY(&htable[idx])) { - ie = SLIST_FIRST(&htable[idx]); - SLIST_REMOVE_HEAD(&htable[idx], link); - free(ie->ent.key); - free(ie); - } - } - free(htable); - htable = NULL; -} - -ENTRY * -hsearch(ENTRY item, ACTION action) -{ - struct internal_head *head; - struct internal_entry *ie; - uint32_t hashval; - size_t len; - - len = strlen(item.key); - hashval = (*__default_hash)(item.key, len); - - head = &htable[hashval & (htablesize - 1)]; - ie = SLIST_FIRST(head); - while (ie != NULL) { - if (strcmp(ie->ent.key, item.key) == 0) - break; - ie = SLIST_NEXT(ie, link); - } - - if (ie != NULL) - return &ie->ent; - else if (action == FIND) - return NULL; - - ie = malloc(sizeof *ie); - if (ie == NULL) - return NULL; - ie->ent.key = item.key; - ie->ent.data = item.data; - - SLIST_INSERT_HEAD(head, ie, link); - return &ie->ent; -} diff --git a/lib/libc/stdlib/heapsort.c b/lib/libc/stdlib/heapsort.c deleted file mode 100644 index f656876..0000000 --- a/lib/libc/stdlib/heapsort.c +++ /dev/null @@ -1,181 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Ronnie Kon at Mindcraft Inc., Kevin Lew and Elmer Yglesias. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)heapsort.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <errno.h> -#include <stddef.h> -#include <stdlib.h> - -/* - * Swap two areas of size number of bytes. Although qsort(3) permits random - * blocks of memory to be sorted, sorting pointers is almost certainly the - * common case (and, were it not, could easily be made so). Regardless, it - * isn't worth optimizing; the SWAP's get sped up by the cache, and pointer - * arithmetic gets lost in the time required for comparison function calls. - */ -#define SWAP(a, b, count, size, tmp) { \ - count = size; \ - do { \ - tmp = *a; \ - *a++ = *b; \ - *b++ = tmp; \ - } while (--count); \ -} - -/* Copy one block of size size to another. */ -#define COPY(a, b, count, size, tmp1, tmp2) { \ - count = size; \ - tmp1 = a; \ - tmp2 = b; \ - do { \ - *tmp1++ = *tmp2++; \ - } while (--count); \ -} - -/* - * Build the list into a heap, where a heap is defined such that for - * the records K1 ... KN, Kj/2 >= Kj for 1 <= j/2 <= j <= N. - * - * There two cases. If j == nmemb, select largest of Ki and Kj. If - * j < nmemb, select largest of Ki, Kj and Kj+1. - */ -#define CREATE(initval, nmemb, par_i, child_i, par, child, size, count, tmp) { \ - for (par_i = initval; (child_i = par_i * 2) <= nmemb; \ - par_i = child_i) { \ - child = base + child_i * size; \ - if (child_i < nmemb && compar(child, child + size) < 0) { \ - child += size; \ - ++child_i; \ - } \ - par = base + par_i * size; \ - if (compar(child, par) <= 0) \ - break; \ - SWAP(par, child, count, size, tmp); \ - } \ -} - -/* - * Select the top of the heap and 'heapify'. Since by far the most expensive - * action is the call to the compar function, a considerable optimization - * in the average case can be achieved due to the fact that k, the displaced - * elememt, is ususally quite small, so it would be preferable to first - * heapify, always maintaining the invariant that the larger child is copied - * over its parent's record. - * - * Then, starting from the *bottom* of the heap, finding k's correct place, - * again maintianing the invariant. As a result of the invariant no element - * is 'lost' when k is assigned its correct place in the heap. - * - * The time savings from this optimization are on the order of 15-20% for the - * average case. See Knuth, Vol. 3, page 158, problem 18. - * - * XXX Don't break the #define SELECT line, below. Reiser cpp gets upset. - */ -#define SELECT(par_i, child_i, nmemb, par, child, size, k, count, tmp1, tmp2) { \ - for (par_i = 1; (child_i = par_i * 2) <= nmemb; par_i = child_i) { \ - child = base + child_i * size; \ - if (child_i < nmemb && compar(child, child + size) < 0) { \ - child += size; \ - ++child_i; \ - } \ - par = base + par_i * size; \ - COPY(par, child, count, size, tmp1, tmp2); \ - } \ - for (;;) { \ - child_i = par_i; \ - par_i = child_i / 2; \ - child = base + child_i * size; \ - par = base + par_i * size; \ - if (child_i == 1 || compar(k, par) < 0) { \ - COPY(child, k, count, size, tmp1, tmp2); \ - break; \ - } \ - COPY(child, par, count, size, tmp1, tmp2); \ - } \ -} - -/* - * Heapsort -- Knuth, Vol. 3, page 145. Runs in O (N lg N), both average - * and worst. While heapsort is faster than the worst case of quicksort, - * the BSD quicksort does median selection so that the chance of finding - * a data set that will trigger the worst case is nonexistent. Heapsort's - * only advantage over quicksort is that it requires little additional memory. - */ -int -heapsort(vbase, nmemb, size, compar) - void *vbase; - size_t nmemb, size; - int (*compar)(const void *, const void *); -{ - size_t cnt, i, j, l; - char tmp, *tmp1, *tmp2; - char *base, *k, *p, *t; - - if (nmemb <= 1) - return (0); - - if (!size) { - errno = EINVAL; - return (-1); - } - - if ((k = malloc(size)) == NULL) - return (-1); - - /* - * Items are numbered from 1 to nmemb, so offset from size bytes - * below the starting address. - */ - base = (char *)vbase - size; - - for (l = nmemb / 2 + 1; --l;) - CREATE(l, nmemb, i, j, t, p, size, cnt, tmp); - - /* - * For each element of the heap, save the largest element into its - * final slot, save the displaced element (k), then recreate the - * heap. - */ - while (nmemb > 1) { - COPY(k, base + nmemb * size, cnt, size, tmp1, tmp2); - COPY(base + nmemb * size, base + size, cnt, size, tmp1, tmp2); - --nmemb; - SELECT(i, j, nmemb, t, p, size, k, cnt, tmp1, tmp2); - } - free(k); - return (0); -} diff --git a/lib/libc/stdlib/imaxabs.3 b/lib/libc/stdlib/imaxabs.3 deleted file mode 100644 index 430f873..0000000 --- a/lib/libc/stdlib/imaxabs.3 +++ /dev/null @@ -1,62 +0,0 @@ -.\" Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org> -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $FreeBSD$ -.\" -.Dd November 14, 2001 -.Dt IMAXABS 3 -.Os -.Sh NAME -.Nm imaxabs -.Nd returns absolute value -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In inttypes.h -.Ft intmax_t -.Fn imaxabs "intmax_t j" -.Sh DESCRIPTION -The -.Fn imaxabs -function returns the absolute value of -.Fa j . -.Sh SEE ALSO -.Xr abs 3 , -.Xr fabs 3 , -.Xr hypot 3 , -.Xr labs 3 , -.Xr llabs 3 , -.Xr math 3 -.Sh STANDARDS -The -.Fn imaxabs -function conforms to -.St -isoC-99 . -.Sh HISTORY -The -.Fn imaxabs -function first appeared in -.Fx 5.0 . -.Sh BUGS -The absolute value of the most negative integer remains negative. diff --git a/lib/libc/stdlib/imaxabs.c b/lib/libc/stdlib/imaxabs.c deleted file mode 100644 index 35e3dee..0000000 --- a/lib/libc/stdlib/imaxabs.c +++ /dev/null @@ -1,36 +0,0 @@ -/*- - * Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <inttypes.h> - -intmax_t -imaxabs(intmax_t j) -{ - return (j < 0 ? -j : j); -} diff --git a/lib/libc/stdlib/imaxdiv.3 b/lib/libc/stdlib/imaxdiv.3 deleted file mode 100644 index 0ee0971..0000000 --- a/lib/libc/stdlib/imaxdiv.3 +++ /dev/null @@ -1,73 +0,0 @@ -.\" Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org> -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $FreeBSD$ -.\" -.Dd November 14, 2001 -.Dt IMAXDIV 3 -.Os -.Sh NAME -.Nm imaxdiv -.Nd returns quotient and remainder -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In inttypes.h -.Ft imaxdiv_t -.Fn imaxdiv "intmax_t numer" "intmax_t denom" -.Sh DESCRIPTION -The -.Fn imaxdiv -function computes the value of -.Fa numer -divided by -.Fa denom -and returns the stored result in the form of the -.Vt imaxdiv_t -type. -.Pp -The -.Vt imaxdiv_t -type is defined as: -.Bd -literal -offset indent -typedef struct { - intmax_t quot; /* Quotient. */ - intmax_t rem; /* Remainder. */ -} imaxdiv_t; -.Ed -.Sh SEE ALSO -.Xr div 3 , -.Xr ldiv 3 , -.Xr lldiv 3 , -.Xr math 3 -.Sh STANDARDS -The -.Fn imaxdiv -function conforms to -.St -isoC-99 . -.Sh HISTORY -The -.Fn imaxdiv -function first appeared in -.Fx 5.0 . diff --git a/lib/libc/stdlib/imaxdiv.c b/lib/libc/stdlib/imaxdiv.c deleted file mode 100644 index 7dae467..0000000 --- a/lib/libc/stdlib/imaxdiv.c +++ /dev/null @@ -1,45 +0,0 @@ -/*- - * Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <inttypes.h> - -/* See comments in div.c for implementation details. */ -imaxdiv_t -imaxdiv(intmax_t numer, intmax_t denom) -{ - imaxdiv_t retval; - - retval.quot = numer / denom; - retval.rem = numer % denom; - if (numer >= 0 && retval.rem < 0) { - retval.quot++; - retval.rem -= denom; - } - return (retval); -} diff --git a/lib/libc/stdlib/insque.3 b/lib/libc/stdlib/insque.3 deleted file mode 100644 index a54434c..0000000 --- a/lib/libc/stdlib/insque.3 +++ /dev/null @@ -1,61 +0,0 @@ -.\" -.\" Initial implementation: -.\" Copyright (c) 2002 Robert Drehmel -.\" All rights reserved. -.\" -.\" As long as the above copyright statement and this notice remain -.\" unchanged, you can do what ever you want with this file. -.\" -.\" $FreeBSD$ -.\" -.Dd October 10, 2002 -.Dt INSQUE 3 -.Os -.Sh NAME -.Nm insque , -.Nm remque -.Nd doubly-linked list management -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In search.h -.Ft void -.Fn insque "void *element1" "void *pred" -.Ft void -.Fn remque "void *element" -.Sh DESCRIPTION -The -.Fn insque -and -.Fn remque -functions encapsulate the ever-repeating task of doing insertion and -removal operations on doubly linked lists. -The functions expect their -arguments to point to a structure whose first and second members are -pointers to the next and previous element, respectively. -The -.Fn insque -function also allows the -.Fa pred -argument to be a -.Dv NULL -pointer for the initialization of a new list's -head element. -.Sh STANDARDS -The -.Fn insque -and -.Fn remque -functions conform to -.St -p1003.1-2001 . -.Sh HISTORY -The -.Fn insque -and -.Fn remque -functions appeared in -.Bx 4.2 . -In -.Fx 5.0 , -they reappeared conforming to -.St -p1003.1-2001 . diff --git a/lib/libc/stdlib/insque.c b/lib/libc/stdlib/insque.c deleted file mode 100644 index 388e4d5..0000000 --- a/lib/libc/stdlib/insque.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Initial implementation: - * Copyright (c) 2002 Robert Drehmel - * All rights reserved. - * - * As long as the above copyright statement and this notice remain - * unchanged, you can do what ever you want with this file. - */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#define _SEARCH_PRIVATE -#include <search.h> -#ifdef DEBUG -#include <stdio.h> -#else -#include <stdlib.h> /* for NULL */ -#endif - -void -insque(void *element, void *pred) -{ - struct que_elem *prev, *next, *elem; - - elem = (struct que_elem *)element; - prev = (struct que_elem *)pred; - - if (prev == NULL) { - elem->prev = elem->next = NULL; - return; - } - - next = prev->next; - if (next != NULL) { -#ifdef DEBUG - if (next->prev != prev) { - fprintf(stderr, "insque: Inconsistency detected:" - " next(%p)->prev(%p) != prev(%p)\n", - next, next->prev, prev); - } -#endif - next->prev = elem; - } - prev->next = elem; - elem->prev = prev; - elem->next = next; -} diff --git a/lib/libc/stdlib/l64a.c b/lib/libc/stdlib/l64a.c deleted file mode 100644 index bc10553..0000000 --- a/lib/libc/stdlib/l64a.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Written by J.T. Conklin <jtc@NetBSD.org>. - * Public domain. - */ - -#if 0 -#if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: l64a.c,v 1.13 2003/07/26 19:24:54 salo Exp $"); -#endif /* not lint */ -#endif - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stdlib.h> - -#define ADOT 46 /* ASCII '.' */ -#define ASLASH ADOT + 1 /* ASCII '/' */ -#define A0 48 /* ASCII '0' */ -#define AA 65 /* ASCII 'A' */ -#define Aa 97 /* ASCII 'a' */ - -char * -l64a(long value) -{ - static char buf[8]; - - (void)l64a_r(value, buf, sizeof(buf)); - return (buf); -} - -int -l64a_r(long value, char *buffer, int buflen) -{ - long v; - int digit; - - v = value & (long)0xffffffff; - for (; v != 0 && buflen > 1; buffer++, buflen--) { - digit = v & 0x3f; - if (digit < 2) - *buffer = digit + ADOT; - else if (digit < 12) - *buffer = digit + A0 - 2; - else if (digit < 38) - *buffer = digit + AA - 12; - else - *buffer = digit + Aa - 38; - v >>= 6; - } - return (v == 0 ? 0 : -1); -} diff --git a/lib/libc/stdlib/labs.3 b/lib/libc/stdlib/labs.3 deleted file mode 100644 index b714fe3..0000000 --- a/lib/libc/stdlib/labs.3 +++ /dev/null @@ -1,67 +0,0 @@ -.\" Copyright (c) 1990, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the American National Standards Committee X3, on Information -.\" Processing Systems. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)labs.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD$ -.\" -.Dd November 14, 2001 -.Dt LABS 3 -.Os -.Sh NAME -.Nm labs -.Nd return the absolute value of a long integer -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In stdlib.h -.Ft long -.Fn labs "long j" -.Sh DESCRIPTION -The -.Fn labs -function -returns the absolute value of the long integer -.Fa j . -.Sh SEE ALSO -.Xr abs 3 , -.Xr cabs 3 , -.Xr floor 3 , -.Xr imaxabs 3 , -.Xr llabs 3 , -.Xr math 3 -.Sh STANDARDS -The -.Fn labs -function -conforms to -.St -isoC . -.Sh BUGS -The absolute value of the most negative integer remains negative. diff --git a/lib/libc/stdlib/labs.c b/lib/libc/stdlib/labs.c deleted file mode 100644 index d22975e..0000000 --- a/lib/libc/stdlib/labs.c +++ /dev/null @@ -1,43 +0,0 @@ -/*- - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)labs.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stdlib.h> - -long -labs(j) - long j; -{ - return(j < 0 ? -j : j); -} diff --git a/lib/libc/stdlib/ldiv.3 b/lib/libc/stdlib/ldiv.3 deleted file mode 100644 index 221e68d..0000000 --- a/lib/libc/stdlib/ldiv.3 +++ /dev/null @@ -1,71 +0,0 @@ -.\" Copyright (c) 1990, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" Chris Torek and the American National Standards Committee X3, -.\" on Information Processing Systems. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)ldiv.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD$ -.\" -.Dd November 14, 2001 -.Dt LDIV 3 -.Os -.Sh NAME -.Nm ldiv -.Nd return quotient and remainder from division -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In stdlib.h -.Ft ldiv_t -.Fn ldiv "long num" "long denom" -.Sh DESCRIPTION -The -.Fn ldiv -function -computes the value -.Fa num Ns / Ns Fa denom -and returns the quotient and remainder in a structure named -.Vt ldiv_t -that contains two -.Vt long -members named -.Va quot -and -.Va rem . -.Sh SEE ALSO -.Xr div 3 , -.Xr imaxdiv 3 , -.Xr lldiv 3 , -.Xr math 3 -.Sh STANDARDS -The -.Fn ldiv -function -conforms to -.St -isoC-99 . diff --git a/lib/libc/stdlib/ldiv.c b/lib/libc/stdlib/ldiv.c deleted file mode 100644 index 0311d06..0000000 --- a/lib/libc/stdlib/ldiv.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Chris Torek. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)ldiv.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stdlib.h> /* ldiv_t */ - -ldiv_t -ldiv(num, denom) - long num, denom; -{ - ldiv_t r; - - /* see div.c for comments */ - - r.quot = num / denom; - r.rem = num % denom; - if (num >= 0 && r.rem < 0) { - r.quot++; - r.rem -= denom; - } - return (r); -} diff --git a/lib/libc/stdlib/llabs.3 b/lib/libc/stdlib/llabs.3 deleted file mode 100644 index 8c031a9..0000000 --- a/lib/libc/stdlib/llabs.3 +++ /dev/null @@ -1,62 +0,0 @@ -.\" Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org> -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $FreeBSD$ -.\" -.Dd November 14, 2001 -.Dt LLABS 3 -.Os -.Sh NAME -.Nm llabs -.Nd returns absolute value -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In stdlib.h -.Ft "long long" -.Fn llabs "long long j" -.Sh DESCRIPTION -The -.Fn llabs -function returns the absolute value of -.Fa j . -.Sh SEE ALSO -.Xr abs 3 , -.Xr fabs 3 , -.Xr hypot 3 , -.Xr imaxabs 3 , -.Xr labs 3 , -.Xr math 3 -.Sh STANDARDS -The -.Fn llabs -function conforms to -.St -isoC-99 . -.Sh HISTORY -The -.Fn llabs -function first appeared in -.Fx 5.0 . -.Sh BUGS -The absolute value of the most negative integer remains negative. diff --git a/lib/libc/stdlib/llabs.c b/lib/libc/stdlib/llabs.c deleted file mode 100644 index 2bfbada..0000000 --- a/lib/libc/stdlib/llabs.c +++ /dev/null @@ -1,36 +0,0 @@ -/*- - * Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stdlib.h> - -long long -llabs(long long j) -{ - return (j < 0 ? -j : j); -} diff --git a/lib/libc/stdlib/lldiv.3 b/lib/libc/stdlib/lldiv.3 deleted file mode 100644 index 976a997..0000000 --- a/lib/libc/stdlib/lldiv.3 +++ /dev/null @@ -1,73 +0,0 @@ -.\" Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org> -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $FreeBSD$ -.\" -.Dd November 14, 2001 -.Dt LLDIV 3 -.Os -.Sh NAME -.Nm lldiv -.Nd returns quotient and remainder -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In stdlib.h -.Ft lldiv_t -.Fn lldiv "long long numer" "long long denom" -.Sh DESCRIPTION -The -.Fn lldiv -function computes the value of -.Fa numer -divided by -.Fa denom -and returns the stored result in the form of the -.Vt lldiv_t -type. -.Pp -The -.Vt lldiv_t -type is defined as: -.Bd -literal -offset indent -typedef struct { - long long quot; /* Quotient. */ - long long rem; /* Remainder. */ -} lldiv_t; -.Ed -.Sh SEE ALSO -.Xr div 3 , -.Xr imaxdiv 3 , -.Xr ldiv 3 , -.Xr math 3 -.Sh STANDARDS -The -.Fn lldiv -function conforms to -.St -isoC-99 . -.Sh HISTORY -The -.Fn lldiv -function first appeared in -.Fx 5.0 . diff --git a/lib/libc/stdlib/lldiv.c b/lib/libc/stdlib/lldiv.c deleted file mode 100644 index b34b65e..0000000 --- a/lib/libc/stdlib/lldiv.c +++ /dev/null @@ -1,45 +0,0 @@ -/*- - * Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stdlib.h> - -/* See comments in div.c for implementation details. */ -lldiv_t -lldiv(long long numer, long long denom) -{ - lldiv_t retval; - - retval.quot = numer / denom; - retval.rem = numer % denom; - if (numer >= 0 && retval.rem < 0) { - retval.quot++; - retval.rem -= denom; - } - return (retval); -} diff --git a/lib/libc/stdlib/lsearch.3 b/lib/libc/stdlib/lsearch.3 deleted file mode 100644 index 5e76724..0000000 --- a/lib/libc/stdlib/lsearch.3 +++ /dev/null @@ -1,105 +0,0 @@ -.\" -.\" Initial implementation: -.\" Copyright (c) 2002 Robert Drehmel -.\" All rights reserved. -.\" -.\" As long as the above copyright statement and this notice remain -.\" unchanged, you can do what ever you want with this file. -.\" -.\" $FreeBSD$ -.\" -.Dd October 11, 2002 -.Dt LSEARCH 3 -.Os -.Sh NAME -.Nm lsearch , -.Nm lfind -.Nd linear search and append -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In search.h -.Ft "void *" -.Fo lsearch -.Fa "const void *key" "void *base" "size_t *nelp" "size_t width" -.Fa "int \*[lp]*compar\*[rp]\*[lp]const void *, const void *\*[rp]" -.Fc -.Ft "void *" -.Fo lfind -.Fa "const void *key" "const void *base" "size_t *nelp" "size_t width" -.Fa "int \*[lp]*compar\*[rp]\*[lp]const void *, const void *\*[rp]" -.Fc -.Sh DESCRIPTION -The -.Fn lsearch -and -.Fn lfind -functions walk linearly through an array and compare each element with -the one to be sought using a supplied comparison function. -.Pp -The -.Fa key -argument -points to an element that matches the one that is searched. -The array's address in memory is denoted by the -.Fa base -argument. -The width of one element (i.e., the size as returned by -.Fn sizeof ) -is passed as the -.Fa width -argument. -The number of valid elements contained in the array (not the number of -elements the array has space reserved for) is given in the integer pointed -to by -.Fa nelp . -The -.Fa compar -argument points to a function which compares its two arguments and returns -zero if they are matching, and non-zero otherwise. -.Pp -If no matching element was found in the array, -.Fn lsearch -copies -.Fa key -into the position after the last element and increments the -integer pointed to by -.Fa nelp . -.Sh RETURN VALUES -The -.Fn lsearch -and -.Fn lfind -functions -return a pointer to the first element found. -If no element was found, -.Fn lsearch -returns a pointer to the newly added element, whereas -.Fn lfind -returns -.Dv NULL . -Both functions return -.Dv NULL -if an error occurs. -.Sh SEE ALSO -.Xr bsearch 3 , -.Xr hsearch 3 , -.Xr tsearch 3 -.Sh STANDARDS -The -.Fn lsearch -and -.Fn lfind -functions conform to -.St -p1003.1-2001 . -.Sh HISTORY -The -.Fn lsearch -and -.Fn lfind -functions appeared in -.Bx 4.2 . -In -.Fx 5.0 , -they reappeared conforming to -.St -p1003.1-2001 . diff --git a/lib/libc/stdlib/lsearch.c b/lib/libc/stdlib/lsearch.c deleted file mode 100644 index e4d1dd5..0000000 --- a/lib/libc/stdlib/lsearch.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Initial implementation: - * Copyright (c) 2002 Robert Drehmel - * All rights reserved. - * - * As long as the above copyright statement and this notice remain - * unchanged, you can do what ever you want with this file. - */ -#include <sys/types.h> -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#define _SEARCH_PRIVATE -#include <search.h> -#include <stdint.h> /* for uint8_t */ -#include <stdlib.h> /* for NULL */ -#include <string.h> /* for memcpy() prototype */ - -static void *lwork(const void *, const void *, size_t *, size_t, - int (*)(const void *, const void *), int); - -void *lsearch(const void *key, void *base, size_t *nelp, size_t width, - int (*compar)(const void *, const void *)) -{ - - return (lwork(key, base, nelp, width, compar, 1)); -} - -void *lfind(const void *key, const void *base, size_t *nelp, size_t width, - int (*compar)(const void *, const void *)) -{ - - return (lwork(key, base, nelp, width, compar, 0)); -} - -static void * -lwork(const void *key, const void *base, size_t *nelp, size_t width, - int (*compar)(const void *, const void *), int addelem) -{ - uint8_t *ep, *endp; - - /* - * Cast to an integer value first to avoid the warning for removing - * 'const' via a cast. - */ - ep = (uint8_t *)(uintptr_t)base; - for (endp = (uint8_t *)(ep + width * *nelp); ep < endp; ep += width) { - if (compar(key, ep) == 0) - return (ep); - } - - /* lfind() shall return when the key was not found. */ - if (!addelem) - return (NULL); - - /* - * lsearch() adds the key to the end of the table and increments - * the number of elements. - */ - memcpy(endp, key, width); - ++*nelp; - - return (endp); -} diff --git a/lib/libc/stdlib/malloc.3 b/lib/libc/stdlib/malloc.3 deleted file mode 100644 index 9f49b2e..0000000 --- a/lib/libc/stdlib/malloc.3 +++ /dev/null @@ -1,591 +0,0 @@ -.\" Copyright (c) 1980, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the American National Standards Committee X3, on Information -.\" Processing Systems. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)malloc.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD$ -.\" -.Dd January 31, 2010 -.Dt MALLOC 3 -.Os -.Sh NAME -.Nm malloc , calloc , realloc , free , reallocf , malloc_usable_size -.Nd general purpose memory allocation functions -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In stdlib.h -.Ft void * -.Fn malloc "size_t size" -.Ft void * -.Fn calloc "size_t number" "size_t size" -.Ft void * -.Fn realloc "void *ptr" "size_t size" -.Ft void * -.Fn reallocf "void *ptr" "size_t size" -.Ft void -.Fn free "void *ptr" -.Ft const char * -.Va _malloc_options ; -.Ft void -.Fn \*(lp*_malloc_message\*(rp "const char *p1" "const char *p2" "const char *p3" "const char *p4" -.In malloc_np.h -.Ft size_t -.Fn malloc_usable_size "const void *ptr" -.Sh DESCRIPTION -The -.Fn malloc -function allocates -.Fa size -bytes of uninitialized memory. -The allocated space is suitably aligned (after possible pointer coercion) -for storage of any type of object. -.Pp -The -.Fn calloc -function allocates space for -.Fa number -objects, -each -.Fa size -bytes in length. -The result is identical to calling -.Fn malloc -with an argument of -.Dq "number * size" , -with the exception that the allocated memory is explicitly initialized -to zero bytes. -.Pp -The -.Fn realloc -function changes the size of the previously allocated memory referenced by -.Fa ptr -to -.Fa size -bytes. -The contents of the memory are unchanged up to the lesser of the new and -old sizes. -If the new size is larger, -the contents of the newly allocated portion of the memory are undefined. -Upon success, the memory referenced by -.Fa ptr -is freed and a pointer to the newly allocated memory is returned. -Note that -.Fn realloc -and -.Fn reallocf -may move the memory allocation, resulting in a different return value than -.Fa ptr . -If -.Fa ptr -is -.Dv NULL , -the -.Fn realloc -function behaves identically to -.Fn malloc -for the specified size. -.Pp -The -.Fn reallocf -function is identical to the -.Fn realloc -function, except that it -will free the passed pointer when the requested memory cannot be allocated. -This is a -.Fx -specific API designed to ease the problems with traditional coding styles -for -.Fn realloc -causing memory leaks in libraries. -.Pp -The -.Fn free -function causes the allocated memory referenced by -.Fa ptr -to be made available for future allocations. -If -.Fa ptr -is -.Dv NULL , -no action occurs. -.Pp -The -.Fn malloc_usable_size -function returns the usable size of the allocation pointed to by -.Fa ptr . -The return value may be larger than the size that was requested during -allocation. -The -.Fn malloc_usable_size -function is not a mechanism for in-place -.Fn realloc ; -rather it is provided solely as a tool for introspection purposes. -Any discrepancy between the requested allocation size and the size reported by -.Fn malloc_usable_size -should not be depended on, since such behavior is entirely -implementation-dependent. -.Sh TUNING -Once, when the first call is made to one of these memory allocation -routines, various flags will be set or reset, which affects the -workings of this allocator implementation. -.Pp -The -.Dq name -of the file referenced by the symbolic link named -.Pa /etc/malloc.conf , -the value of the environment variable -.Ev MALLOC_OPTIONS , -and the string pointed to by the global variable -.Va _malloc_options -will be interpreted, in that order, from left to right as flags. -.Pp -Each flag is a single letter, optionally prefixed by a non-negative base 10 -integer repetition count. -For example, -.Dq 3N -is equivalent to -.Dq NNN . -Some flags control parameter magnitudes, where uppercase increases the -magnitude, and lowercase decreases the magnitude. -Other flags control boolean parameters, where uppercase indicates that a -behavior is set, or on, and lowercase means that a behavior is not set, or off. -.Bl -tag -width indent -.It A -All warnings (except for the warning about unknown -flags being set) become fatal. -The process will call -.Xr abort 3 -in these cases. -.It C -Double/halve the size of the maximum size class that is a multiple of the -cacheline size (64). -Above this size, subpage spacing (256 bytes) is used for size classes. -The default value is 512 bytes. -.It D -Use -.Xr sbrk 2 -to acquire memory in the data storage segment (DSS). -This option is enabled by default. -See the -.Dq M -option for related information and interactions. -.It E -Double/halve the size of the maximum medium size class. -The valid range is from one page to one half chunk. -The default value is 32 KiB. -.It F -Halve/double the per-arena minimum ratio of active to dirty pages. -Some dirty unused pages may be allowed to accumulate, within the limit set by -the ratio, before informing the kernel about at least half of those pages via -.Xr madvise 2 . -This provides the kernel with sufficient information to recycle dirty pages if -physical memory becomes scarce and the pages remain unused. -The default minimum ratio is 32:1; -.Ev MALLOC_OPTIONS=6F -will disable dirty page purging. -.It G -Double/halve the approximate interval (counted in terms of -thread-specific cache allocation/deallocation events) between full -thread-specific cache garbage collection sweeps. -Garbage collection is actually performed incrementally, one size -class at a time, in order to avoid large collection pauses. -The default sweep interval is 8192; -.Ev JEMALLOC_OPTIONS=14g -will disable garbage collection. -.It H -Double/halve the number of thread-specific cache slots per size -class. -When there are multiple threads, each thread uses a -thread-specific cache for small and medium objects. -Thread-specific caching allows many allocations to be satisfied -without performing any thread synchronization, at the cost of -increased memory use. -See the -.Dq G -option for related tuning information. -The default number of cache slots is 128; -.Ev JEMALLOC_OPTIONS=7h -will disable thread-specific caching. -Note that one cache slot per size class is not a valid -configuration due to implementation details. -.It J -Each byte of new memory allocated by -.Fn malloc , -.Fn realloc , -or -.Fn reallocf -will be initialized to 0xa5. -All memory returned by -.Fn free , -.Fn realloc , -or -.Fn reallocf -will be initialized to 0x5a. -This is intended for debugging and will impact performance negatively. -.It K -Double/halve the virtual memory chunk size. -The default chunk size is 4 MiB. -.It M -Use -.Xr mmap 2 -to acquire anonymously mapped memory. -This option is enabled by default. -If both the -.Dq D -and -.Dq M -options are enabled, the allocator prefers anonymous mappings over the DSS, -but allocation only fails if memory cannot be acquired via either method. -If neither option is enabled, then the -.Dq M -option is implicitly enabled in order to assure that there is a method for -acquiring memory. -.It N -Double/halve the number of arenas. -The default number of arenas is two times the number of CPUs, or one if there -is a single CPU. -.It P -Various statistics are printed at program exit via an -.Xr atexit 3 -function. -This has the potential to cause deadlock for a multi-threaded process that exits -while one or more threads are executing in the memory allocation functions. -Therefore, this option should only be used with care; it is primarily intended -as a performance tuning aid during application development. -.It Q -Double/halve the size of the maximum size class that is a multiple of the -quantum (8 or 16 bytes, depending on architecture). -Above this size, cacheline spacing is used for size classes. -The default value is 128 bytes. -.It U -Generate -.Dq utrace -entries for -.Xr ktrace 1 , -for all operations. -Consult the source for details on this option. -.It V -Attempting to allocate zero bytes will return a -.Dv NULL -pointer instead of a valid pointer. -(The default behavior is to make a minimal allocation and return a -pointer to it.) -This option is provided for System V compatibility. -This option is incompatible with the -.Dq X -option. -.It X -Rather than return failure for any allocation function, display a diagnostic -message on -.Dv STDERR_FILENO -and cause the program to drop core (using -.Xr abort 3 ) . -This option should be set at compile time by including the following in the -source code: -.Bd -literal -offset indent -_malloc_options = "X"; -.Ed -.It Z -Each byte of new memory allocated by -.Fn malloc , -.Fn realloc , -or -.Fn reallocf -will be initialized to 0. -Note that this initialization only happens once for each byte, so -.Fn realloc -and -.Fn reallocf -calls do not zero memory that was previously allocated. -This is intended for debugging and will impact performance negatively. -.El -.Pp -The -.Dq J -and -.Dq Z -options are intended for testing and debugging. -An application which changes its behavior when these options are used -is flawed. -.Sh IMPLEMENTATION NOTES -Traditionally, allocators have used -.Xr sbrk 2 -to obtain memory, which is suboptimal for several reasons, including race -conditions, increased fragmentation, and artificial limitations on maximum -usable memory. -This allocator uses both -.Xr sbrk 2 -and -.Xr mmap 2 -by default, but it can be configured at run time to use only one or the other. -If resource limits are not a primary concern, the preferred configuration is -.Ev MALLOC_OPTIONS=dM -or -.Ev MALLOC_OPTIONS=DM . -When so configured, the -.Ar datasize -resource limit has little practical effect for typical applications; use -.Ev MALLOC_OPTIONS=Dm -if that is a concern. -Regardless of allocator configuration, the -.Ar vmemoryuse -resource limit can be used to bound the total virtual memory used by a -process, as described in -.Xr limits 1 . -.Pp -This allocator uses multiple arenas in order to reduce lock contention for -threaded programs on multi-processor systems. -This works well with regard to threading scalability, but incurs some costs. -There is a small fixed per-arena overhead, and additionally, arenas manage -memory completely independently of each other, which means a small fixed -increase in overall memory fragmentation. -These overheads are not generally an issue, given the number of arenas normally -used. -Note that using substantially more arenas than the default is not likely to -improve performance, mainly due to reduced cache performance. -However, it may make sense to reduce the number of arenas if an application -does not make much use of the allocation functions. -.Pp -In addition to multiple arenas, this allocator supports thread-specific caching -for small and medium objects, in order to make it possible to completely avoid -synchronization for most small and medium allocation requests. -Such caching allows very fast allocation in the common case, but it increases -memory usage and fragmentation, since a bounded number of objects can remain -allocated in each thread cache. -.Pp -Memory is conceptually broken into equal-sized chunks, where the chunk size is -a power of two that is greater than the page size. -Chunks are always aligned to multiples of the chunk size. -This alignment makes it possible to find metadata for user objects very -quickly. -.Pp -User objects are broken into four categories according to size: small, medium, -large, and huge. -Small objects are smaller than one page. -Medium objects range from one page to an upper limit determined at run time (see -the -.Dq E -option). -Large objects are smaller than the chunk size. -Huge objects are a multiple of the chunk size. -Small, medium, and large objects are managed by arenas; huge objects are managed -separately in a single data structure that is shared by all threads. -Huge objects are used by applications infrequently enough that this single -data structure is not a scalability issue. -.Pp -Each chunk that is managed by an arena tracks its contents as runs of -contiguous pages (unused, backing a set of small or medium objects, or backing -one large object). -The combination of chunk alignment and chunk page maps makes it possible to -determine all metadata regarding small and large allocations in constant time. -.Pp -Small and medium objects are managed in groups by page runs. -Each run maintains a bitmap that tracks which regions are in use. -Allocation requests that are no more than half the quantum (8 or 16, depending -on architecture) are rounded up to the nearest power of two. -Allocation requests that are more than half the quantum, but no more than the -minimum cacheline-multiple size class (see the -.Dq Q -option) are rounded up to the nearest multiple of the quantum. -Allocation requests that are more than the minimum cacheline-multiple size -class, but no more than the minimum subpage-multiple size class (see the -.Dq C -option) are rounded up to the nearest multiple of the cacheline size (64). -Allocation requests that are more than the minimum subpage-multiple size class, -but no more than the maximum subpage-multiple size class are rounded up to the -nearest multiple of the subpage size (256). -Allocation requests that are more than the maximum subpage-multiple size class, -but no more than the maximum medium size class (see the -.Dq M -option) are rounded up to the nearest medium size class; spacing is an -automatically determined power of two and ranges from the subpage size to the -page size. -Allocation requests that are more than the maximum medium size class, but small -enough to fit in an arena-managed chunk (see the -.Dq K -option), are rounded up to the nearest run size. -Allocation requests that are too large to fit in an arena-managed chunk are -rounded up to the nearest multiple of the chunk size. -.Pp -Allocations are packed tightly together, which can be an issue for -multi-threaded applications. -If you need to assure that allocations do not suffer from cacheline sharing, -round your allocation requests up to the nearest multiple of the cacheline -size. -.Sh DEBUGGING MALLOC PROBLEMS -The first thing to do is to set the -.Dq A -option. -This option forces a coredump (if possible) at the first sign of trouble, -rather than the normal policy of trying to continue if at all possible. -.Pp -It is probably also a good idea to recompile the program with suitable -options and symbols for debugger support. -.Pp -If the program starts to give unusual results, coredump or generally behave -differently without emitting any of the messages mentioned in the next -section, it is likely because it depends on the storage being filled with -zero bytes. -Try running it with the -.Dq Z -option set; -if that improves the situation, this diagnosis has been confirmed. -If the program still misbehaves, -the likely problem is accessing memory outside the allocated area. -.Pp -Alternatively, if the symptoms are not easy to reproduce, setting the -.Dq J -option may help provoke the problem. -.Pp -In truly difficult cases, the -.Dq U -option, if supported by the kernel, can provide a detailed trace of -all calls made to these functions. -.Pp -Unfortunately this implementation does not provide much detail about -the problems it detects; the performance impact for storing such information -would be prohibitive. -There are a number of allocator implementations available on the Internet -which focus on detecting and pinpointing problems by trading performance for -extra sanity checks and detailed diagnostics. -.Sh DIAGNOSTIC MESSAGES -If any of the memory allocation/deallocation functions detect an error or -warning condition, a message will be printed to file descriptor -.Dv STDERR_FILENO . -Errors will result in the process dumping core. -If the -.Dq A -option is set, all warnings are treated as errors. -.Pp -The -.Va _malloc_message -variable allows the programmer to override the function which emits the text -strings forming the errors and warnings if for some reason the -.Dv STDERR_FILENO -file descriptor is not suitable for this. -Please note that doing anything which tries to allocate memory in this function -is likely to result in a crash or deadlock. -.Pp -All messages are prefixed by -.Dq Ao Ar progname Ac Ns Li : (malloc) . -.Sh RETURN VALUES -The -.Fn malloc -and -.Fn calloc -functions return a pointer to the allocated memory if successful; otherwise -a -.Dv NULL -pointer is returned and -.Va errno -is set to -.Er ENOMEM . -.Pp -The -.Fn realloc -and -.Fn reallocf -functions return a pointer, possibly identical to -.Fa ptr , -to the allocated memory -if successful; otherwise a -.Dv NULL -pointer is returned, and -.Va errno -is set to -.Er ENOMEM -if the error was the result of an allocation failure. -The -.Fn realloc -function always leaves the original buffer intact -when an error occurs, whereas -.Fn reallocf -deallocates it in this case. -.Pp -The -.Fn free -function returns no value. -.Pp -The -.Fn malloc_usable_size -function returns the usable size of the allocation pointed to by -.Fa ptr . -.Sh ENVIRONMENT -The following environment variables affect the execution of the allocation -functions: -.Bl -tag -width ".Ev MALLOC_OPTIONS" -.It Ev MALLOC_OPTIONS -If the environment variable -.Ev MALLOC_OPTIONS -is set, the characters it contains will be interpreted as flags to the -allocation functions. -.El -.Sh EXAMPLES -To dump core whenever a problem occurs: -.Bd -literal -offset indent -ln -s 'A' /etc/malloc.conf -.Ed -.Pp -To specify in the source that a program does no return value checking -on calls to these functions: -.Bd -literal -offset indent -_malloc_options = "X"; -.Ed -.Sh SEE ALSO -.Xr limits 1 , -.Xr madvise 2 , -.Xr mmap 2 , -.Xr sbrk 2 , -.Xr alloca 3 , -.Xr atexit 3 , -.Xr getpagesize 3 , -.Xr getpagesizes 3 , -.Xr memory 3 , -.Xr posix_memalign 3 -.Sh STANDARDS -The -.Fn malloc , -.Fn calloc , -.Fn realloc -and -.Fn free -functions conform to -.St -isoC . -.Sh HISTORY -The -.Fn reallocf -function first appeared in -.Fx 3.0 . -.Pp -The -.Fn malloc_usable_size -function first appeared in -.Fx 7.0 . diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c deleted file mode 100644 index f1a13ef..0000000 --- a/lib/libc/stdlib/malloc.c +++ /dev/null @@ -1,6248 +0,0 @@ -/*- - * Copyright (C) 2006-2010 Jason Evans <jasone@FreeBSD.org>. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice(s), this list of conditions and the following disclaimer as - * the first lines of this file unmodified other than the possible - * addition of one or more copyright notices. - * 2. Redistributions in binary form must reproduce the above copyright - * notice(s), this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ******************************************************************************* - * - * This allocator implementation is designed to provide scalable performance - * for multi-threaded programs on multi-processor systems. The following - * features are included for this purpose: - * - * + Multiple arenas are used if there are multiple CPUs, which reduces lock - * contention and cache sloshing. - * - * + Thread-specific caching is used if there are multiple threads, which - * reduces the amount of locking. - * - * + Cache line sharing between arenas is avoided for internal data - * structures. - * - * + Memory is managed in chunks and runs (chunks can be split into runs), - * rather than as individual pages. This provides a constant-time - * mechanism for associating allocations with particular arenas. - * - * Allocation requests are rounded up to the nearest size class, and no record - * of the original request size is maintained. Allocations are broken into - * categories according to size class. Assuming runtime defaults, 4 KiB pages - * and a 16 byte quantum on a 32-bit system, the size classes in each category - * are as follows: - * - * |========================================| - * | Category | Subcategory | Size | - * |========================================| - * | Small | Tiny | 2 | - * | | | 4 | - * | | | 8 | - * | |------------------+----------| - * | | Quantum-spaced | 16 | - * | | | 32 | - * | | | 48 | - * | | | ... | - * | | | 96 | - * | | | 112 | - * | | | 128 | - * | |------------------+----------| - * | | Cacheline-spaced | 192 | - * | | | 256 | - * | | | 320 | - * | | | 384 | - * | | | 448 | - * | | | 512 | - * | |------------------+----------| - * | | Sub-page | 760 | - * | | | 1024 | - * | | | 1280 | - * | | | ... | - * | | | 3328 | - * | | | 3584 | - * | | | 3840 | - * |========================================| - * | Medium | 4 KiB | - * | | 6 KiB | - * | | 8 KiB | - * | | ... | - * | | 28 KiB | - * | | 30 KiB | - * | | 32 KiB | - * |========================================| - * | Large | 36 KiB | - * | | 40 KiB | - * | | 44 KiB | - * | | ... | - * | | 1012 KiB | - * | | 1016 KiB | - * | | 1020 KiB | - * |========================================| - * | Huge | 1 MiB | - * | | 2 MiB | - * | | 3 MiB | - * | | ... | - * |========================================| - * - * Different mechanisms are used accoding to category: - * - * Small/medium : Each size class is segregated into its own set of runs. - * Each run maintains a bitmap of which regions are - * free/allocated. - * - * Large : Each allocation is backed by a dedicated run. Metadata are stored - * in the associated arena chunk header maps. - * - * Huge : Each allocation is backed by a dedicated contiguous set of chunks. - * Metadata are stored in a separate red-black tree. - * - ******************************************************************************* - */ - -/* - * MALLOC_PRODUCTION disables assertions and statistics gathering. It also - * defaults the A and J runtime options to off. These settings are appropriate - * for production systems. - */ -/* #define MALLOC_PRODUCTION */ - -#ifndef MALLOC_PRODUCTION - /* - * MALLOC_DEBUG enables assertions and other sanity checks, and disables - * inline functions. - */ -# define MALLOC_DEBUG - - /* MALLOC_STATS enables statistics calculation. */ -# define MALLOC_STATS -#endif - -/* - * MALLOC_TINY enables support for tiny objects, which are smaller than one - * quantum. - */ -#define MALLOC_TINY - -/* - * MALLOC_TCACHE enables a thread-specific caching layer for small and medium - * objects. This makes it possible to allocate/deallocate objects without any - * locking when the cache is in the steady state. - */ -#define MALLOC_TCACHE - -/* - * MALLOC_DSS enables use of sbrk(2) to allocate chunks from the data storage - * segment (DSS). In an ideal world, this functionality would be completely - * unnecessary, but we are burdened by history and the lack of resource limits - * for anonymous mapped memory. - */ -#define MALLOC_DSS - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include "libc_private.h" -#ifdef MALLOC_DEBUG -# define _LOCK_DEBUG -#endif -#include "spinlock.h" -#include "namespace.h" -#include <sys/mman.h> -#include <sys/param.h> -#include <sys/time.h> -#include <sys/types.h> -#include <sys/sysctl.h> -#include <sys/uio.h> -#include <sys/ktrace.h> /* Must come after several other sys/ includes. */ - -#include <machine/cpufunc.h> -#include <machine/param.h> -#include <machine/vmparam.h> - -#include <errno.h> -#include <limits.h> -#include <link.h> -#include <pthread.h> -#include <sched.h> -#include <stdarg.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdint.h> -#include <inttypes.h> -#include <stdlib.h> -#include <string.h> -#include <strings.h> -#include <unistd.h> - -#include "un-namespace.h" - -#include "libc_private.h" - -#define RB_COMPACT -#include "rb.h" -#if (defined(MALLOC_TCACHE) && defined(MALLOC_STATS)) -#include "qr.h" -#include "ql.h" -#endif - -#ifdef MALLOC_DEBUG - /* Disable inlining to make debugging easier. */ -# define inline -#endif - -/* Size of stack-allocated buffer passed to strerror_r(). */ -#define STRERROR_BUF 64 - -/* - * Minimum alignment of allocations is 2^LG_QUANTUM bytes. - */ -#ifdef __i386__ -# define LG_QUANTUM 4 -# define LG_SIZEOF_PTR 2 -# define CPU_SPINWAIT __asm__ volatile("pause") -# define TLS_MODEL __attribute__((tls_model("initial-exec"))) -#endif -#ifdef __ia64__ -# define LG_QUANTUM 4 -# define LG_SIZEOF_PTR 3 -# define TLS_MODEL /* default */ -#endif -#ifdef __alpha__ -# define LG_QUANTUM 4 -# define LG_SIZEOF_PTR 3 -# define NO_TLS -#endif -#ifdef __sparc64__ -# define LG_QUANTUM 4 -# define LG_SIZEOF_PTR 3 -# define NO_TLS -#endif -#ifdef __amd64__ -# define LG_QUANTUM 4 -# define LG_SIZEOF_PTR 3 -# define CPU_SPINWAIT __asm__ volatile("pause") -# define TLS_MODEL __attribute__((tls_model("initial-exec"))) -#endif -#ifdef __arm__ -# define LG_QUANTUM 3 -# define LG_SIZEOF_PTR 2 -# define NO_TLS -#endif -#ifdef __mips__ -# define LG_QUANTUM 3 -# define LG_SIZEOF_PTR 2 -# define NO_TLS -#endif -#ifdef __powerpc64__ -# define LG_QUANTUM 4 -# define LG_SIZEOF_PTR 3 -# define TLS_MODEL /* default */ -#elif defined(__powerpc__) -# define LG_QUANTUM 4 -# define LG_SIZEOF_PTR 2 -# define TLS_MODEL /* default */ -#endif -#ifdef __s390x__ -# define LG_QUANTUM 4 -#endif - -#define QUANTUM ((size_t)(1U << LG_QUANTUM)) -#define QUANTUM_MASK (QUANTUM - 1) - -#define SIZEOF_PTR (1U << LG_SIZEOF_PTR) - -/* sizeof(int) == (1U << LG_SIZEOF_INT). */ -#ifndef LG_SIZEOF_INT -# define LG_SIZEOF_INT 2 -#endif - -/* We can't use TLS in non-PIC programs, since TLS relies on loader magic. */ -#if (!defined(PIC) && !defined(NO_TLS)) -# define NO_TLS -#endif - -#ifdef NO_TLS - /* MALLOC_TCACHE requires TLS. */ -# ifdef MALLOC_TCACHE -# undef MALLOC_TCACHE -# endif -#endif - -/* - * Size and alignment of memory chunks that are allocated by the OS's virtual - * memory system. - */ -#define LG_CHUNK_DEFAULT 22 - -/* - * The minimum ratio of active:dirty pages per arena is computed as: - * - * (nactive >> opt_lg_dirty_mult) >= ndirty - * - * So, supposing that opt_lg_dirty_mult is 5, there can be no less than 32 - * times as many active pages as dirty pages. - */ -#define LG_DIRTY_MULT_DEFAULT 5 - -/* - * Maximum size of L1 cache line. This is used to avoid cache line aliasing. - * In addition, this controls the spacing of cacheline-spaced size classes. - */ -#define LG_CACHELINE 6 -#define CACHELINE ((size_t)(1U << LG_CACHELINE)) -#define CACHELINE_MASK (CACHELINE - 1) - -/* - * Subpages are an artificially designated partitioning of pages. Their only - * purpose is to support subpage-spaced size classes. - * - * There must be at least 4 subpages per page, due to the way size classes are - * handled. - */ -#define LG_SUBPAGE 8 -#define SUBPAGE ((size_t)(1U << LG_SUBPAGE)) -#define SUBPAGE_MASK (SUBPAGE - 1) - -#ifdef MALLOC_TINY - /* Smallest size class to support. */ -# define LG_TINY_MIN 1 -#endif - -/* - * Maximum size class that is a multiple of the quantum, but not (necessarily) - * a power of 2. Above this size, allocations are rounded up to the nearest - * power of 2. - */ -#define LG_QSPACE_MAX_DEFAULT 7 - -/* - * Maximum size class that is a multiple of the cacheline, but not (necessarily) - * a power of 2. Above this size, allocations are rounded up to the nearest - * power of 2. - */ -#define LG_CSPACE_MAX_DEFAULT 9 - -/* - * Maximum medium size class. This must not be more than 1/4 of a chunk - * (LG_MEDIUM_MAX_DEFAULT <= LG_CHUNK_DEFAULT - 2). - */ -#define LG_MEDIUM_MAX_DEFAULT 15 - -/* - * RUN_MAX_OVRHD indicates maximum desired run header overhead. Runs are sized - * as small as possible such that this setting is still honored, without - * violating other constraints. The goal is to make runs as small as possible - * without exceeding a per run external fragmentation threshold. - * - * We use binary fixed point math for overhead computations, where the binary - * point is implicitly RUN_BFP bits to the left. - * - * Note that it is possible to set RUN_MAX_OVRHD low enough that it cannot be - * honored for some/all object sizes, since there is one bit of header overhead - * per object (plus a constant). This constraint is relaxed (ignored) for runs - * that are so small that the per-region overhead is greater than: - * - * (RUN_MAX_OVRHD / (reg_size << (3+RUN_BFP)) - */ -#define RUN_BFP 12 -/* \/ Implicit binary fixed point. */ -#define RUN_MAX_OVRHD 0x0000003dU -#define RUN_MAX_OVRHD_RELAX 0x00001800U - -/* Put a cap on small object run size. This overrides RUN_MAX_OVRHD. */ -#define RUN_MAX_SMALL \ - (arena_maxclass <= (1U << (CHUNK_MAP_LG_PG_RANGE + PAGE_SHIFT)) \ - ? arena_maxclass : (1U << (CHUNK_MAP_LG_PG_RANGE + \ - PAGE_SHIFT))) - -/* - * Hyper-threaded CPUs may need a special instruction inside spin loops in - * order to yield to another virtual CPU. If no such instruction is defined - * above, make CPU_SPINWAIT a no-op. - */ -#ifndef CPU_SPINWAIT -# define CPU_SPINWAIT -#endif - -/* - * Adaptive spinning must eventually switch to blocking, in order to avoid the - * potential for priority inversion deadlock. Backing off past a certain point - * can actually waste time. - */ -#define LG_SPIN_LIMIT 11 - -#ifdef MALLOC_TCACHE - /* - * Default number of cache slots for each bin in the thread cache (0: - * disabled). - */ -# define LG_TCACHE_NSLOTS_DEFAULT 7 - /* - * (1U << opt_lg_tcache_gc_sweep) is the approximate number of - * allocation events between full GC sweeps (-1: disabled). Integer - * rounding may cause the actual number to be slightly higher, since GC is - * performed incrementally. - */ -# define LG_TCACHE_GC_SWEEP_DEFAULT 13 -#endif - -/******************************************************************************/ - -/* - * Mutexes based on spinlocks. We can't use normal pthread spinlocks in all - * places, because they require malloc()ed memory, which causes bootstrapping - * issues in some cases. - */ -typedef struct { - spinlock_t lock; -} malloc_mutex_t; - -/* Set to true once the allocator has been initialized. */ -static bool malloc_initialized = false; - -/* Used to avoid initialization races. */ -static malloc_mutex_t init_lock = {_SPINLOCK_INITIALIZER}; - -/******************************************************************************/ -/* - * Statistics data structures. - */ - -#ifdef MALLOC_STATS - -#ifdef MALLOC_TCACHE -typedef struct tcache_bin_stats_s tcache_bin_stats_t; -struct tcache_bin_stats_s { - /* - * Number of allocation requests that corresponded to the size of this - * bin. - */ - uint64_t nrequests; -}; -#endif - -typedef struct malloc_bin_stats_s malloc_bin_stats_t; -struct malloc_bin_stats_s { - /* - * Number of allocation requests that corresponded to the size of this - * bin. - */ - uint64_t nrequests; - -#ifdef MALLOC_TCACHE - /* Number of tcache fills from this bin. */ - uint64_t nfills; - - /* Number of tcache flushes to this bin. */ - uint64_t nflushes; -#endif - - /* Total number of runs created for this bin's size class. */ - uint64_t nruns; - - /* - * Total number of runs reused by extracting them from the runs tree for - * this bin's size class. - */ - uint64_t reruns; - - /* High-water mark for this bin. */ - size_t highruns; - - /* Current number of runs in this bin. */ - size_t curruns; -}; - -typedef struct malloc_large_stats_s malloc_large_stats_t; -struct malloc_large_stats_s { - /* - * Number of allocation requests that corresponded to this size class. - */ - uint64_t nrequests; - - /* High-water mark for this size class. */ - size_t highruns; - - /* Current number of runs of this size class. */ - size_t curruns; -}; - -typedef struct arena_stats_s arena_stats_t; -struct arena_stats_s { - /* Number of bytes currently mapped. */ - size_t mapped; - - /* - * Total number of purge sweeps, total number of madvise calls made, - * and total pages purged in order to keep dirty unused memory under - * control. - */ - uint64_t npurge; - uint64_t nmadvise; - uint64_t purged; - - /* Per-size-category statistics. */ - size_t allocated_small; - uint64_t nmalloc_small; - uint64_t ndalloc_small; - - size_t allocated_medium; - uint64_t nmalloc_medium; - uint64_t ndalloc_medium; - - size_t allocated_large; - uint64_t nmalloc_large; - uint64_t ndalloc_large; - - /* - * One element for each possible size class, including sizes that - * overlap with bin size classes. This is necessary because ipalloc() - * sometimes has to use such large objects in order to assure proper - * alignment. - */ - malloc_large_stats_t *lstats; -}; - -typedef struct chunk_stats_s chunk_stats_t; -struct chunk_stats_s { - /* Number of chunks that were allocated. */ - uint64_t nchunks; - - /* High-water mark for number of chunks allocated. */ - size_t highchunks; - - /* - * Current number of chunks allocated. This value isn't maintained for - * any other purpose, so keep track of it in order to be able to set - * highchunks. - */ - size_t curchunks; -}; - -#endif /* #ifdef MALLOC_STATS */ - -/******************************************************************************/ -/* - * Extent data structures. - */ - -/* Tree of extents. */ -typedef struct extent_node_s extent_node_t; -struct extent_node_s { -#ifdef MALLOC_DSS - /* Linkage for the size/address-ordered tree. */ - rb_node(extent_node_t) link_szad; -#endif - - /* Linkage for the address-ordered tree. */ - rb_node(extent_node_t) link_ad; - - /* Pointer to the extent that this tree node is responsible for. */ - void *addr; - - /* Total region size. */ - size_t size; -}; -typedef rb_tree(extent_node_t) extent_tree_t; - -/******************************************************************************/ -/* - * Arena data structures. - */ - -typedef struct arena_s arena_t; -typedef struct arena_bin_s arena_bin_t; - -/* Each element of the chunk map corresponds to one page within the chunk. */ -typedef struct arena_chunk_map_s arena_chunk_map_t; -struct arena_chunk_map_s { - /* - * Linkage for run trees. There are two disjoint uses: - * - * 1) arena_t's runs_avail tree. - * 2) arena_run_t conceptually uses this linkage for in-use non-full - * runs, rather than directly embedding linkage. - */ - rb_node(arena_chunk_map_t) link; - - /* - * Run address (or size) and various flags are stored together. The bit - * layout looks like (assuming 32-bit system): - * - * ???????? ???????? ????cccc ccccdzla - * - * ? : Unallocated: Run address for first/last pages, unset for internal - * pages. - * Small/medium: Don't care. - * Large: Run size for first page, unset for trailing pages. - * - : Unused. - * c : refcount (could overflow for PAGE_SIZE >= 128 KiB) - * d : dirty? - * z : zeroed? - * l : large? - * a : allocated? - * - * Following are example bit patterns for the three types of runs. - * - * p : run page offset - * s : run size - * x : don't care - * - : 0 - * [dzla] : bit set - * - * Unallocated: - * ssssssss ssssssss ssss---- -------- - * xxxxxxxx xxxxxxxx xxxx---- ----d--- - * ssssssss ssssssss ssss---- -----z-- - * - * Small/medium: - * pppppppp ppppcccc cccccccc cccc---a - * pppppppp ppppcccc cccccccc cccc---a - * pppppppp ppppcccc cccccccc cccc---a - * - * Large: - * ssssssss ssssssss ssss---- ------la - * -------- -------- -------- ------la - * -------- -------- -------- ------la - */ - size_t bits; -#define CHUNK_MAP_PG_MASK ((size_t)0xfff00000U) -#define CHUNK_MAP_PG_SHIFT 20 -#define CHUNK_MAP_LG_PG_RANGE 12 - -#define CHUNK_MAP_RC_MASK ((size_t)0xffff0U) -#define CHUNK_MAP_RC_ONE ((size_t)0x00010U) - -#define CHUNK_MAP_FLAGS_MASK ((size_t)0xfU) -#define CHUNK_MAP_DIRTY ((size_t)0x8U) -#define CHUNK_MAP_ZEROED ((size_t)0x4U) -#define CHUNK_MAP_LARGE ((size_t)0x2U) -#define CHUNK_MAP_ALLOCATED ((size_t)0x1U) -#define CHUNK_MAP_KEY (CHUNK_MAP_DIRTY | CHUNK_MAP_ALLOCATED) -}; -typedef rb_tree(arena_chunk_map_t) arena_avail_tree_t; -typedef rb_tree(arena_chunk_map_t) arena_run_tree_t; - -/* Arena chunk header. */ -typedef struct arena_chunk_s arena_chunk_t; -struct arena_chunk_s { - /* Arena that owns the chunk. */ - arena_t *arena; - - /* Linkage for the arena's chunks_dirty tree. */ - rb_node(arena_chunk_t) link_dirty; - - /* - * True if the chunk is currently in the chunks_dirty tree, due to - * having at some point contained one or more dirty pages. Removal - * from chunks_dirty is lazy, so (dirtied && ndirty == 0) is possible. - */ - bool dirtied; - - /* Number of dirty pages. */ - size_t ndirty; - - /* Map of pages within chunk that keeps track of free/large/small. */ - arena_chunk_map_t map[1]; /* Dynamically sized. */ -}; -typedef rb_tree(arena_chunk_t) arena_chunk_tree_t; - -typedef struct arena_run_s arena_run_t; -struct arena_run_s { -#ifdef MALLOC_DEBUG - uint32_t magic; -# define ARENA_RUN_MAGIC 0x384adf93 -#endif - - /* Bin this run is associated with. */ - arena_bin_t *bin; - - /* Index of first element that might have a free region. */ - unsigned regs_minelm; - - /* Number of free regions in run. */ - unsigned nfree; - - /* Bitmask of in-use regions (0: in use, 1: free). */ - unsigned regs_mask[1]; /* Dynamically sized. */ -}; - -struct arena_bin_s { - /* - * Current run being used to service allocations of this bin's size - * class. - */ - arena_run_t *runcur; - - /* - * Tree of non-full runs. This tree is used when looking for an - * existing run when runcur is no longer usable. We choose the - * non-full run that is lowest in memory; this policy tends to keep - * objects packed well, and it can also help reduce the number of - * almost-empty chunks. - */ - arena_run_tree_t runs; - - /* Size of regions in a run for this bin's size class. */ - size_t reg_size; - - /* Total size of a run for this bin's size class. */ - size_t run_size; - - /* Total number of regions in a run for this bin's size class. */ - uint32_t nregs; - - /* Number of elements in a run's regs_mask for this bin's size class. */ - uint32_t regs_mask_nelms; - - /* Offset of first region in a run for this bin's size class. */ - uint32_t reg0_offset; - -#ifdef MALLOC_STATS - /* Bin statistics. */ - malloc_bin_stats_t stats; -#endif -}; - -#ifdef MALLOC_TCACHE -typedef struct tcache_s tcache_t; -#endif - -struct arena_s { -#ifdef MALLOC_DEBUG - uint32_t magic; -# define ARENA_MAGIC 0x947d3d24 -#endif - - /* All operations on this arena require that lock be locked. */ - pthread_mutex_t lock; - -#ifdef MALLOC_STATS - arena_stats_t stats; -# ifdef MALLOC_TCACHE - /* - * List of tcaches for extant threads associated with this arena. - * Stats from these are merged incrementally, and at exit. - */ - ql_head(tcache_t) tcache_ql; -# endif -#endif - - /* Tree of dirty-page-containing chunks this arena manages. */ - arena_chunk_tree_t chunks_dirty; - - /* - * In order to avoid rapid chunk allocation/deallocation when an arena - * oscillates right on the cusp of needing a new chunk, cache the most - * recently freed chunk. The spare is left in the arena's chunk trees - * until it is deleted. - * - * There is one spare chunk per arena, rather than one spare total, in - * order to avoid interactions between multiple threads that could make - * a single spare inadequate. - */ - arena_chunk_t *spare; - - /* Number of pages in active runs. */ - size_t nactive; - - /* - * Current count of pages within unused runs that are potentially - * dirty, and for which madvise(... MADV_FREE) has not been called. By - * tracking this, we can institute a limit on how much dirty unused - * memory is mapped for each arena. - */ - size_t ndirty; - - /* - * Size/address-ordered tree of this arena's available runs. This tree - * is used for first-best-fit run allocation. - */ - arena_avail_tree_t runs_avail; - - /* - * bins is used to store trees of free regions of the following sizes, - * assuming a 16-byte quantum, 4 KiB page size, and default - * MALLOC_OPTIONS. - * - * bins[i] | size | - * --------+--------+ - * 0 | 2 | - * 1 | 4 | - * 2 | 8 | - * --------+--------+ - * 3 | 16 | - * 4 | 32 | - * 5 | 48 | - * : : - * 8 | 96 | - * 9 | 112 | - * 10 | 128 | - * --------+--------+ - * 11 | 192 | - * 12 | 256 | - * 13 | 320 | - * 14 | 384 | - * 15 | 448 | - * 16 | 512 | - * --------+--------+ - * 17 | 768 | - * 18 | 1024 | - * 19 | 1280 | - * : : - * 27 | 3328 | - * 28 | 3584 | - * 29 | 3840 | - * --------+--------+ - * 30 | 4 KiB | - * 31 | 6 KiB | - * 33 | 8 KiB | - * : : - * 43 | 28 KiB | - * 44 | 30 KiB | - * 45 | 32 KiB | - * --------+--------+ - */ - arena_bin_t bins[1]; /* Dynamically sized. */ -}; - -/******************************************************************************/ -/* - * Thread cache data structures. - */ - -#ifdef MALLOC_TCACHE -typedef struct tcache_bin_s tcache_bin_t; -struct tcache_bin_s { -# ifdef MALLOC_STATS - tcache_bin_stats_t tstats; -# endif - unsigned low_water; /* Min # cached since last GC. */ - unsigned high_water; /* Max # cached since last GC. */ - unsigned ncached; /* # of cached objects. */ - void *slots[1]; /* Dynamically sized. */ -}; - -struct tcache_s { -# ifdef MALLOC_STATS - ql_elm(tcache_t) link; /* Used for aggregating stats. */ -# endif - arena_t *arena; /* This thread's arena. */ - unsigned ev_cnt; /* Event count since incremental GC. */ - unsigned next_gc_bin; /* Next bin to GC. */ - tcache_bin_t *tbins[1]; /* Dynamically sized. */ -}; -#endif - -/******************************************************************************/ -/* - * Data. - */ - -/* Number of CPUs. */ -static unsigned ncpus; - -/* Various bin-related settings. */ -#ifdef MALLOC_TINY /* Number of (2^n)-spaced tiny bins. */ -# define ntbins ((unsigned)(LG_QUANTUM - LG_TINY_MIN)) -#else -# define ntbins 0 -#endif -static unsigned nqbins; /* Number of quantum-spaced bins. */ -static unsigned ncbins; /* Number of cacheline-spaced bins. */ -static unsigned nsbins; /* Number of subpage-spaced bins. */ -static unsigned nmbins; /* Number of medium bins. */ -static unsigned nbins; -static unsigned mbin0; /* mbin offset (nbins - nmbins). */ -#ifdef MALLOC_TINY -# define tspace_max ((size_t)(QUANTUM >> 1)) -#endif -#define qspace_min QUANTUM -static size_t qspace_max; -static size_t cspace_min; -static size_t cspace_max; -static size_t sspace_min; -static size_t sspace_max; -#define small_maxclass sspace_max -#define medium_min PAGE_SIZE -static size_t medium_max; -#define bin_maxclass medium_max - -/* - * Soft limit on the number of medium size classes. Spacing between medium - * size classes never exceeds pagesize, which can force more than NBINS_MAX - * medium size classes. - */ -#define NMBINS_MAX 16 -/* Spacing between medium size classes. */ -static size_t lg_mspace; -static size_t mspace_mask; - -static uint8_t const *small_size2bin; -/* - * const_small_size2bin is a static constant lookup table that in the common - * case can be used as-is for small_size2bin. For dynamically linked programs, - * this avoids a page of memory overhead per process. - */ -#define S2B_1(i) i, -#define S2B_2(i) S2B_1(i) S2B_1(i) -#define S2B_4(i) S2B_2(i) S2B_2(i) -#define S2B_8(i) S2B_4(i) S2B_4(i) -#define S2B_16(i) S2B_8(i) S2B_8(i) -#define S2B_32(i) S2B_16(i) S2B_16(i) -#define S2B_64(i) S2B_32(i) S2B_32(i) -#define S2B_128(i) S2B_64(i) S2B_64(i) -#define S2B_256(i) S2B_128(i) S2B_128(i) -static const uint8_t const_small_size2bin[PAGE_SIZE - 255] = { - S2B_1(0xffU) /* 0 */ -#if (LG_QUANTUM == 4) -/* 64-bit system ************************/ -# ifdef MALLOC_TINY - S2B_2(0) /* 2 */ - S2B_2(1) /* 4 */ - S2B_4(2) /* 8 */ - S2B_8(3) /* 16 */ -# define S2B_QMIN 3 -# else - S2B_16(0) /* 16 */ -# define S2B_QMIN 0 -# endif - S2B_16(S2B_QMIN + 1) /* 32 */ - S2B_16(S2B_QMIN + 2) /* 48 */ - S2B_16(S2B_QMIN + 3) /* 64 */ - S2B_16(S2B_QMIN + 4) /* 80 */ - S2B_16(S2B_QMIN + 5) /* 96 */ - S2B_16(S2B_QMIN + 6) /* 112 */ - S2B_16(S2B_QMIN + 7) /* 128 */ -# define S2B_CMIN (S2B_QMIN + 8) -#else -/* 32-bit system ************************/ -# ifdef MALLOC_TINY - S2B_2(0) /* 2 */ - S2B_2(1) /* 4 */ - S2B_4(2) /* 8 */ -# define S2B_QMIN 2 -# else - S2B_8(0) /* 8 */ -# define S2B_QMIN 0 -# endif - S2B_8(S2B_QMIN + 1) /* 16 */ - S2B_8(S2B_QMIN + 2) /* 24 */ - S2B_8(S2B_QMIN + 3) /* 32 */ - S2B_8(S2B_QMIN + 4) /* 40 */ - S2B_8(S2B_QMIN + 5) /* 48 */ - S2B_8(S2B_QMIN + 6) /* 56 */ - S2B_8(S2B_QMIN + 7) /* 64 */ - S2B_8(S2B_QMIN + 8) /* 72 */ - S2B_8(S2B_QMIN + 9) /* 80 */ - S2B_8(S2B_QMIN + 10) /* 88 */ - S2B_8(S2B_QMIN + 11) /* 96 */ - S2B_8(S2B_QMIN + 12) /* 104 */ - S2B_8(S2B_QMIN + 13) /* 112 */ - S2B_8(S2B_QMIN + 14) /* 120 */ - S2B_8(S2B_QMIN + 15) /* 128 */ -# define S2B_CMIN (S2B_QMIN + 16) -#endif -/****************************************/ - S2B_64(S2B_CMIN + 0) /* 192 */ - S2B_64(S2B_CMIN + 1) /* 256 */ - S2B_64(S2B_CMIN + 2) /* 320 */ - S2B_64(S2B_CMIN + 3) /* 384 */ - S2B_64(S2B_CMIN + 4) /* 448 */ - S2B_64(S2B_CMIN + 5) /* 512 */ -# define S2B_SMIN (S2B_CMIN + 6) - S2B_256(S2B_SMIN + 0) /* 768 */ - S2B_256(S2B_SMIN + 1) /* 1024 */ - S2B_256(S2B_SMIN + 2) /* 1280 */ - S2B_256(S2B_SMIN + 3) /* 1536 */ - S2B_256(S2B_SMIN + 4) /* 1792 */ - S2B_256(S2B_SMIN + 5) /* 2048 */ - S2B_256(S2B_SMIN + 6) /* 2304 */ - S2B_256(S2B_SMIN + 7) /* 2560 */ - S2B_256(S2B_SMIN + 8) /* 2816 */ - S2B_256(S2B_SMIN + 9) /* 3072 */ - S2B_256(S2B_SMIN + 10) /* 3328 */ - S2B_256(S2B_SMIN + 11) /* 3584 */ - S2B_256(S2B_SMIN + 12) /* 3840 */ -#if (PAGE_SHIFT == 13) - S2B_256(S2B_SMIN + 13) /* 4096 */ - S2B_256(S2B_SMIN + 14) /* 4352 */ - S2B_256(S2B_SMIN + 15) /* 4608 */ - S2B_256(S2B_SMIN + 16) /* 4864 */ - S2B_256(S2B_SMIN + 17) /* 5120 */ - S2B_256(S2B_SMIN + 18) /* 5376 */ - S2B_256(S2B_SMIN + 19) /* 5632 */ - S2B_256(S2B_SMIN + 20) /* 5888 */ - S2B_256(S2B_SMIN + 21) /* 6144 */ - S2B_256(S2B_SMIN + 22) /* 6400 */ - S2B_256(S2B_SMIN + 23) /* 6656 */ - S2B_256(S2B_SMIN + 24) /* 6912 */ - S2B_256(S2B_SMIN + 25) /* 7168 */ - S2B_256(S2B_SMIN + 26) /* 7424 */ - S2B_256(S2B_SMIN + 27) /* 7680 */ - S2B_256(S2B_SMIN + 28) /* 7936 */ -#endif -}; -#undef S2B_1 -#undef S2B_2 -#undef S2B_4 -#undef S2B_8 -#undef S2B_16 -#undef S2B_32 -#undef S2B_64 -#undef S2B_128 -#undef S2B_256 -#undef S2B_QMIN -#undef S2B_CMIN -#undef S2B_SMIN - -/* Various chunk-related settings. */ -static size_t chunksize; -static size_t chunksize_mask; /* (chunksize - 1). */ -static size_t chunk_npages; -static size_t arena_chunk_header_npages; -static size_t arena_maxclass; /* Max size class for arenas. */ - -/********/ -/* - * Chunks. - */ - -/* Protects chunk-related data structures. */ -static malloc_mutex_t huge_mtx; - -/* Tree of chunks that are stand-alone huge allocations. */ -static extent_tree_t huge; - -#ifdef MALLOC_DSS -/* - * Protects sbrk() calls. This avoids malloc races among threads, though it - * does not protect against races with threads that call sbrk() directly. - */ -static malloc_mutex_t dss_mtx; -/* Base address of the DSS. */ -static void *dss_base; -/* Current end of the DSS, or ((void *)-1) if the DSS is exhausted. */ -static void *dss_prev; -/* Current upper limit on DSS addresses. */ -static void *dss_max; - -/* - * Trees of chunks that were previously allocated (trees differ only in node - * ordering). These are used when allocating chunks, in an attempt to re-use - * address space. Depending on function, different tree orderings are needed, - * which is why there are two trees with the same contents. - */ -static extent_tree_t dss_chunks_szad; -static extent_tree_t dss_chunks_ad; -#endif - -#ifdef MALLOC_STATS -/* Huge allocation statistics. */ -static uint64_t huge_nmalloc; -static uint64_t huge_ndalloc; -static size_t huge_allocated; -#endif - -/****************************/ -/* - * base (internal allocation). - */ - -/* - * Current pages that are being used for internal memory allocations. These - * pages are carved up in cacheline-size quanta, so that there is no chance of - * false cache line sharing. - */ -static void *base_pages; -static void *base_next_addr; -static void *base_past_addr; /* Addr immediately past base_pages. */ -static extent_node_t *base_nodes; -static malloc_mutex_t base_mtx; -#ifdef MALLOC_STATS -static size_t base_mapped; -#endif - -/********/ -/* - * Arenas. - */ - -/* - * Arenas that are used to service external requests. Not all elements of the - * arenas array are necessarily used; arenas are created lazily as needed. - */ -static arena_t **arenas; -static unsigned narenas; -#ifndef NO_TLS -static unsigned next_arena; -#endif -static pthread_mutex_t arenas_lock; /* Protects arenas initialization. */ - -#ifndef NO_TLS -/* - * Map of _pthread_self() --> arenas[???], used for selecting an arena to use - * for allocations. - */ -static __thread arena_t *arenas_map TLS_MODEL; -#endif - -#ifdef MALLOC_TCACHE -/* Map of thread-specific caches. */ -static __thread tcache_t *tcache_tls TLS_MODEL; - -/* - * Number of cache slots for each bin in the thread cache, or 0 if tcache is - * disabled. - */ -size_t tcache_nslots; - -/* Number of tcache allocation/deallocation events between incremental GCs. */ -unsigned tcache_gc_incr; -#endif - -/* - * Used by chunk_alloc_mmap() to decide whether to attempt the fast path and - * potentially avoid some system calls. We can get away without TLS here, - * since the state of mmap_unaligned only affects performance, rather than - * correct function. - */ -#ifndef NO_TLS -static __thread bool mmap_unaligned TLS_MODEL; -#else -static bool mmap_unaligned; -#endif - -#ifdef MALLOC_STATS -static malloc_mutex_t chunks_mtx; -/* Chunk statistics. */ -static chunk_stats_t stats_chunks; -#endif - -/*******************************/ -/* - * Runtime configuration options. - */ -const char *_malloc_options; - -#ifndef MALLOC_PRODUCTION -static bool opt_abort = true; -static bool opt_junk = true; -#else -static bool opt_abort = false; -static bool opt_junk = false; -#endif -#ifdef MALLOC_TCACHE -static size_t opt_lg_tcache_nslots = LG_TCACHE_NSLOTS_DEFAULT; -static ssize_t opt_lg_tcache_gc_sweep = LG_TCACHE_GC_SWEEP_DEFAULT; -#endif -#ifdef MALLOC_DSS -static bool opt_dss = true; -static bool opt_mmap = true; -#endif -static ssize_t opt_lg_dirty_mult = LG_DIRTY_MULT_DEFAULT; -static bool opt_stats_print = false; -static size_t opt_lg_qspace_max = LG_QSPACE_MAX_DEFAULT; -static size_t opt_lg_cspace_max = LG_CSPACE_MAX_DEFAULT; -static size_t opt_lg_medium_max = LG_MEDIUM_MAX_DEFAULT; -static size_t opt_lg_chunk = LG_CHUNK_DEFAULT; -static bool opt_utrace = false; -static bool opt_sysv = false; -static bool opt_xmalloc = false; -static bool opt_zero = false; -static int opt_narenas_lshift = 0; - -typedef struct { - void *p; - size_t s; - void *r; -} malloc_utrace_t; - -#define UTRACE(a, b, c) \ - if (opt_utrace) { \ - malloc_utrace_t ut; \ - ut.p = (a); \ - ut.s = (b); \ - ut.r = (c); \ - utrace(&ut, sizeof(ut)); \ - } - -/******************************************************************************/ -/* - * Begin function prototypes for non-inline static functions. - */ - -static void malloc_mutex_init(malloc_mutex_t *mutex); -static bool malloc_spin_init(pthread_mutex_t *lock); -#ifdef MALLOC_TINY -static size_t pow2_ceil(size_t x); -#endif -static void wrtmessage(const char *p1, const char *p2, const char *p3, - const char *p4); -#ifdef MALLOC_STATS -static void malloc_printf(const char *format, ...); -#endif -static char *umax2s(uintmax_t x, unsigned base, char *s); -#ifdef MALLOC_DSS -static bool base_pages_alloc_dss(size_t minsize); -#endif -static bool base_pages_alloc_mmap(size_t minsize); -static bool base_pages_alloc(size_t minsize); -static void *base_alloc(size_t size); -static void *base_calloc(size_t number, size_t size); -static extent_node_t *base_node_alloc(void); -static void base_node_dealloc(extent_node_t *node); -static void *pages_map(void *addr, size_t size); -static void pages_unmap(void *addr, size_t size); -#ifdef MALLOC_DSS -static void *chunk_alloc_dss(size_t size, bool *zero); -static void *chunk_recycle_dss(size_t size, bool *zero); -#endif -static void *chunk_alloc_mmap_slow(size_t size, bool unaligned); -static void *chunk_alloc_mmap(size_t size); -static void *chunk_alloc(size_t size, bool *zero); -#ifdef MALLOC_DSS -static extent_node_t *chunk_dealloc_dss_record(void *chunk, size_t size); -static bool chunk_dealloc_dss(void *chunk, size_t size); -#endif -static void chunk_dealloc_mmap(void *chunk, size_t size); -static void chunk_dealloc(void *chunk, size_t size); -#ifndef NO_TLS -static arena_t *choose_arena_hard(void); -#endif -static void arena_run_split(arena_t *arena, arena_run_t *run, size_t size, - bool large, bool zero); -static arena_chunk_t *arena_chunk_alloc(arena_t *arena); -static void arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk); -static arena_run_t *arena_run_alloc(arena_t *arena, size_t size, bool large, - bool zero); -static void arena_purge(arena_t *arena); -static void arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty); -static void arena_run_trim_head(arena_t *arena, arena_chunk_t *chunk, - arena_run_t *run, size_t oldsize, size_t newsize); -static void arena_run_trim_tail(arena_t *arena, arena_chunk_t *chunk, - arena_run_t *run, size_t oldsize, size_t newsize, bool dirty); -static arena_run_t *arena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin); -static void *arena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin); -static size_t arena_bin_run_size_calc(arena_bin_t *bin, size_t min_run_size); -#ifdef MALLOC_TCACHE -static void tcache_bin_fill(tcache_t *tcache, tcache_bin_t *tbin, - size_t binind); -static void *tcache_alloc_hard(tcache_t *tcache, tcache_bin_t *tbin, - size_t binind); -#endif -static void *arena_malloc_medium(arena_t *arena, size_t size, bool zero); -static void *arena_malloc_large(arena_t *arena, size_t size, bool zero); -static void *arena_palloc(arena_t *arena, size_t alignment, size_t size, - size_t alloc_size); -static bool arena_is_large(const void *ptr); -static size_t arena_salloc(const void *ptr); -static void -arena_dalloc_bin_run(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run, - arena_bin_t *bin); -#ifdef MALLOC_STATS -static void arena_stats_print(arena_t *arena); -#endif -static void stats_print_atexit(void); -#ifdef MALLOC_TCACHE -static void tcache_bin_flush(tcache_bin_t *tbin, size_t binind, - unsigned rem); -#endif -static void arena_dalloc_large(arena_t *arena, arena_chunk_t *chunk, - void *ptr); -#ifdef MALLOC_TCACHE -static void arena_dalloc_hard(arena_t *arena, arena_chunk_t *chunk, - void *ptr, arena_chunk_map_t *mapelm, tcache_t *tcache); -#endif -static void arena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk, - void *ptr, size_t size, size_t oldsize); -static bool arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, - void *ptr, size_t size, size_t oldsize); -static bool arena_ralloc_large(void *ptr, size_t size, size_t oldsize); -static void *arena_ralloc(void *ptr, size_t size, size_t oldsize); -static bool arena_new(arena_t *arena, unsigned ind); -static arena_t *arenas_extend(unsigned ind); -#ifdef MALLOC_TCACHE -static tcache_bin_t *tcache_bin_create(arena_t *arena); -static void tcache_bin_destroy(tcache_t *tcache, tcache_bin_t *tbin, - unsigned binind); -# ifdef MALLOC_STATS -static void tcache_stats_merge(tcache_t *tcache, arena_t *arena); -# endif -static tcache_t *tcache_create(arena_t *arena); -static void tcache_destroy(tcache_t *tcache); -#endif -static void *huge_malloc(size_t size, bool zero); -static void *huge_palloc(size_t alignment, size_t size); -static void *huge_ralloc(void *ptr, size_t size, size_t oldsize); -static void huge_dalloc(void *ptr); -static void malloc_stats_print(void); -#ifdef MALLOC_DEBUG -static void small_size2bin_validate(void); -#endif -static bool small_size2bin_init(void); -static bool small_size2bin_init_hard(void); -static unsigned malloc_ncpus(void); -static bool malloc_init_hard(void); - -/* - * End function prototypes. - */ -/******************************************************************************/ - -static void -wrtmessage(const char *p1, const char *p2, const char *p3, const char *p4) -{ - - if (_write(STDERR_FILENO, p1, strlen(p1)) < 0 - || _write(STDERR_FILENO, p2, strlen(p2)) < 0 - || _write(STDERR_FILENO, p3, strlen(p3)) < 0 - || _write(STDERR_FILENO, p4, strlen(p4)) < 0) - return; -} - -void (*_malloc_message)(const char *p1, const char *p2, const char *p3, - const char *p4) = wrtmessage; - -/* - * We don't want to depend on vsnprintf() for production builds, since that can - * cause unnecessary bloat for static binaries. umax2s() provides minimal - * integer printing functionality, so that malloc_printf() use can be limited to - * MALLOC_STATS code. - */ -#define UMAX2S_BUFSIZE 65 -static char * -umax2s(uintmax_t x, unsigned base, char *s) -{ - unsigned i; - - i = UMAX2S_BUFSIZE - 1; - s[i] = '\0'; - switch (base) { - case 10: - do { - i--; - s[i] = "0123456789"[x % 10]; - x /= 10; - } while (x > 0); - break; - case 16: - do { - i--; - s[i] = "0123456789abcdef"[x & 0xf]; - x >>= 4; - } while (x > 0); - break; - default: - do { - i--; - s[i] = "0123456789abcdefghijklmnopqrstuvwxyz"[x % base]; - x /= base; - } while (x > 0); - } - - return (&s[i]); -} - -/* - * Define a custom assert() in order to reduce the chances of deadlock during - * assertion failure. - */ -#ifdef MALLOC_DEBUG -# define assert(e) do { \ - if (!(e)) { \ - char line_buf[UMAX2S_BUFSIZE]; \ - _malloc_message(_getprogname(), ": (malloc) ", \ - __FILE__, ":"); \ - _malloc_message(umax2s(__LINE__, 10, line_buf), \ - ": Failed assertion: ", "\"", #e); \ - _malloc_message("\"\n", "", "", ""); \ - abort(); \ - } \ -} while (0) -#else -#define assert(e) -#endif - -#ifdef MALLOC_STATS -/* - * Print to stderr in such a way as to (hopefully) avoid memory allocation. - */ -static void -malloc_printf(const char *format, ...) -{ - char buf[4096]; - va_list ap; - - va_start(ap, format); - vsnprintf(buf, sizeof(buf), format, ap); - va_end(ap); - _malloc_message(buf, "", "", ""); -} -#endif - -/******************************************************************************/ -/* - * Begin mutex. We can't use normal pthread mutexes in all places, because - * they require malloc()ed memory, which causes bootstrapping issues in some - * cases. - */ - -static void -malloc_mutex_init(malloc_mutex_t *mutex) -{ - static const spinlock_t lock = _SPINLOCK_INITIALIZER; - - mutex->lock = lock; -} - -static inline void -malloc_mutex_lock(malloc_mutex_t *mutex) -{ - - if (__isthreaded) - _SPINLOCK(&mutex->lock); -} - -static inline void -malloc_mutex_unlock(malloc_mutex_t *mutex) -{ - - if (__isthreaded) - _SPINUNLOCK(&mutex->lock); -} - -/* - * End mutex. - */ -/******************************************************************************/ -/* - * Begin spin lock. Spin locks here are actually adaptive mutexes that block - * after a period of spinning, because unbounded spinning would allow for - * priority inversion. - */ - -/* - * We use an unpublished interface to initialize pthread mutexes with an - * allocation callback, in order to avoid infinite recursion. - */ -int _pthread_mutex_init_calloc_cb(pthread_mutex_t *mutex, - void *(calloc_cb)(size_t, size_t)); - -__weak_reference(_pthread_mutex_init_calloc_cb_stub, - _pthread_mutex_init_calloc_cb); - -int -_pthread_mutex_init_calloc_cb_stub(pthread_mutex_t *mutex, - void *(calloc_cb)(size_t, size_t)) -{ - - return (0); -} - -static bool -malloc_spin_init(pthread_mutex_t *lock) -{ - - if (_pthread_mutex_init_calloc_cb(lock, base_calloc) != 0) - return (true); - - return (false); -} - -static inline void -malloc_spin_lock(pthread_mutex_t *lock) -{ - - if (__isthreaded) { - if (_pthread_mutex_trylock(lock) != 0) { - /* Exponentially back off if there are multiple CPUs. */ - if (ncpus > 1) { - unsigned i; - volatile unsigned j; - - for (i = 1; i <= LG_SPIN_LIMIT; i++) { - for (j = 0; j < (1U << i); j++) { - CPU_SPINWAIT; - } - - if (_pthread_mutex_trylock(lock) == 0) - return; - } - } - - /* - * Spinning failed. Block until the lock becomes - * available, in order to avoid indefinite priority - * inversion. - */ - _pthread_mutex_lock(lock); - } - } -} - -static inline void -malloc_spin_unlock(pthread_mutex_t *lock) -{ - - if (__isthreaded) - _pthread_mutex_unlock(lock); -} - -/* - * End spin lock. - */ -/******************************************************************************/ -/* - * Begin Utility functions/macros. - */ - -/* Return the chunk address for allocation address a. */ -#define CHUNK_ADDR2BASE(a) \ - ((void *)((uintptr_t)(a) & ~chunksize_mask)) - -/* Return the chunk offset of address a. */ -#define CHUNK_ADDR2OFFSET(a) \ - ((size_t)((uintptr_t)(a) & chunksize_mask)) - -/* Return the smallest chunk multiple that is >= s. */ -#define CHUNK_CEILING(s) \ - (((s) + chunksize_mask) & ~chunksize_mask) - -/* Return the smallest quantum multiple that is >= a. */ -#define QUANTUM_CEILING(a) \ - (((a) + QUANTUM_MASK) & ~QUANTUM_MASK) - -/* Return the smallest cacheline multiple that is >= s. */ -#define CACHELINE_CEILING(s) \ - (((s) + CACHELINE_MASK) & ~CACHELINE_MASK) - -/* Return the smallest subpage multiple that is >= s. */ -#define SUBPAGE_CEILING(s) \ - (((s) + SUBPAGE_MASK) & ~SUBPAGE_MASK) - -/* Return the smallest medium size class that is >= s. */ -#define MEDIUM_CEILING(s) \ - (((s) + mspace_mask) & ~mspace_mask) - -/* Return the smallest pagesize multiple that is >= s. */ -#define PAGE_CEILING(s) \ - (((s) + PAGE_MASK) & ~PAGE_MASK) - -#ifdef MALLOC_TINY -/* Compute the smallest power of 2 that is >= x. */ -static size_t -pow2_ceil(size_t x) -{ - - x--; - x |= x >> 1; - x |= x >> 2; - x |= x >> 4; - x |= x >> 8; - x |= x >> 16; -#if (SIZEOF_PTR == 8) - x |= x >> 32; -#endif - x++; - return (x); -} -#endif - -/******************************************************************************/ - -#ifdef MALLOC_DSS -static bool -base_pages_alloc_dss(size_t minsize) -{ - - /* - * Do special DSS allocation here, since base allocations don't need to - * be chunk-aligned. - */ - malloc_mutex_lock(&dss_mtx); - if (dss_prev != (void *)-1) { - intptr_t incr; - size_t csize = CHUNK_CEILING(minsize); - - do { - /* Get the current end of the DSS. */ - dss_max = sbrk(0); - - /* - * Calculate how much padding is necessary to - * chunk-align the end of the DSS. Don't worry about - * dss_max not being chunk-aligned though. - */ - incr = (intptr_t)chunksize - - (intptr_t)CHUNK_ADDR2OFFSET(dss_max); - assert(incr >= 0); - if ((size_t)incr < minsize) - incr += csize; - - dss_prev = sbrk(incr); - if (dss_prev == dss_max) { - /* Success. */ - dss_max = (void *)((intptr_t)dss_prev + incr); - base_pages = dss_prev; - base_next_addr = base_pages; - base_past_addr = dss_max; -#ifdef MALLOC_STATS - base_mapped += incr; -#endif - malloc_mutex_unlock(&dss_mtx); - return (false); - } - } while (dss_prev != (void *)-1); - } - malloc_mutex_unlock(&dss_mtx); - - return (true); -} -#endif - -static bool -base_pages_alloc_mmap(size_t minsize) -{ - size_t csize; - - assert(minsize != 0); - csize = PAGE_CEILING(minsize); - base_pages = pages_map(NULL, csize); - if (base_pages == NULL) - return (true); - base_next_addr = base_pages; - base_past_addr = (void *)((uintptr_t)base_pages + csize); -#ifdef MALLOC_STATS - base_mapped += csize; -#endif - - return (false); -} - -static bool -base_pages_alloc(size_t minsize) -{ - -#ifdef MALLOC_DSS - if (opt_mmap && minsize != 0) -#endif - { - if (base_pages_alloc_mmap(minsize) == false) - return (false); - } - -#ifdef MALLOC_DSS - if (opt_dss) { - if (base_pages_alloc_dss(minsize) == false) - return (false); - } - -#endif - - return (true); -} - -static void * -base_alloc(size_t size) -{ - void *ret; - size_t csize; - - /* Round size up to nearest multiple of the cacheline size. */ - csize = CACHELINE_CEILING(size); - - malloc_mutex_lock(&base_mtx); - /* Make sure there's enough space for the allocation. */ - if ((uintptr_t)base_next_addr + csize > (uintptr_t)base_past_addr) { - if (base_pages_alloc(csize)) { - malloc_mutex_unlock(&base_mtx); - return (NULL); - } - } - /* Allocate. */ - ret = base_next_addr; - base_next_addr = (void *)((uintptr_t)base_next_addr + csize); - malloc_mutex_unlock(&base_mtx); - - return (ret); -} - -static void * -base_calloc(size_t number, size_t size) -{ - void *ret; - - ret = base_alloc(number * size); - if (ret != NULL) - memset(ret, 0, number * size); - - return (ret); -} - -static extent_node_t * -base_node_alloc(void) -{ - extent_node_t *ret; - - malloc_mutex_lock(&base_mtx); - if (base_nodes != NULL) { - ret = base_nodes; - base_nodes = *(extent_node_t **)ret; - malloc_mutex_unlock(&base_mtx); - } else { - malloc_mutex_unlock(&base_mtx); - ret = (extent_node_t *)base_alloc(sizeof(extent_node_t)); - } - - return (ret); -} - -static void -base_node_dealloc(extent_node_t *node) -{ - - malloc_mutex_lock(&base_mtx); - *(extent_node_t **)node = base_nodes; - base_nodes = node; - malloc_mutex_unlock(&base_mtx); -} - -/* - * End Utility functions/macros. - */ -/******************************************************************************/ -/* - * Begin extent tree code. - */ - -#ifdef MALLOC_DSS -static inline int -extent_szad_comp(extent_node_t *a, extent_node_t *b) -{ - int ret; - size_t a_size = a->size; - size_t b_size = b->size; - - ret = (a_size > b_size) - (a_size < b_size); - if (ret == 0) { - uintptr_t a_addr = (uintptr_t)a->addr; - uintptr_t b_addr = (uintptr_t)b->addr; - - ret = (a_addr > b_addr) - (a_addr < b_addr); - } - - return (ret); -} - -/* Wrap red-black tree macros in functions. */ -rb_gen(__unused static, extent_tree_szad_, extent_tree_t, extent_node_t, - link_szad, extent_szad_comp) -#endif - -static inline int -extent_ad_comp(extent_node_t *a, extent_node_t *b) -{ - uintptr_t a_addr = (uintptr_t)a->addr; - uintptr_t b_addr = (uintptr_t)b->addr; - - return ((a_addr > b_addr) - (a_addr < b_addr)); -} - -/* Wrap red-black tree macros in functions. */ -rb_gen(__unused static, extent_tree_ad_, extent_tree_t, extent_node_t, link_ad, - extent_ad_comp) - -/* - * End extent tree code. - */ -/******************************************************************************/ -/* - * Begin chunk management functions. - */ - -static void * -pages_map(void *addr, size_t size) -{ - void *ret; - - /* - * We don't use MAP_FIXED here, because it can cause the *replacement* - * of existing mappings, and we only want to create new mappings. - */ - ret = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, - -1, 0); - assert(ret != NULL); - - if (ret == MAP_FAILED) - ret = NULL; - else if (addr != NULL && ret != addr) { - /* - * We succeeded in mapping memory, but not in the right place. - */ - if (munmap(ret, size) == -1) { - char buf[STRERROR_BUF]; - - strerror_r(errno, buf, sizeof(buf)); - _malloc_message(_getprogname(), - ": (malloc) Error in munmap(): ", buf, "\n"); - if (opt_abort) - abort(); - } - ret = NULL; - } - - assert(ret == NULL || (addr == NULL && ret != addr) - || (addr != NULL && ret == addr)); - return (ret); -} - -static void -pages_unmap(void *addr, size_t size) -{ - - if (munmap(addr, size) == -1) { - char buf[STRERROR_BUF]; - - strerror_r(errno, buf, sizeof(buf)); - _malloc_message(_getprogname(), - ": (malloc) Error in munmap(): ", buf, "\n"); - if (opt_abort) - abort(); - } -} - -#ifdef MALLOC_DSS -static void * -chunk_alloc_dss(size_t size, bool *zero) -{ - void *ret; - - ret = chunk_recycle_dss(size, zero); - if (ret != NULL) - return (ret); - - /* - * sbrk() uses a signed increment argument, so take care not to - * interpret a huge allocation request as a negative increment. - */ - if ((intptr_t)size < 0) - return (NULL); - - malloc_mutex_lock(&dss_mtx); - if (dss_prev != (void *)-1) { - intptr_t incr; - - /* - * The loop is necessary to recover from races with other - * threads that are using the DSS for something other than - * malloc. - */ - do { - /* Get the current end of the DSS. */ - dss_max = sbrk(0); - - /* - * Calculate how much padding is necessary to - * chunk-align the end of the DSS. - */ - incr = (intptr_t)size - - (intptr_t)CHUNK_ADDR2OFFSET(dss_max); - if (incr == (intptr_t)size) - ret = dss_max; - else { - ret = (void *)((intptr_t)dss_max + incr); - incr += size; - } - - dss_prev = sbrk(incr); - if (dss_prev == dss_max) { - /* Success. */ - dss_max = (void *)((intptr_t)dss_prev + incr); - malloc_mutex_unlock(&dss_mtx); - *zero = true; - return (ret); - } - } while (dss_prev != (void *)-1); - } - malloc_mutex_unlock(&dss_mtx); - - return (NULL); -} - -static void * -chunk_recycle_dss(size_t size, bool *zero) -{ - extent_node_t *node, key; - - key.addr = NULL; - key.size = size; - malloc_mutex_lock(&dss_mtx); - node = extent_tree_szad_nsearch(&dss_chunks_szad, &key); - if (node != NULL) { - void *ret = node->addr; - - /* Remove node from the tree. */ - extent_tree_szad_remove(&dss_chunks_szad, node); - if (node->size == size) { - extent_tree_ad_remove(&dss_chunks_ad, node); - base_node_dealloc(node); - } else { - /* - * Insert the remainder of node's address range as a - * smaller chunk. Its position within dss_chunks_ad - * does not change. - */ - assert(node->size > size); - node->addr = (void *)((uintptr_t)node->addr + size); - node->size -= size; - extent_tree_szad_insert(&dss_chunks_szad, node); - } - malloc_mutex_unlock(&dss_mtx); - - if (*zero) - memset(ret, 0, size); - return (ret); - } - malloc_mutex_unlock(&dss_mtx); - - return (NULL); -} -#endif - -static void * -chunk_alloc_mmap_slow(size_t size, bool unaligned) -{ - void *ret; - size_t offset; - - /* Beware size_t wrap-around. */ - if (size + chunksize <= size) - return (NULL); - - ret = pages_map(NULL, size + chunksize); - if (ret == NULL) - return (NULL); - - /* Clean up unneeded leading/trailing space. */ - offset = CHUNK_ADDR2OFFSET(ret); - if (offset != 0) { - /* Note that mmap() returned an unaligned mapping. */ - unaligned = true; - - /* Leading space. */ - pages_unmap(ret, chunksize - offset); - - ret = (void *)((uintptr_t)ret + - (chunksize - offset)); - - /* Trailing space. */ - pages_unmap((void *)((uintptr_t)ret + size), - offset); - } else { - /* Trailing space only. */ - pages_unmap((void *)((uintptr_t)ret + size), - chunksize); - } - - /* - * If mmap() returned an aligned mapping, reset mmap_unaligned so that - * the next chunk_alloc_mmap() execution tries the fast allocation - * method. - */ - if (unaligned == false) - mmap_unaligned = false; - - return (ret); -} - -static void * -chunk_alloc_mmap(size_t size) -{ - void *ret; - - /* - * Ideally, there would be a way to specify alignment to mmap() (like - * NetBSD has), but in the absence of such a feature, we have to work - * hard to efficiently create aligned mappings. The reliable, but - * slow method is to create a mapping that is over-sized, then trim the - * excess. However, that always results in at least one call to - * pages_unmap(). - * - * A more optimistic approach is to try mapping precisely the right - * amount, then try to append another mapping if alignment is off. In - * practice, this works out well as long as the application is not - * interleaving mappings via direct mmap() calls. If we do run into a - * situation where there is an interleaved mapping and we are unable to - * extend an unaligned mapping, our best option is to switch to the - * slow method until mmap() returns another aligned mapping. This will - * tend to leave a gap in the memory map that is too small to cause - * later problems for the optimistic method. - * - * Another possible confounding factor is address space layout - * randomization (ASLR), which causes mmap(2) to disregard the - * requested address. mmap_unaligned tracks whether the previous - * chunk_alloc_mmap() execution received any unaligned or relocated - * mappings, and if so, the current execution will immediately fall - * back to the slow method. However, we keep track of whether the fast - * method would have succeeded, and if so, we make a note to try the - * fast method next time. - */ - - if (mmap_unaligned == false) { - size_t offset; - - ret = pages_map(NULL, size); - if (ret == NULL) - return (NULL); - - offset = CHUNK_ADDR2OFFSET(ret); - if (offset != 0) { - mmap_unaligned = true; - /* Try to extend chunk boundary. */ - if (pages_map((void *)((uintptr_t)ret + size), - chunksize - offset) == NULL) { - /* - * Extension failed. Clean up, then revert to - * the reliable-but-expensive method. - */ - pages_unmap(ret, size); - ret = chunk_alloc_mmap_slow(size, true); - } else { - /* Clean up unneeded leading space. */ - pages_unmap(ret, chunksize - offset); - ret = (void *)((uintptr_t)ret + (chunksize - - offset)); - } - } - } else - ret = chunk_alloc_mmap_slow(size, false); - - return (ret); -} - -/* - * If the caller specifies (*zero == false), it is still possible to receive - * zeroed memory, in which case *zero is toggled to true. arena_chunk_alloc() - * takes advantage of this to avoid demanding zeroed chunks, but taking - * advantage of them if they are returned. - */ -static void * -chunk_alloc(size_t size, bool *zero) -{ - void *ret; - - assert(size != 0); - assert((size & chunksize_mask) == 0); - -#ifdef MALLOC_DSS - if (opt_mmap) -#endif - { - ret = chunk_alloc_mmap(size); - if (ret != NULL) { - *zero = true; - goto RETURN; - } - } - -#ifdef MALLOC_DSS - if (opt_dss) { - ret = chunk_alloc_dss(size, zero); - if (ret != NULL) - goto RETURN; - } -#endif - - /* All strategies for allocation failed. */ - ret = NULL; -RETURN: -#ifdef MALLOC_STATS - if (ret != NULL) { - malloc_mutex_lock(&chunks_mtx); - stats_chunks.nchunks += (size / chunksize); - stats_chunks.curchunks += (size / chunksize); - if (stats_chunks.curchunks > stats_chunks.highchunks) - stats_chunks.highchunks = stats_chunks.curchunks; - malloc_mutex_unlock(&chunks_mtx); - } -#endif - - assert(CHUNK_ADDR2BASE(ret) == ret); - return (ret); -} - -#ifdef MALLOC_DSS -static extent_node_t * -chunk_dealloc_dss_record(void *chunk, size_t size) -{ - extent_node_t *node, *prev, key; - - key.addr = (void *)((uintptr_t)chunk + size); - node = extent_tree_ad_nsearch(&dss_chunks_ad, &key); - /* Try to coalesce forward. */ - if (node != NULL && node->addr == key.addr) { - /* - * Coalesce chunk with the following address range. This does - * not change the position within dss_chunks_ad, so only - * remove/insert from/into dss_chunks_szad. - */ - extent_tree_szad_remove(&dss_chunks_szad, node); - node->addr = chunk; - node->size += size; - extent_tree_szad_insert(&dss_chunks_szad, node); - } else { - /* - * Coalescing forward failed, so insert a new node. Drop - * dss_mtx during node allocation, since it is possible that a - * new base chunk will be allocated. - */ - malloc_mutex_unlock(&dss_mtx); - node = base_node_alloc(); - malloc_mutex_lock(&dss_mtx); - if (node == NULL) - return (NULL); - node->addr = chunk; - node->size = size; - extent_tree_ad_insert(&dss_chunks_ad, node); - extent_tree_szad_insert(&dss_chunks_szad, node); - } - - /* Try to coalesce backward. */ - prev = extent_tree_ad_prev(&dss_chunks_ad, node); - if (prev != NULL && (void *)((uintptr_t)prev->addr + prev->size) == - chunk) { - /* - * Coalesce chunk with the previous address range. This does - * not change the position within dss_chunks_ad, so only - * remove/insert node from/into dss_chunks_szad. - */ - extent_tree_szad_remove(&dss_chunks_szad, prev); - extent_tree_ad_remove(&dss_chunks_ad, prev); - - extent_tree_szad_remove(&dss_chunks_szad, node); - node->addr = prev->addr; - node->size += prev->size; - extent_tree_szad_insert(&dss_chunks_szad, node); - - base_node_dealloc(prev); - } - - return (node); -} - -static bool -chunk_dealloc_dss(void *chunk, size_t size) -{ - bool ret; - - malloc_mutex_lock(&dss_mtx); - if ((uintptr_t)chunk >= (uintptr_t)dss_base - && (uintptr_t)chunk < (uintptr_t)dss_max) { - extent_node_t *node; - - /* Try to coalesce with other unused chunks. */ - node = chunk_dealloc_dss_record(chunk, size); - if (node != NULL) { - chunk = node->addr; - size = node->size; - } - - /* Get the current end of the DSS. */ - dss_max = sbrk(0); - - /* - * Try to shrink the DSS if this chunk is at the end of the - * DSS. The sbrk() call here is subject to a race condition - * with threads that use brk(2) or sbrk(2) directly, but the - * alternative would be to leak memory for the sake of poorly - * designed multi-threaded programs. - */ - if ((void *)((uintptr_t)chunk + size) == dss_max - && (dss_prev = sbrk(-(intptr_t)size)) == dss_max) { - /* Success. */ - dss_max = (void *)((intptr_t)dss_prev - (intptr_t)size); - - if (node != NULL) { - extent_tree_szad_remove(&dss_chunks_szad, node); - extent_tree_ad_remove(&dss_chunks_ad, node); - base_node_dealloc(node); - } - } else - madvise(chunk, size, MADV_FREE); - - ret = false; - goto RETURN; - } - - ret = true; -RETURN: - malloc_mutex_unlock(&dss_mtx); - return (ret); -} -#endif - -static void -chunk_dealloc_mmap(void *chunk, size_t size) -{ - - pages_unmap(chunk, size); -} - -static void -chunk_dealloc(void *chunk, size_t size) -{ - - assert(chunk != NULL); - assert(CHUNK_ADDR2BASE(chunk) == chunk); - assert(size != 0); - assert((size & chunksize_mask) == 0); - -#ifdef MALLOC_STATS - malloc_mutex_lock(&chunks_mtx); - stats_chunks.curchunks -= (size / chunksize); - malloc_mutex_unlock(&chunks_mtx); -#endif - -#ifdef MALLOC_DSS - if (opt_dss) { - if (chunk_dealloc_dss(chunk, size) == false) - return; - } - - if (opt_mmap) -#endif - chunk_dealloc_mmap(chunk, size); -} - -/* - * End chunk management functions. - */ -/******************************************************************************/ -/* - * Begin arena. - */ - -/* - * Choose an arena based on a per-thread value (fast-path code, calls slow-path - * code if necessary). - */ -static inline arena_t * -choose_arena(void) -{ - arena_t *ret; - - /* - * We can only use TLS if this is a PIC library, since for the static - * library version, libc's malloc is used by TLS allocation, which - * introduces a bootstrapping issue. - */ -#ifndef NO_TLS - if (__isthreaded == false) { - /* Avoid the overhead of TLS for single-threaded operation. */ - return (arenas[0]); - } - - ret = arenas_map; - if (ret == NULL) { - ret = choose_arena_hard(); - assert(ret != NULL); - } -#else - if (__isthreaded && narenas > 1) { - unsigned long ind; - - /* - * Hash _pthread_self() to one of the arenas. There is a prime - * number of arenas, so this has a reasonable chance of - * working. Even so, the hashing can be easily thwarted by - * inconvenient _pthread_self() values. Without specific - * knowledge of how _pthread_self() calculates values, we can't - * easily do much better than this. - */ - ind = (unsigned long) _pthread_self() % narenas; - - /* - * Optimistially assume that arenas[ind] has been initialized. - * At worst, we find out that some other thread has already - * done so, after acquiring the lock in preparation. Note that - * this lazy locking also has the effect of lazily forcing - * cache coherency; without the lock acquisition, there's no - * guarantee that modification of arenas[ind] by another thread - * would be seen on this CPU for an arbitrary amount of time. - * - * In general, this approach to modifying a synchronized value - * isn't a good idea, but in this case we only ever modify the - * value once, so things work out well. - */ - ret = arenas[ind]; - if (ret == NULL) { - /* - * Avoid races with another thread that may have already - * initialized arenas[ind]. - */ - malloc_spin_lock(&arenas_lock); - if (arenas[ind] == NULL) - ret = arenas_extend((unsigned)ind); - else - ret = arenas[ind]; - malloc_spin_unlock(&arenas_lock); - } - } else - ret = arenas[0]; -#endif - - assert(ret != NULL); - return (ret); -} - -#ifndef NO_TLS -/* - * Choose an arena based on a per-thread value (slow-path code only, called - * only by choose_arena()). - */ -static arena_t * -choose_arena_hard(void) -{ - arena_t *ret; - - assert(__isthreaded); - - if (narenas > 1) { - malloc_spin_lock(&arenas_lock); - if ((ret = arenas[next_arena]) == NULL) - ret = arenas_extend(next_arena); - next_arena = (next_arena + 1) % narenas; - malloc_spin_unlock(&arenas_lock); - } else - ret = arenas[0]; - - arenas_map = ret; - - return (ret); -} -#endif - -static inline int -arena_chunk_comp(arena_chunk_t *a, arena_chunk_t *b) -{ - uintptr_t a_chunk = (uintptr_t)a; - uintptr_t b_chunk = (uintptr_t)b; - - assert(a != NULL); - assert(b != NULL); - - return ((a_chunk > b_chunk) - (a_chunk < b_chunk)); -} - -/* Wrap red-black tree macros in functions. */ -rb_gen(__unused static, arena_chunk_tree_dirty_, arena_chunk_tree_t, - arena_chunk_t, link_dirty, arena_chunk_comp) - -static inline int -arena_run_comp(arena_chunk_map_t *a, arena_chunk_map_t *b) -{ - uintptr_t a_mapelm = (uintptr_t)a; - uintptr_t b_mapelm = (uintptr_t)b; - - assert(a != NULL); - assert(b != NULL); - - return ((a_mapelm > b_mapelm) - (a_mapelm < b_mapelm)); -} - -/* Wrap red-black tree macros in functions. */ -rb_gen(__unused static, arena_run_tree_, arena_run_tree_t, arena_chunk_map_t, - link, arena_run_comp) - -static inline int -arena_avail_comp(arena_chunk_map_t *a, arena_chunk_map_t *b) -{ - int ret; - size_t a_size = a->bits & ~PAGE_MASK; - size_t b_size = b->bits & ~PAGE_MASK; - - ret = (a_size > b_size) - (a_size < b_size); - if (ret == 0) { - uintptr_t a_mapelm, b_mapelm; - - if ((a->bits & CHUNK_MAP_KEY) != CHUNK_MAP_KEY) - a_mapelm = (uintptr_t)a; - else { - /* - * Treat keys as though they are lower than anything - * else. - */ - a_mapelm = 0; - } - b_mapelm = (uintptr_t)b; - - ret = (a_mapelm > b_mapelm) - (a_mapelm < b_mapelm); - } - - return (ret); -} - -/* Wrap red-black tree macros in functions. */ -rb_gen(__unused static, arena_avail_tree_, arena_avail_tree_t, - arena_chunk_map_t, link, arena_avail_comp) - -static inline void -arena_run_rc_incr(arena_run_t *run, arena_bin_t *bin, const void *ptr) -{ - arena_chunk_t *chunk; - arena_t *arena; - size_t pagebeg, pageend, i; - - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); - arena = chunk->arena; - pagebeg = ((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT; - pageend = ((uintptr_t)ptr + (uintptr_t)(bin->reg_size - 1) - - (uintptr_t)chunk) >> PAGE_SHIFT; - - for (i = pagebeg; i <= pageend; i++) { - size_t mapbits = chunk->map[i].bits; - - if (mapbits & CHUNK_MAP_DIRTY) { - assert((mapbits & CHUNK_MAP_RC_MASK) == 0); - chunk->ndirty--; - arena->ndirty--; - mapbits ^= CHUNK_MAP_DIRTY; - } - assert((mapbits & CHUNK_MAP_RC_MASK) != CHUNK_MAP_RC_MASK); - mapbits += CHUNK_MAP_RC_ONE; - chunk->map[i].bits = mapbits; - } -} - -static inline void -arena_run_rc_decr(arena_run_t *run, arena_bin_t *bin, const void *ptr) -{ - arena_chunk_t *chunk; - arena_t *arena; - size_t pagebeg, pageend, mapbits, i; - bool dirtier = false; - - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); - arena = chunk->arena; - pagebeg = ((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT; - pageend = ((uintptr_t)ptr + (uintptr_t)(bin->reg_size - 1) - - (uintptr_t)chunk) >> PAGE_SHIFT; - - /* First page. */ - mapbits = chunk->map[pagebeg].bits; - mapbits -= CHUNK_MAP_RC_ONE; - if ((mapbits & CHUNK_MAP_RC_MASK) == 0) { - dirtier = true; - assert((mapbits & CHUNK_MAP_DIRTY) == 0); - mapbits |= CHUNK_MAP_DIRTY; - chunk->ndirty++; - arena->ndirty++; - } - chunk->map[pagebeg].bits = mapbits; - - if (pageend - pagebeg >= 1) { - /* - * Interior pages are completely consumed by the object being - * deallocated, which means that the pages can be - * unconditionally marked dirty. - */ - for (i = pagebeg + 1; i < pageend; i++) { - mapbits = chunk->map[i].bits; - mapbits -= CHUNK_MAP_RC_ONE; - assert((mapbits & CHUNK_MAP_RC_MASK) == 0); - dirtier = true; - assert((mapbits & CHUNK_MAP_DIRTY) == 0); - mapbits |= CHUNK_MAP_DIRTY; - chunk->ndirty++; - arena->ndirty++; - chunk->map[i].bits = mapbits; - } - - /* Last page. */ - mapbits = chunk->map[pageend].bits; - mapbits -= CHUNK_MAP_RC_ONE; - if ((mapbits & CHUNK_MAP_RC_MASK) == 0) { - dirtier = true; - assert((mapbits & CHUNK_MAP_DIRTY) == 0); - mapbits |= CHUNK_MAP_DIRTY; - chunk->ndirty++; - arena->ndirty++; - } - chunk->map[pageend].bits = mapbits; - } - - if (dirtier) { - if (chunk->dirtied == false) { - arena_chunk_tree_dirty_insert(&arena->chunks_dirty, - chunk); - chunk->dirtied = true; - } - - /* Enforce opt_lg_dirty_mult. */ - if (opt_lg_dirty_mult >= 0 && (arena->nactive >> - opt_lg_dirty_mult) < arena->ndirty) - arena_purge(arena); - } -} - -static inline void * -arena_run_reg_alloc(arena_run_t *run, arena_bin_t *bin) -{ - void *ret; - unsigned i, mask, bit, regind; - - assert(run->magic == ARENA_RUN_MAGIC); - assert(run->regs_minelm < bin->regs_mask_nelms); - - /* - * Move the first check outside the loop, so that run->regs_minelm can - * be updated unconditionally, without the possibility of updating it - * multiple times. - */ - i = run->regs_minelm; - mask = run->regs_mask[i]; - if (mask != 0) { - /* Usable allocation found. */ - bit = ffs((int)mask) - 1; - - regind = ((i << (LG_SIZEOF_INT + 3)) + bit); - assert(regind < bin->nregs); - ret = (void *)(((uintptr_t)run) + bin->reg0_offset - + (bin->reg_size * regind)); - - /* Clear bit. */ - mask ^= (1U << bit); - run->regs_mask[i] = mask; - - arena_run_rc_incr(run, bin, ret); - - return (ret); - } - - for (i++; i < bin->regs_mask_nelms; i++) { - mask = run->regs_mask[i]; - if (mask != 0) { - /* Usable allocation found. */ - bit = ffs((int)mask) - 1; - - regind = ((i << (LG_SIZEOF_INT + 3)) + bit); - assert(regind < bin->nregs); - ret = (void *)(((uintptr_t)run) + bin->reg0_offset - + (bin->reg_size * regind)); - - /* Clear bit. */ - mask ^= (1U << bit); - run->regs_mask[i] = mask; - - /* - * Make a note that nothing before this element - * contains a free region. - */ - run->regs_minelm = i; /* Low payoff: + (mask == 0); */ - - arena_run_rc_incr(run, bin, ret); - - return (ret); - } - } - /* Not reached. */ - assert(0); - return (NULL); -} - -static inline void -arena_run_reg_dalloc(arena_run_t *run, arena_bin_t *bin, void *ptr, size_t size) -{ - unsigned shift, diff, regind, elm, bit; - - assert(run->magic == ARENA_RUN_MAGIC); - - /* - * Avoid doing division with a variable divisor if possible. Using - * actual division here can reduce allocator throughput by over 20%! - */ - diff = (unsigned)((uintptr_t)ptr - (uintptr_t)run - bin->reg0_offset); - - /* Rescale (factor powers of 2 out of the numerator and denominator). */ - shift = ffs(size) - 1; - diff >>= shift; - size >>= shift; - - if (size == 1) { - /* The divisor was a power of 2. */ - regind = diff; - } else { - /* - * To divide by a number D that is not a power of two we - * multiply by (2^21 / D) and then right shift by 21 positions. - * - * X / D - * - * becomes - * - * (X * size_invs[D - 3]) >> SIZE_INV_SHIFT - * - * We can omit the first three elements, because we never - * divide by 0, and 1 and 2 are both powers of two, which are - * handled above. - */ -#define SIZE_INV_SHIFT 21 -#define SIZE_INV(s) (((1U << SIZE_INV_SHIFT) / (s)) + 1) - static const unsigned size_invs[] = { - SIZE_INV(3), - SIZE_INV(4), SIZE_INV(5), SIZE_INV(6), SIZE_INV(7), - SIZE_INV(8), SIZE_INV(9), SIZE_INV(10), SIZE_INV(11), - SIZE_INV(12), SIZE_INV(13), SIZE_INV(14), SIZE_INV(15), - SIZE_INV(16), SIZE_INV(17), SIZE_INV(18), SIZE_INV(19), - SIZE_INV(20), SIZE_INV(21), SIZE_INV(22), SIZE_INV(23), - SIZE_INV(24), SIZE_INV(25), SIZE_INV(26), SIZE_INV(27), - SIZE_INV(28), SIZE_INV(29), SIZE_INV(30), SIZE_INV(31) - }; - - if (size <= ((sizeof(size_invs) / sizeof(unsigned)) + 2)) - regind = (diff * size_invs[size - 3]) >> SIZE_INV_SHIFT; - else - regind = diff / size; -#undef SIZE_INV -#undef SIZE_INV_SHIFT - } - assert(diff == regind * size); - assert(regind < bin->nregs); - - elm = regind >> (LG_SIZEOF_INT + 3); - if (elm < run->regs_minelm) - run->regs_minelm = elm; - bit = regind - (elm << (LG_SIZEOF_INT + 3)); - assert((run->regs_mask[elm] & (1U << bit)) == 0); - run->regs_mask[elm] |= (1U << bit); - - arena_run_rc_decr(run, bin, ptr); -} - -static void -arena_run_split(arena_t *arena, arena_run_t *run, size_t size, bool large, - bool zero) -{ - arena_chunk_t *chunk; - size_t old_ndirty, run_ind, total_pages, need_pages, rem_pages, i; - - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run); - old_ndirty = chunk->ndirty; - run_ind = (unsigned)(((uintptr_t)run - (uintptr_t)chunk) - >> PAGE_SHIFT); - total_pages = (chunk->map[run_ind].bits & ~PAGE_MASK) >> - PAGE_SHIFT; - need_pages = (size >> PAGE_SHIFT); - assert(need_pages > 0); - assert(need_pages <= total_pages); - rem_pages = total_pages - need_pages; - - arena_avail_tree_remove(&arena->runs_avail, &chunk->map[run_ind]); - arena->nactive += need_pages; - - /* Keep track of trailing unused pages for later use. */ - if (rem_pages > 0) { - chunk->map[run_ind+need_pages].bits = (rem_pages << - PAGE_SHIFT) | (chunk->map[run_ind+need_pages].bits & - CHUNK_MAP_FLAGS_MASK); - chunk->map[run_ind+total_pages-1].bits = (rem_pages << - PAGE_SHIFT) | (chunk->map[run_ind+total_pages-1].bits & - CHUNK_MAP_FLAGS_MASK); - arena_avail_tree_insert(&arena->runs_avail, - &chunk->map[run_ind+need_pages]); - } - - for (i = 0; i < need_pages; i++) { - /* Zero if necessary. */ - if (zero) { - if ((chunk->map[run_ind + i].bits & CHUNK_MAP_ZEROED) - == 0) { - memset((void *)((uintptr_t)chunk + ((run_ind - + i) << PAGE_SHIFT)), 0, PAGE_SIZE); - /* CHUNK_MAP_ZEROED is cleared below. */ - } - } - - /* Update dirty page accounting. */ - if (chunk->map[run_ind + i].bits & CHUNK_MAP_DIRTY) { - chunk->ndirty--; - arena->ndirty--; - /* CHUNK_MAP_DIRTY is cleared below. */ - } - - /* Initialize the chunk map. */ - if (large) { - chunk->map[run_ind + i].bits = CHUNK_MAP_LARGE - | CHUNK_MAP_ALLOCATED; - } else { - chunk->map[run_ind + i].bits = (i << CHUNK_MAP_PG_SHIFT) - | CHUNK_MAP_ALLOCATED; - } - } - - if (large) { - /* - * Set the run size only in the first element for large runs. - * This is primarily a debugging aid, since the lack of size - * info for trailing pages only matters if the application - * tries to operate on an interior pointer. - */ - chunk->map[run_ind].bits |= size; - } else { - /* - * Initialize the first page's refcount to 1, so that the run - * header is protected from dirty page purging. - */ - chunk->map[run_ind].bits += CHUNK_MAP_RC_ONE; - } -} - -static arena_chunk_t * -arena_chunk_alloc(arena_t *arena) -{ - arena_chunk_t *chunk; - size_t i; - - if (arena->spare != NULL) { - chunk = arena->spare; - arena->spare = NULL; - } else { - bool zero; - size_t zeroed; - - zero = false; - chunk = (arena_chunk_t *)chunk_alloc(chunksize, &zero); - if (chunk == NULL) - return (NULL); -#ifdef MALLOC_STATS - arena->stats.mapped += chunksize; -#endif - - chunk->arena = arena; - chunk->dirtied = false; - - /* - * Claim that no pages are in use, since the header is merely - * overhead. - */ - chunk->ndirty = 0; - - /* - * Initialize the map to contain one maximal free untouched run. - * Mark the pages as zeroed iff chunk_alloc() returned a zeroed - * chunk. - */ - zeroed = zero ? CHUNK_MAP_ZEROED : 0; - for (i = 0; i < arena_chunk_header_npages; i++) - chunk->map[i].bits = 0; - chunk->map[i].bits = arena_maxclass | zeroed; - for (i++; i < chunk_npages-1; i++) - chunk->map[i].bits = zeroed; - chunk->map[chunk_npages-1].bits = arena_maxclass | zeroed; - } - - /* Insert the run into the runs_avail tree. */ - arena_avail_tree_insert(&arena->runs_avail, - &chunk->map[arena_chunk_header_npages]); - - return (chunk); -} - -static void -arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk) -{ - - if (arena->spare != NULL) { - if (arena->spare->dirtied) { - arena_chunk_tree_dirty_remove( - &chunk->arena->chunks_dirty, arena->spare); - arena->ndirty -= arena->spare->ndirty; - } - chunk_dealloc((void *)arena->spare, chunksize); -#ifdef MALLOC_STATS - arena->stats.mapped -= chunksize; -#endif - } - - /* - * Remove run from runs_avail, regardless of whether this chunk - * will be cached, so that the arena does not use it. Dirty page - * flushing only uses the chunks_dirty tree, so leaving this chunk in - * the chunks_* trees is sufficient for that purpose. - */ - arena_avail_tree_remove(&arena->runs_avail, - &chunk->map[arena_chunk_header_npages]); - - arena->spare = chunk; -} - -static arena_run_t * -arena_run_alloc(arena_t *arena, size_t size, bool large, bool zero) -{ - arena_chunk_t *chunk; - arena_run_t *run; - arena_chunk_map_t *mapelm, key; - - assert(size <= arena_maxclass); - assert((size & PAGE_MASK) == 0); - - /* Search the arena's chunks for the lowest best fit. */ - key.bits = size | CHUNK_MAP_KEY; - mapelm = arena_avail_tree_nsearch(&arena->runs_avail, &key); - if (mapelm != NULL) { - arena_chunk_t *run_chunk = CHUNK_ADDR2BASE(mapelm); - size_t pageind = ((uintptr_t)mapelm - (uintptr_t)run_chunk->map) - / sizeof(arena_chunk_map_t); - - run = (arena_run_t *)((uintptr_t)run_chunk + (pageind - << PAGE_SHIFT)); - arena_run_split(arena, run, size, large, zero); - return (run); - } - - /* - * No usable runs. Create a new chunk from which to allocate the run. - */ - chunk = arena_chunk_alloc(arena); - if (chunk == NULL) - return (NULL); - run = (arena_run_t *)((uintptr_t)chunk + (arena_chunk_header_npages << - PAGE_SHIFT)); - /* Update page map. */ - arena_run_split(arena, run, size, large, zero); - return (run); -} - -#ifdef MALLOC_DEBUG -static arena_chunk_t * -chunks_dirty_iter_cb(arena_chunk_tree_t *tree, arena_chunk_t *chunk, void *arg) -{ - size_t *ndirty = (size_t *)arg; - - assert(chunk->dirtied); - *ndirty += chunk->ndirty; - return (NULL); -} -#endif - -static void -arena_purge(arena_t *arena) -{ - arena_chunk_t *chunk; - size_t i, npages; -#ifdef MALLOC_DEBUG - size_t ndirty = 0; - - arena_chunk_tree_dirty_iter(&arena->chunks_dirty, NULL, - chunks_dirty_iter_cb, (void *)&ndirty); - assert(ndirty == arena->ndirty); -#endif - assert((arena->nactive >> opt_lg_dirty_mult) < arena->ndirty); - -#ifdef MALLOC_STATS - arena->stats.npurge++; -#endif - - /* - * Iterate downward through chunks until enough dirty memory has been - * purged. Terminate as soon as possible in order to minimize the - * number of system calls, even if a chunk has only been partially - * purged. - */ - - while ((arena->nactive >> (opt_lg_dirty_mult + 1)) < arena->ndirty) { - chunk = arena_chunk_tree_dirty_last(&arena->chunks_dirty); - assert(chunk != NULL); - - for (i = chunk_npages - 1; chunk->ndirty > 0; i--) { - assert(i >= arena_chunk_header_npages); - if (chunk->map[i].bits & CHUNK_MAP_DIRTY) { - chunk->map[i].bits ^= CHUNK_MAP_DIRTY; - /* Find adjacent dirty run(s). */ - for (npages = 1; i > arena_chunk_header_npages - && (chunk->map[i - 1].bits & - CHUNK_MAP_DIRTY); npages++) { - i--; - chunk->map[i].bits ^= CHUNK_MAP_DIRTY; - } - chunk->ndirty -= npages; - arena->ndirty -= npages; - - madvise((void *)((uintptr_t)chunk + (i << - PAGE_SHIFT)), (npages << PAGE_SHIFT), - MADV_FREE); -#ifdef MALLOC_STATS - arena->stats.nmadvise++; - arena->stats.purged += npages; -#endif - if ((arena->nactive >> (opt_lg_dirty_mult + 1)) - >= arena->ndirty) - break; - } - } - - if (chunk->ndirty == 0) { - arena_chunk_tree_dirty_remove(&arena->chunks_dirty, - chunk); - chunk->dirtied = false; - } - } -} - -static void -arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty) -{ - arena_chunk_t *chunk; - size_t size, run_ind, run_pages; - - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run); - run_ind = (size_t)(((uintptr_t)run - (uintptr_t)chunk) - >> PAGE_SHIFT); - assert(run_ind >= arena_chunk_header_npages); - assert(run_ind < chunk_npages); - if ((chunk->map[run_ind].bits & CHUNK_MAP_LARGE) != 0) - size = chunk->map[run_ind].bits & ~PAGE_MASK; - else - size = run->bin->run_size; - run_pages = (size >> PAGE_SHIFT); - arena->nactive -= run_pages; - - /* Mark pages as unallocated in the chunk map. */ - if (dirty) { - size_t i; - - for (i = 0; i < run_pages; i++) { - /* - * When (dirty == true), *all* pages within the run - * need to have their dirty bits set, because only - * small runs can create a mixture of clean/dirty - * pages, but such runs are passed to this function - * with (dirty == false). - */ - assert((chunk->map[run_ind + i].bits & CHUNK_MAP_DIRTY) - == 0); - chunk->ndirty++; - arena->ndirty++; - chunk->map[run_ind + i].bits = CHUNK_MAP_DIRTY; - } - } else { - size_t i; - - for (i = 0; i < run_pages; i++) { - chunk->map[run_ind + i].bits &= ~(CHUNK_MAP_LARGE | - CHUNK_MAP_ALLOCATED); - } - } - chunk->map[run_ind].bits = size | (chunk->map[run_ind].bits & - CHUNK_MAP_FLAGS_MASK); - chunk->map[run_ind+run_pages-1].bits = size | - (chunk->map[run_ind+run_pages-1].bits & CHUNK_MAP_FLAGS_MASK); - - /* Try to coalesce forward. */ - if (run_ind + run_pages < chunk_npages && - (chunk->map[run_ind+run_pages].bits & CHUNK_MAP_ALLOCATED) == 0) { - size_t nrun_size = chunk->map[run_ind+run_pages].bits & - ~PAGE_MASK; - - /* - * Remove successor from runs_avail; the coalesced run is - * inserted later. - */ - arena_avail_tree_remove(&arena->runs_avail, - &chunk->map[run_ind+run_pages]); - - size += nrun_size; - run_pages = size >> PAGE_SHIFT; - - assert((chunk->map[run_ind+run_pages-1].bits & ~PAGE_MASK) - == nrun_size); - chunk->map[run_ind].bits = size | (chunk->map[run_ind].bits & - CHUNK_MAP_FLAGS_MASK); - chunk->map[run_ind+run_pages-1].bits = size | - (chunk->map[run_ind+run_pages-1].bits & - CHUNK_MAP_FLAGS_MASK); - } - - /* Try to coalesce backward. */ - if (run_ind > arena_chunk_header_npages && (chunk->map[run_ind-1].bits & - CHUNK_MAP_ALLOCATED) == 0) { - size_t prun_size = chunk->map[run_ind-1].bits & ~PAGE_MASK; - - run_ind -= prun_size >> PAGE_SHIFT; - - /* - * Remove predecessor from runs_avail; the coalesced run is - * inserted later. - */ - arena_avail_tree_remove(&arena->runs_avail, - &chunk->map[run_ind]); - - size += prun_size; - run_pages = size >> PAGE_SHIFT; - - assert((chunk->map[run_ind].bits & ~PAGE_MASK) == prun_size); - chunk->map[run_ind].bits = size | (chunk->map[run_ind].bits & - CHUNK_MAP_FLAGS_MASK); - chunk->map[run_ind+run_pages-1].bits = size | - (chunk->map[run_ind+run_pages-1].bits & - CHUNK_MAP_FLAGS_MASK); - } - - /* Insert into runs_avail, now that coalescing is complete. */ - arena_avail_tree_insert(&arena->runs_avail, &chunk->map[run_ind]); - - /* - * Deallocate chunk if it is now completely unused. The bit - * manipulation checks whether the first run is unallocated and extends - * to the end of the chunk. - */ - if ((chunk->map[arena_chunk_header_npages].bits & (~PAGE_MASK | - CHUNK_MAP_ALLOCATED)) == arena_maxclass) - arena_chunk_dealloc(arena, chunk); - - /* - * It is okay to do dirty page processing even if the chunk was - * deallocated above, since in that case it is the spare. Waiting - * until after possible chunk deallocation to do dirty processing - * allows for an old spare to be fully deallocated, thus decreasing the - * chances of spuriously crossing the dirty page purging threshold. - */ - if (dirty) { - if (chunk->dirtied == false) { - arena_chunk_tree_dirty_insert(&arena->chunks_dirty, - chunk); - chunk->dirtied = true; - } - - /* Enforce opt_lg_dirty_mult. */ - if (opt_lg_dirty_mult >= 0 && (arena->nactive >> - opt_lg_dirty_mult) < arena->ndirty) - arena_purge(arena); - } -} - -static void -arena_run_trim_head(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run, - size_t oldsize, size_t newsize) -{ - size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> PAGE_SHIFT; - size_t head_npages = (oldsize - newsize) >> PAGE_SHIFT; - - assert(oldsize > newsize); - - /* - * Update the chunk map so that arena_run_dalloc() can treat the - * leading run as separately allocated. - */ - assert((chunk->map[pageind].bits & CHUNK_MAP_DIRTY) == 0); - chunk->map[pageind].bits = (oldsize - newsize) | CHUNK_MAP_LARGE | - CHUNK_MAP_ALLOCATED; - assert((chunk->map[pageind+head_npages].bits & CHUNK_MAP_DIRTY) == 0); - chunk->map[pageind+head_npages].bits = newsize | CHUNK_MAP_LARGE | - CHUNK_MAP_ALLOCATED; - - arena_run_dalloc(arena, run, false); -} - -static void -arena_run_trim_tail(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run, - size_t oldsize, size_t newsize, bool dirty) -{ - size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> PAGE_SHIFT; - size_t npages = newsize >> PAGE_SHIFT; - - assert(oldsize > newsize); - - /* - * Update the chunk map so that arena_run_dalloc() can treat the - * trailing run as separately allocated. - */ - assert((chunk->map[pageind].bits & CHUNK_MAP_DIRTY) == 0); - chunk->map[pageind].bits = newsize | CHUNK_MAP_LARGE | - CHUNK_MAP_ALLOCATED; - assert((chunk->map[pageind+npages].bits & CHUNK_MAP_DIRTY) == 0); - chunk->map[pageind+npages].bits = (oldsize - newsize) | CHUNK_MAP_LARGE - | CHUNK_MAP_ALLOCATED; - - arena_run_dalloc(arena, (arena_run_t *)((uintptr_t)run + newsize), - dirty); -} - -static arena_run_t * -arena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin) -{ - arena_chunk_map_t *mapelm; - arena_run_t *run; - unsigned i, remainder; - - /* Look for a usable run. */ - mapelm = arena_run_tree_first(&bin->runs); - if (mapelm != NULL) { - arena_chunk_t *chunk; - size_t pageind; - - /* run is guaranteed to have available space. */ - arena_run_tree_remove(&bin->runs, mapelm); - - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(mapelm); - pageind = (((uintptr_t)mapelm - (uintptr_t)chunk->map) / - sizeof(arena_chunk_map_t)); - run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind - - ((mapelm->bits & CHUNK_MAP_PG_MASK) >> CHUNK_MAP_PG_SHIFT)) - << PAGE_SHIFT)); -#ifdef MALLOC_STATS - bin->stats.reruns++; -#endif - return (run); - } - /* No existing runs have any space available. */ - - /* Allocate a new run. */ - run = arena_run_alloc(arena, bin->run_size, false, false); - if (run == NULL) - return (NULL); - - /* Initialize run internals. */ - run->bin = bin; - - for (i = 0; i < bin->regs_mask_nelms - 1; i++) - run->regs_mask[i] = UINT_MAX; - remainder = bin->nregs & ((1U << (LG_SIZEOF_INT + 3)) - 1); - if (remainder == 0) - run->regs_mask[i] = UINT_MAX; - else { - /* The last element has spare bits that need to be unset. */ - run->regs_mask[i] = (UINT_MAX >> ((1U << (LG_SIZEOF_INT + 3)) - - remainder)); - } - - run->regs_minelm = 0; - - run->nfree = bin->nregs; -#ifdef MALLOC_DEBUG - run->magic = ARENA_RUN_MAGIC; -#endif - -#ifdef MALLOC_STATS - bin->stats.nruns++; - bin->stats.curruns++; - if (bin->stats.curruns > bin->stats.highruns) - bin->stats.highruns = bin->stats.curruns; -#endif - return (run); -} - -/* bin->runcur must have space available before this function is called. */ -static inline void * -arena_bin_malloc_easy(arena_t *arena, arena_bin_t *bin, arena_run_t *run) -{ - void *ret; - - assert(run->magic == ARENA_RUN_MAGIC); - assert(run->nfree > 0); - - ret = arena_run_reg_alloc(run, bin); - assert(ret != NULL); - run->nfree--; - - return (ret); -} - -/* Re-fill bin->runcur, then call arena_bin_malloc_easy(). */ -static void * -arena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin) -{ - - bin->runcur = arena_bin_nonfull_run_get(arena, bin); - if (bin->runcur == NULL) - return (NULL); - assert(bin->runcur->magic == ARENA_RUN_MAGIC); - assert(bin->runcur->nfree > 0); - - return (arena_bin_malloc_easy(arena, bin, bin->runcur)); -} - -/* - * Calculate bin->run_size such that it meets the following constraints: - * - * *) bin->run_size >= min_run_size - * *) bin->run_size <= arena_maxclass - * *) bin->run_size <= RUN_MAX_SMALL - * *) run header overhead <= RUN_MAX_OVRHD (or header overhead relaxed). - * *) run header size < PAGE_SIZE - * - * bin->nregs, bin->regs_mask_nelms, and bin->reg0_offset are - * also calculated here, since these settings are all interdependent. - */ -static size_t -arena_bin_run_size_calc(arena_bin_t *bin, size_t min_run_size) -{ - size_t try_run_size, good_run_size; - unsigned good_nregs, good_mask_nelms, good_reg0_offset; - unsigned try_nregs, try_mask_nelms, try_reg0_offset; - - assert(min_run_size >= PAGE_SIZE); - assert(min_run_size <= arena_maxclass); - assert(min_run_size <= RUN_MAX_SMALL); - - /* - * Calculate known-valid settings before entering the run_size - * expansion loop, so that the first part of the loop always copies - * valid settings. - * - * The do..while loop iteratively reduces the number of regions until - * the run header and the regions no longer overlap. A closed formula - * would be quite messy, since there is an interdependency between the - * header's mask length and the number of regions. - */ - try_run_size = min_run_size; - try_nregs = ((try_run_size - sizeof(arena_run_t)) / bin->reg_size) - + 1; /* Counter-act try_nregs-- in loop. */ - do { - try_nregs--; - try_mask_nelms = (try_nregs >> (LG_SIZEOF_INT + 3)) + - ((try_nregs & ((1U << (LG_SIZEOF_INT + 3)) - 1)) ? 1 : 0); - try_reg0_offset = try_run_size - (try_nregs * bin->reg_size); - } while (sizeof(arena_run_t) + (sizeof(unsigned) * (try_mask_nelms - 1)) - > try_reg0_offset); - - /* run_size expansion loop. */ - do { - /* - * Copy valid settings before trying more aggressive settings. - */ - good_run_size = try_run_size; - good_nregs = try_nregs; - good_mask_nelms = try_mask_nelms; - good_reg0_offset = try_reg0_offset; - - /* Try more aggressive settings. */ - try_run_size += PAGE_SIZE; - try_nregs = ((try_run_size - sizeof(arena_run_t)) / - bin->reg_size) + 1; /* Counter-act try_nregs-- in loop. */ - do { - try_nregs--; - try_mask_nelms = (try_nregs >> (LG_SIZEOF_INT + 3)) + - ((try_nregs & ((1U << (LG_SIZEOF_INT + 3)) - 1)) ? - 1 : 0); - try_reg0_offset = try_run_size - (try_nregs * - bin->reg_size); - } while (sizeof(arena_run_t) + (sizeof(unsigned) * - (try_mask_nelms - 1)) > try_reg0_offset); - } while (try_run_size <= arena_maxclass && try_run_size <= RUN_MAX_SMALL - && RUN_MAX_OVRHD * (bin->reg_size << 3) > RUN_MAX_OVRHD_RELAX - && (try_reg0_offset << RUN_BFP) > RUN_MAX_OVRHD * try_run_size - && (sizeof(arena_run_t) + (sizeof(unsigned) * (try_mask_nelms - 1))) - < PAGE_SIZE); - - assert(sizeof(arena_run_t) + (sizeof(unsigned) * (good_mask_nelms - 1)) - <= good_reg0_offset); - assert((good_mask_nelms << (LG_SIZEOF_INT + 3)) >= good_nregs); - - /* Copy final settings. */ - bin->run_size = good_run_size; - bin->nregs = good_nregs; - bin->regs_mask_nelms = good_mask_nelms; - bin->reg0_offset = good_reg0_offset; - - return (good_run_size); -} - -#ifdef MALLOC_TCACHE -static inline void -tcache_event(tcache_t *tcache) -{ - - if (tcache_gc_incr == 0) - return; - - tcache->ev_cnt++; - assert(tcache->ev_cnt <= tcache_gc_incr); - if (tcache->ev_cnt >= tcache_gc_incr) { - size_t binind = tcache->next_gc_bin; - tcache_bin_t *tbin = tcache->tbins[binind]; - - if (tbin != NULL) { - if (tbin->high_water == 0) { - /* - * This bin went completely unused for an - * entire GC cycle, so throw away the tbin. - */ - assert(tbin->ncached == 0); - tcache_bin_destroy(tcache, tbin, binind); - tcache->tbins[binind] = NULL; - } else { - if (tbin->low_water > 0) { - /* - * Flush (ceiling) half of the objects - * below the low water mark. - */ - tcache_bin_flush(tbin, binind, - tbin->ncached - (tbin->low_water >> - 1) - (tbin->low_water & 1)); - } - tbin->low_water = tbin->ncached; - tbin->high_water = tbin->ncached; - } - } - - tcache->next_gc_bin++; - if (tcache->next_gc_bin == nbins) - tcache->next_gc_bin = 0; - tcache->ev_cnt = 0; - } -} - -static inline void * -tcache_bin_alloc(tcache_bin_t *tbin) -{ - - if (tbin->ncached == 0) - return (NULL); - tbin->ncached--; - if (tbin->ncached < tbin->low_water) - tbin->low_water = tbin->ncached; - return (tbin->slots[tbin->ncached]); -} - -static void -tcache_bin_fill(tcache_t *tcache, tcache_bin_t *tbin, size_t binind) -{ - arena_t *arena; - arena_bin_t *bin; - arena_run_t *run; - void *ptr; - unsigned i; - - assert(tbin->ncached == 0); - - arena = tcache->arena; - bin = &arena->bins[binind]; - malloc_spin_lock(&arena->lock); - for (i = 0; i < (tcache_nslots >> 1); i++) { - if ((run = bin->runcur) != NULL && run->nfree > 0) - ptr = arena_bin_malloc_easy(arena, bin, run); - else - ptr = arena_bin_malloc_hard(arena, bin); - if (ptr == NULL) - break; - /* - * Fill tbin such that the objects lowest in memory are used - * first. - */ - tbin->slots[(tcache_nslots >> 1) - 1 - i] = ptr; - } -#ifdef MALLOC_STATS - bin->stats.nfills++; - bin->stats.nrequests += tbin->tstats.nrequests; - if (bin->reg_size <= small_maxclass) { - arena->stats.nmalloc_small += (i - tbin->ncached); - arena->stats.allocated_small += (i - tbin->ncached) * - bin->reg_size; - arena->stats.nmalloc_small += tbin->tstats.nrequests; - } else { - arena->stats.nmalloc_medium += (i - tbin->ncached); - arena->stats.allocated_medium += (i - tbin->ncached) * - bin->reg_size; - arena->stats.nmalloc_medium += tbin->tstats.nrequests; - } - tbin->tstats.nrequests = 0; -#endif - malloc_spin_unlock(&arena->lock); - tbin->ncached = i; - if (tbin->ncached > tbin->high_water) - tbin->high_water = tbin->ncached; -} - -static inline void * -tcache_alloc(tcache_t *tcache, size_t size, bool zero) -{ - void *ret; - tcache_bin_t *tbin; - size_t binind; - - if (size <= small_maxclass) - binind = small_size2bin[size]; - else { - binind = mbin0 + ((MEDIUM_CEILING(size) - medium_min) >> - lg_mspace); - } - assert(binind < nbins); - tbin = tcache->tbins[binind]; - if (tbin == NULL) { - tbin = tcache_bin_create(tcache->arena); - if (tbin == NULL) - return (NULL); - tcache->tbins[binind] = tbin; - } - - ret = tcache_bin_alloc(tbin); - if (ret == NULL) { - ret = tcache_alloc_hard(tcache, tbin, binind); - if (ret == NULL) - return (NULL); - } - - if (zero == false) { - if (opt_junk) - memset(ret, 0xa5, size); - else if (opt_zero) - memset(ret, 0, size); - } else - memset(ret, 0, size); - -#ifdef MALLOC_STATS - tbin->tstats.nrequests++; -#endif - tcache_event(tcache); - return (ret); -} - -static void * -tcache_alloc_hard(tcache_t *tcache, tcache_bin_t *tbin, size_t binind) -{ - void *ret; - - tcache_bin_fill(tcache, tbin, binind); - ret = tcache_bin_alloc(tbin); - - return (ret); -} -#endif - -static inline void * -arena_malloc_small(arena_t *arena, size_t size, bool zero) -{ - void *ret; - arena_bin_t *bin; - arena_run_t *run; - size_t binind; - - binind = small_size2bin[size]; - assert(binind < mbin0); - bin = &arena->bins[binind]; - size = bin->reg_size; - - malloc_spin_lock(&arena->lock); - if ((run = bin->runcur) != NULL && run->nfree > 0) - ret = arena_bin_malloc_easy(arena, bin, run); - else - ret = arena_bin_malloc_hard(arena, bin); - - if (ret == NULL) { - malloc_spin_unlock(&arena->lock); - return (NULL); - } - -#ifdef MALLOC_STATS -# ifdef MALLOC_TCACHE - if (__isthreaded == false) { -# endif - bin->stats.nrequests++; - arena->stats.nmalloc_small++; -# ifdef MALLOC_TCACHE - } -# endif - arena->stats.allocated_small += size; -#endif - malloc_spin_unlock(&arena->lock); - - if (zero == false) { - if (opt_junk) - memset(ret, 0xa5, size); - else if (opt_zero) - memset(ret, 0, size); - } else - memset(ret, 0, size); - - return (ret); -} - -static void * -arena_malloc_medium(arena_t *arena, size_t size, bool zero) -{ - void *ret; - arena_bin_t *bin; - arena_run_t *run; - size_t binind; - - size = MEDIUM_CEILING(size); - binind = mbin0 + ((size - medium_min) >> lg_mspace); - assert(binind < nbins); - bin = &arena->bins[binind]; - assert(bin->reg_size == size); - - malloc_spin_lock(&arena->lock); - if ((run = bin->runcur) != NULL && run->nfree > 0) - ret = arena_bin_malloc_easy(arena, bin, run); - else - ret = arena_bin_malloc_hard(arena, bin); - - if (ret == NULL) { - malloc_spin_unlock(&arena->lock); - return (NULL); - } - -#ifdef MALLOC_STATS -# ifdef MALLOC_TCACHE - if (__isthreaded == false) { -# endif - bin->stats.nrequests++; - arena->stats.nmalloc_medium++; -# ifdef MALLOC_TCACHE - } -# endif - arena->stats.allocated_medium += size; -#endif - malloc_spin_unlock(&arena->lock); - - if (zero == false) { - if (opt_junk) - memset(ret, 0xa5, size); - else if (opt_zero) - memset(ret, 0, size); - } else - memset(ret, 0, size); - - return (ret); -} - -static void * -arena_malloc_large(arena_t *arena, size_t size, bool zero) -{ - void *ret; - - /* Large allocation. */ - size = PAGE_CEILING(size); - malloc_spin_lock(&arena->lock); - ret = (void *)arena_run_alloc(arena, size, true, zero); - if (ret == NULL) { - malloc_spin_unlock(&arena->lock); - return (NULL); - } -#ifdef MALLOC_STATS - arena->stats.nmalloc_large++; - arena->stats.allocated_large += size; - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].nrequests++; - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns++; - if (arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns > - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns) { - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns = - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns; - } -#endif - malloc_spin_unlock(&arena->lock); - - if (zero == false) { - if (opt_junk) - memset(ret, 0xa5, size); - else if (opt_zero) - memset(ret, 0, size); - } - - return (ret); -} - -static inline void * -arena_malloc(size_t size, bool zero) -{ - - assert(size != 0); - assert(QUANTUM_CEILING(size) <= arena_maxclass); - - if (size <= bin_maxclass) { -#ifdef MALLOC_TCACHE - if (__isthreaded && tcache_nslots) { - tcache_t *tcache = tcache_tls; - if ((uintptr_t)tcache > (uintptr_t)1) - return (tcache_alloc(tcache, size, zero)); - else if (tcache == NULL) { - tcache = tcache_create(choose_arena()); - if (tcache == NULL) - return (NULL); - return (tcache_alloc(tcache, size, zero)); - } - } -#endif - if (size <= small_maxclass) { - return (arena_malloc_small(choose_arena(), size, - zero)); - } else { - return (arena_malloc_medium(choose_arena(), - size, zero)); - } - } else - return (arena_malloc_large(choose_arena(), size, zero)); -} - -static inline void * -imalloc(size_t size) -{ - - assert(size != 0); - - if (size <= arena_maxclass) - return (arena_malloc(size, false)); - else - return (huge_malloc(size, false)); -} - -static inline void * -icalloc(size_t size) -{ - - if (size <= arena_maxclass) - return (arena_malloc(size, true)); - else - return (huge_malloc(size, true)); -} - -/* Only handles large allocations that require more than page alignment. */ -static void * -arena_palloc(arena_t *arena, size_t alignment, size_t size, size_t alloc_size) -{ - void *ret; - size_t offset; - arena_chunk_t *chunk; - - assert((size & PAGE_MASK) == 0); - assert((alignment & PAGE_MASK) == 0); - - malloc_spin_lock(&arena->lock); - ret = (void *)arena_run_alloc(arena, alloc_size, true, false); - if (ret == NULL) { - malloc_spin_unlock(&arena->lock); - return (NULL); - } - - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ret); - - offset = (uintptr_t)ret & (alignment - 1); - assert((offset & PAGE_MASK) == 0); - assert(offset < alloc_size); - if (offset == 0) - arena_run_trim_tail(arena, chunk, ret, alloc_size, size, false); - else { - size_t leadsize, trailsize; - - leadsize = alignment - offset; - if (leadsize > 0) { - arena_run_trim_head(arena, chunk, ret, alloc_size, - alloc_size - leadsize); - ret = (void *)((uintptr_t)ret + leadsize); - } - - trailsize = alloc_size - leadsize - size; - if (trailsize != 0) { - /* Trim trailing space. */ - assert(trailsize < alloc_size); - arena_run_trim_tail(arena, chunk, ret, size + trailsize, - size, false); - } - } - -#ifdef MALLOC_STATS - arena->stats.nmalloc_large++; - arena->stats.allocated_large += size; - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].nrequests++; - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns++; - if (arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns > - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns) { - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns = - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns; - } -#endif - malloc_spin_unlock(&arena->lock); - - if (opt_junk) - memset(ret, 0xa5, size); - else if (opt_zero) - memset(ret, 0, size); - return (ret); -} - -static inline void * -ipalloc(size_t alignment, size_t size) -{ - void *ret; - size_t ceil_size; - - /* - * Round size up to the nearest multiple of alignment. - * - * This done, we can take advantage of the fact that for each small - * size class, every object is aligned at the smallest power of two - * that is non-zero in the base two representation of the size. For - * example: - * - * Size | Base 2 | Minimum alignment - * -----+----------+------------------ - * 96 | 1100000 | 32 - * 144 | 10100000 | 32 - * 192 | 11000000 | 64 - * - * Depending on runtime settings, it is possible that arena_malloc() - * will further round up to a power of two, but that never causes - * correctness issues. - */ - ceil_size = (size + (alignment - 1)) & (-alignment); - /* - * (ceil_size < size) protects against the combination of maximal - * alignment and size greater than maximal alignment. - */ - if (ceil_size < size) { - /* size_t overflow. */ - return (NULL); - } - - if (ceil_size <= PAGE_SIZE || (alignment <= PAGE_SIZE - && ceil_size <= arena_maxclass)) - ret = arena_malloc(ceil_size, false); - else { - size_t run_size; - - /* - * We can't achieve subpage alignment, so round up alignment - * permanently; it makes later calculations simpler. - */ - alignment = PAGE_CEILING(alignment); - ceil_size = PAGE_CEILING(size); - /* - * (ceil_size < size) protects against very large sizes within - * PAGE_SIZE of SIZE_T_MAX. - * - * (ceil_size + alignment < ceil_size) protects against the - * combination of maximal alignment and ceil_size large enough - * to cause overflow. This is similar to the first overflow - * check above, but it needs to be repeated due to the new - * ceil_size value, which may now be *equal* to maximal - * alignment, whereas before we only detected overflow if the - * original size was *greater* than maximal alignment. - */ - if (ceil_size < size || ceil_size + alignment < ceil_size) { - /* size_t overflow. */ - return (NULL); - } - - /* - * Calculate the size of the over-size run that arena_palloc() - * would need to allocate in order to guarantee the alignment. - */ - if (ceil_size >= alignment) - run_size = ceil_size + alignment - PAGE_SIZE; - else { - /* - * It is possible that (alignment << 1) will cause - * overflow, but it doesn't matter because we also - * subtract PAGE_SIZE, which in the case of overflow - * leaves us with a very large run_size. That causes - * the first conditional below to fail, which means - * that the bogus run_size value never gets used for - * anything important. - */ - run_size = (alignment << 1) - PAGE_SIZE; - } - - if (run_size <= arena_maxclass) { - ret = arena_palloc(choose_arena(), alignment, ceil_size, - run_size); - } else if (alignment <= chunksize) - ret = huge_malloc(ceil_size, false); - else - ret = huge_palloc(alignment, ceil_size); - } - - assert(((uintptr_t)ret & (alignment - 1)) == 0); - return (ret); -} - -static bool -arena_is_large(const void *ptr) -{ - arena_chunk_t *chunk; - size_t pageind, mapbits; - - assert(ptr != NULL); - assert(CHUNK_ADDR2BASE(ptr) != ptr); - - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); - pageind = (((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT); - mapbits = chunk->map[pageind].bits; - assert((mapbits & CHUNK_MAP_ALLOCATED) != 0); - return ((mapbits & CHUNK_MAP_LARGE) != 0); -} - -/* Return the size of the allocation pointed to by ptr. */ -static size_t -arena_salloc(const void *ptr) -{ - size_t ret; - arena_chunk_t *chunk; - size_t pageind, mapbits; - - assert(ptr != NULL); - assert(CHUNK_ADDR2BASE(ptr) != ptr); - - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); - pageind = (((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT); - mapbits = chunk->map[pageind].bits; - assert((mapbits & CHUNK_MAP_ALLOCATED) != 0); - if ((mapbits & CHUNK_MAP_LARGE) == 0) { - arena_run_t *run = (arena_run_t *)((uintptr_t)chunk + - (uintptr_t)((pageind - ((mapbits & CHUNK_MAP_PG_MASK) >> - CHUNK_MAP_PG_SHIFT)) << PAGE_SHIFT)); - assert(run->magic == ARENA_RUN_MAGIC); - ret = run->bin->reg_size; - } else { - ret = mapbits & ~PAGE_MASK; - assert(ret != 0); - } - - return (ret); -} - -static inline size_t -isalloc(const void *ptr) -{ - size_t ret; - arena_chunk_t *chunk; - - assert(ptr != NULL); - - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); - if (chunk != ptr) { - /* Region. */ - assert(chunk->arena->magic == ARENA_MAGIC); - - ret = arena_salloc(ptr); - } else { - extent_node_t *node, key; - - /* Chunk (huge allocation). */ - - malloc_mutex_lock(&huge_mtx); - - /* Extract from tree of huge allocations. */ - key.addr = __DECONST(void *, ptr); - node = extent_tree_ad_search(&huge, &key); - assert(node != NULL); - - ret = node->size; - - malloc_mutex_unlock(&huge_mtx); - } - - return (ret); -} - -static inline void -arena_dalloc_bin(arena_t *arena, arena_chunk_t *chunk, void *ptr, - arena_chunk_map_t *mapelm) -{ - size_t pageind; - arena_run_t *run; - arena_bin_t *bin; - size_t size; - - pageind = (((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT); - run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind - - ((mapelm->bits & CHUNK_MAP_PG_MASK) >> CHUNK_MAP_PG_SHIFT)) << - PAGE_SHIFT)); - assert(run->magic == ARENA_RUN_MAGIC); - bin = run->bin; - size = bin->reg_size; - - if (opt_junk) - memset(ptr, 0x5a, size); - - arena_run_reg_dalloc(run, bin, ptr, size); - run->nfree++; - - if (run->nfree == bin->nregs) - arena_dalloc_bin_run(arena, chunk, run, bin); - else if (run->nfree == 1 && run != bin->runcur) { - /* - * Make sure that bin->runcur always refers to the lowest - * non-full run, if one exists. - */ - if (bin->runcur == NULL) - bin->runcur = run; - else if ((uintptr_t)run < (uintptr_t)bin->runcur) { - /* Switch runcur. */ - if (bin->runcur->nfree > 0) { - arena_chunk_t *runcur_chunk = - CHUNK_ADDR2BASE(bin->runcur); - size_t runcur_pageind = - (((uintptr_t)bin->runcur - - (uintptr_t)runcur_chunk)) >> PAGE_SHIFT; - arena_chunk_map_t *runcur_mapelm = - &runcur_chunk->map[runcur_pageind]; - - /* Insert runcur. */ - arena_run_tree_insert(&bin->runs, - runcur_mapelm); - } - bin->runcur = run; - } else { - size_t run_pageind = (((uintptr_t)run - - (uintptr_t)chunk)) >> PAGE_SHIFT; - arena_chunk_map_t *run_mapelm = - &chunk->map[run_pageind]; - - assert(arena_run_tree_search(&bin->runs, run_mapelm) == - NULL); - arena_run_tree_insert(&bin->runs, run_mapelm); - } - } - -#ifdef MALLOC_STATS - if (size <= small_maxclass) { - arena->stats.allocated_small -= size; - arena->stats.ndalloc_small++; - } else { - arena->stats.allocated_medium -= size; - arena->stats.ndalloc_medium++; - } -#endif -} - -static void -arena_dalloc_bin_run(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run, - arena_bin_t *bin) -{ - size_t run_ind; - - /* Deallocate run. */ - if (run == bin->runcur) - bin->runcur = NULL; - else if (bin->nregs != 1) { - size_t run_pageind = (((uintptr_t)run - - (uintptr_t)chunk)) >> PAGE_SHIFT; - arena_chunk_map_t *run_mapelm = - &chunk->map[run_pageind]; - /* - * This block's conditional is necessary because if the - * run only contains one region, then it never gets - * inserted into the non-full runs tree. - */ - arena_run_tree_remove(&bin->runs, run_mapelm); - } - /* - * Mark the first page as dirty. The dirty bit for every other page in - * the run is already properly set, which means we can call - * arena_run_dalloc(..., false), thus potentially avoiding the needless - * creation of many dirty pages. - */ - run_ind = (size_t)(((uintptr_t)run - (uintptr_t)chunk) >> PAGE_SHIFT); - assert((chunk->map[run_ind].bits & CHUNK_MAP_DIRTY) == 0); - chunk->map[run_ind].bits |= CHUNK_MAP_DIRTY; - chunk->ndirty++; - arena->ndirty++; - -#ifdef MALLOC_DEBUG - run->magic = 0; -#endif - arena_run_dalloc(arena, run, false); -#ifdef MALLOC_STATS - bin->stats.curruns--; -#endif - - if (chunk->dirtied == false) { - arena_chunk_tree_dirty_insert(&arena->chunks_dirty, chunk); - chunk->dirtied = true; - } - /* Enforce opt_lg_dirty_mult. */ - if (opt_lg_dirty_mult >= 0 && (arena->nactive >> opt_lg_dirty_mult) < - arena->ndirty) - arena_purge(arena); -} - -#ifdef MALLOC_STATS -static void -arena_stats_print(arena_t *arena) -{ - - malloc_printf("dirty pages: %zu:%zu active:dirty, %"PRIu64" sweep%s," - " %"PRIu64" madvise%s, %"PRIu64" purged\n", - arena->nactive, arena->ndirty, - arena->stats.npurge, arena->stats.npurge == 1 ? "" : "s", - arena->stats.nmadvise, arena->stats.nmadvise == 1 ? "" : "s", - arena->stats.purged); - - malloc_printf(" allocated nmalloc ndalloc\n"); - malloc_printf("small: %12zu %12"PRIu64" %12"PRIu64"\n", - arena->stats.allocated_small, arena->stats.nmalloc_small, - arena->stats.ndalloc_small); - malloc_printf("medium: %12zu %12"PRIu64" %12"PRIu64"\n", - arena->stats.allocated_medium, arena->stats.nmalloc_medium, - arena->stats.ndalloc_medium); - malloc_printf("large: %12zu %12"PRIu64" %12"PRIu64"\n", - arena->stats.allocated_large, arena->stats.nmalloc_large, - arena->stats.ndalloc_large); - malloc_printf("total: %12zu %12"PRIu64" %12"PRIu64"\n", - arena->stats.allocated_small + arena->stats.allocated_medium + - arena->stats.allocated_large, arena->stats.nmalloc_small + - arena->stats.nmalloc_medium + arena->stats.nmalloc_large, - arena->stats.ndalloc_small + arena->stats.ndalloc_medium + - arena->stats.ndalloc_large); - malloc_printf("mapped: %12zu\n", arena->stats.mapped); - - if (arena->stats.nmalloc_small + arena->stats.nmalloc_medium > 0) { - unsigned i, gap_start; -#ifdef MALLOC_TCACHE - malloc_printf("bins: bin size regs pgs requests " - "nfills nflushes newruns reruns maxruns curruns\n"); -#else - malloc_printf("bins: bin size regs pgs requests " - "newruns reruns maxruns curruns\n"); -#endif - for (i = 0, gap_start = UINT_MAX; i < nbins; i++) { - if (arena->bins[i].stats.nruns == 0) { - if (gap_start == UINT_MAX) - gap_start = i; - } else { - if (gap_start != UINT_MAX) { - if (i > gap_start + 1) { - /* - * Gap of more than one size - * class. - */ - malloc_printf("[%u..%u]\n", - gap_start, i - 1); - } else { - /* Gap of one size class. */ - malloc_printf("[%u]\n", - gap_start); - } - gap_start = UINT_MAX; - } - malloc_printf( - "%13u %1s %5u %4u %3u %9"PRIu64" %9"PRIu64 -#ifdef MALLOC_TCACHE - " %9"PRIu64" %9"PRIu64 -#endif - " %9"PRIu64" %7zu %7zu\n", - i, - i < ntbins ? "T" : i < ntbins + nqbins ? - "Q" : i < ntbins + nqbins + ncbins ? "C" : - i < ntbins + nqbins + ncbins + nsbins ? "S" - : "M", - arena->bins[i].reg_size, - arena->bins[i].nregs, - arena->bins[i].run_size >> PAGE_SHIFT, - arena->bins[i].stats.nrequests, -#ifdef MALLOC_TCACHE - arena->bins[i].stats.nfills, - arena->bins[i].stats.nflushes, -#endif - arena->bins[i].stats.nruns, - arena->bins[i].stats.reruns, - arena->bins[i].stats.highruns, - arena->bins[i].stats.curruns); - } - } - if (gap_start != UINT_MAX) { - if (i > gap_start + 1) { - /* Gap of more than one size class. */ - malloc_printf("[%u..%u]\n", gap_start, i - 1); - } else { - /* Gap of one size class. */ - malloc_printf("[%u]\n", gap_start); - } - } - } - - if (arena->stats.nmalloc_large > 0) { - size_t i; - ssize_t gap_start; - size_t nlclasses = (chunksize - PAGE_SIZE) >> PAGE_SHIFT; - - malloc_printf( - "large: size pages nrequests maxruns curruns\n"); - - for (i = 0, gap_start = -1; i < nlclasses; i++) { - if (arena->stats.lstats[i].nrequests == 0) { - if (gap_start == -1) - gap_start = i; - } else { - if (gap_start != -1) { - malloc_printf("[%zu]\n", i - gap_start); - gap_start = -1; - } - malloc_printf( - "%13zu %5zu %9"PRIu64" %9zu %9zu\n", - (i+1) << PAGE_SHIFT, i+1, - arena->stats.lstats[i].nrequests, - arena->stats.lstats[i].highruns, - arena->stats.lstats[i].curruns); - } - } - if (gap_start != -1) - malloc_printf("[%zu]\n", i - gap_start); - } -} -#endif - -static void -stats_print_atexit(void) -{ - -#if (defined(MALLOC_TCACHE) && defined(MALLOC_STATS)) - unsigned i; - - /* - * Merge stats from extant threads. This is racy, since individual - * threads do not lock when recording tcache stats events. As a - * consequence, the final stats may be slightly out of date by the time - * they are reported, if other threads continue to allocate. - */ - for (i = 0; i < narenas; i++) { - arena_t *arena = arenas[i]; - if (arena != NULL) { - tcache_t *tcache; - - malloc_spin_lock(&arena->lock); - ql_foreach(tcache, &arena->tcache_ql, link) { - tcache_stats_merge(tcache, arena); - } - malloc_spin_unlock(&arena->lock); - } - } -#endif - malloc_stats_print(); -} - -#ifdef MALLOC_TCACHE -static void -tcache_bin_flush(tcache_bin_t *tbin, size_t binind, unsigned rem) -{ - arena_chunk_t *chunk; - arena_t *arena; - void *ptr; - unsigned i, ndeferred, ncached; - - for (ndeferred = tbin->ncached - rem; ndeferred > 0;) { - ncached = ndeferred; - /* Lock the arena associated with the first object. */ - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(tbin->slots[0]); - arena = chunk->arena; - malloc_spin_lock(&arena->lock); - /* Deallocate every object that belongs to the locked arena. */ - for (i = ndeferred = 0; i < ncached; i++) { - ptr = tbin->slots[i]; - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); - if (chunk->arena == arena) { - size_t pageind = (((uintptr_t)ptr - - (uintptr_t)chunk) >> PAGE_SHIFT); - arena_chunk_map_t *mapelm = - &chunk->map[pageind]; - arena_dalloc_bin(arena, chunk, ptr, mapelm); - } else { - /* - * This object was allocated via a different - * arena than the one that is currently locked. - * Stash the object, so that it can be handled - * in a future pass. - */ - tbin->slots[ndeferred] = ptr; - ndeferred++; - } - } -#ifdef MALLOC_STATS - arena->bins[binind].stats.nflushes++; - { - arena_bin_t *bin = &arena->bins[binind]; - bin->stats.nrequests += tbin->tstats.nrequests; - if (bin->reg_size <= small_maxclass) { - arena->stats.nmalloc_small += - tbin->tstats.nrequests; - } else { - arena->stats.nmalloc_medium += - tbin->tstats.nrequests; - } - tbin->tstats.nrequests = 0; - } -#endif - malloc_spin_unlock(&arena->lock); - } - - if (rem > 0) { - /* - * Shift the remaining valid pointers to the base of the slots - * array. - */ - memmove(&tbin->slots[0], &tbin->slots[tbin->ncached - rem], - rem * sizeof(void *)); - } - tbin->ncached = rem; -} - -static inline void -tcache_dalloc(tcache_t *tcache, void *ptr) -{ - arena_t *arena; - arena_chunk_t *chunk; - arena_run_t *run; - arena_bin_t *bin; - tcache_bin_t *tbin; - size_t pageind, binind; - arena_chunk_map_t *mapelm; - - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); - arena = chunk->arena; - pageind = (((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT); - mapelm = &chunk->map[pageind]; - run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind - - ((mapelm->bits & CHUNK_MAP_PG_MASK) >> CHUNK_MAP_PG_SHIFT)) << - PAGE_SHIFT)); - assert(run->magic == ARENA_RUN_MAGIC); - bin = run->bin; - binind = ((uintptr_t)bin - (uintptr_t)&arena->bins) / - sizeof(arena_bin_t); - assert(binind < nbins); - - if (opt_junk) - memset(ptr, 0x5a, arena->bins[binind].reg_size); - - tbin = tcache->tbins[binind]; - if (tbin == NULL) { - tbin = tcache_bin_create(choose_arena()); - if (tbin == NULL) { - malloc_spin_lock(&arena->lock); - arena_dalloc_bin(arena, chunk, ptr, mapelm); - malloc_spin_unlock(&arena->lock); - return; - } - tcache->tbins[binind] = tbin; - } - - if (tbin->ncached == tcache_nslots) - tcache_bin_flush(tbin, binind, (tcache_nslots >> 1)); - assert(tbin->ncached < tcache_nslots); - tbin->slots[tbin->ncached] = ptr; - tbin->ncached++; - if (tbin->ncached > tbin->high_water) - tbin->high_water = tbin->ncached; - - tcache_event(tcache); -} -#endif - -static void -arena_dalloc_large(arena_t *arena, arena_chunk_t *chunk, void *ptr) -{ - - /* Large allocation. */ - malloc_spin_lock(&arena->lock); - -#ifndef MALLOC_STATS - if (opt_junk) -#endif - { - size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> - PAGE_SHIFT; - size_t size = chunk->map[pageind].bits & ~PAGE_MASK; - -#ifdef MALLOC_STATS - if (opt_junk) -#endif - memset(ptr, 0x5a, size); -#ifdef MALLOC_STATS - arena->stats.ndalloc_large++; - arena->stats.allocated_large -= size; - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns--; -#endif - } - - arena_run_dalloc(arena, (arena_run_t *)ptr, true); - malloc_spin_unlock(&arena->lock); -} - -static inline void -arena_dalloc(arena_t *arena, arena_chunk_t *chunk, void *ptr) -{ - size_t pageind; - arena_chunk_map_t *mapelm; - - assert(arena != NULL); - assert(arena->magic == ARENA_MAGIC); - assert(chunk->arena == arena); - assert(ptr != NULL); - assert(CHUNK_ADDR2BASE(ptr) != ptr); - - pageind = (((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT); - mapelm = &chunk->map[pageind]; - assert((mapelm->bits & CHUNK_MAP_ALLOCATED) != 0); - if ((mapelm->bits & CHUNK_MAP_LARGE) == 0) { - /* Small allocation. */ -#ifdef MALLOC_TCACHE - if (__isthreaded && tcache_nslots) { - tcache_t *tcache = tcache_tls; - if ((uintptr_t)tcache > (uintptr_t)1) - tcache_dalloc(tcache, ptr); - else { - arena_dalloc_hard(arena, chunk, ptr, mapelm, - tcache); - } - } else { -#endif - malloc_spin_lock(&arena->lock); - arena_dalloc_bin(arena, chunk, ptr, mapelm); - malloc_spin_unlock(&arena->lock); -#ifdef MALLOC_TCACHE - } -#endif - } else - arena_dalloc_large(arena, chunk, ptr); -} - -#ifdef MALLOC_TCACHE -static void -arena_dalloc_hard(arena_t *arena, arena_chunk_t *chunk, void *ptr, - arena_chunk_map_t *mapelm, tcache_t *tcache) -{ - - if (tcache == NULL) { - tcache = tcache_create(arena); - if (tcache == NULL) { - malloc_spin_lock(&arena->lock); - arena_dalloc_bin(arena, chunk, ptr, mapelm); - malloc_spin_unlock(&arena->lock); - } else - tcache_dalloc(tcache, ptr); - } else { - /* This thread is currently exiting, so directly deallocate. */ - assert(tcache == (void *)(uintptr_t)1); - malloc_spin_lock(&arena->lock); - arena_dalloc_bin(arena, chunk, ptr, mapelm); - malloc_spin_unlock(&arena->lock); - } -} -#endif - -static inline void -idalloc(void *ptr) -{ - arena_chunk_t *chunk; - - assert(ptr != NULL); - - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); - if (chunk != ptr) - arena_dalloc(chunk->arena, chunk, ptr); - else - huge_dalloc(ptr); -} - -static void -arena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk, void *ptr, - size_t size, size_t oldsize) -{ - - assert(size < oldsize); - - /* - * Shrink the run, and make trailing pages available for other - * allocations. - */ - malloc_spin_lock(&arena->lock); - arena_run_trim_tail(arena, chunk, (arena_run_t *)ptr, oldsize, size, - true); -#ifdef MALLOC_STATS - arena->stats.ndalloc_large++; - arena->stats.allocated_large -= oldsize; - arena->stats.lstats[(oldsize >> PAGE_SHIFT) - 1].curruns--; - - arena->stats.nmalloc_large++; - arena->stats.allocated_large += size; - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].nrequests++; - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns++; - if (arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns > - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns) { - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns = - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns; - } -#endif - malloc_spin_unlock(&arena->lock); -} - -static bool -arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, void *ptr, - size_t size, size_t oldsize) -{ - size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT; - size_t npages = oldsize >> PAGE_SHIFT; - - assert(oldsize == (chunk->map[pageind].bits & ~PAGE_MASK)); - - /* Try to extend the run. */ - assert(size > oldsize); - malloc_spin_lock(&arena->lock); - if (pageind + npages < chunk_npages && (chunk->map[pageind+npages].bits - & CHUNK_MAP_ALLOCATED) == 0 && (chunk->map[pageind+npages].bits & - ~PAGE_MASK) >= size - oldsize) { - /* - * The next run is available and sufficiently large. Split the - * following run, then merge the first part with the existing - * allocation. - */ - arena_run_split(arena, (arena_run_t *)((uintptr_t)chunk + - ((pageind+npages) << PAGE_SHIFT)), size - oldsize, true, - false); - - chunk->map[pageind].bits = size | CHUNK_MAP_LARGE | - CHUNK_MAP_ALLOCATED; - chunk->map[pageind+npages].bits = CHUNK_MAP_LARGE | - CHUNK_MAP_ALLOCATED; - -#ifdef MALLOC_STATS - arena->stats.ndalloc_large++; - arena->stats.allocated_large -= oldsize; - arena->stats.lstats[(oldsize >> PAGE_SHIFT) - 1].curruns--; - - arena->stats.nmalloc_large++; - arena->stats.allocated_large += size; - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].nrequests++; - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns++; - if (arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns > - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns) { - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns = - arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns; - } -#endif - malloc_spin_unlock(&arena->lock); - return (false); - } - malloc_spin_unlock(&arena->lock); - - return (true); -} - -/* - * Try to resize a large allocation, in order to avoid copying. This will - * always fail if growing an object, and the following run is already in use. - */ -static bool -arena_ralloc_large(void *ptr, size_t size, size_t oldsize) -{ - size_t psize; - - psize = PAGE_CEILING(size); - if (psize == oldsize) { - /* Same size class. */ - if (opt_junk && size < oldsize) { - memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize - - size); - } - return (false); - } else { - arena_chunk_t *chunk; - arena_t *arena; - - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); - arena = chunk->arena; - assert(arena->magic == ARENA_MAGIC); - - if (psize < oldsize) { - /* Fill before shrinking in order avoid a race. */ - if (opt_junk) { - memset((void *)((uintptr_t)ptr + size), 0x5a, - oldsize - size); - } - arena_ralloc_large_shrink(arena, chunk, ptr, psize, - oldsize); - return (false); - } else { - bool ret = arena_ralloc_large_grow(arena, chunk, ptr, - psize, oldsize); - if (ret == false && opt_zero) { - memset((void *)((uintptr_t)ptr + oldsize), 0, - size - oldsize); - } - return (ret); - } - } -} - -static void * -arena_ralloc(void *ptr, size_t size, size_t oldsize) -{ - void *ret; - size_t copysize; - - /* - * Try to avoid moving the allocation. - * - * posix_memalign() can cause allocation of "large" objects that are - * smaller than bin_maxclass (in order to meet alignment requirements). - * Therefore, do not assume that (oldsize <= bin_maxclass) indicates - * ptr refers to a bin-allocated object. - */ - if (oldsize <= arena_maxclass) { - if (arena_is_large(ptr) == false ) { - if (size <= small_maxclass) { - if (oldsize <= small_maxclass && - small_size2bin[size] == - small_size2bin[oldsize]) - goto IN_PLACE; - } else if (size <= bin_maxclass) { - if (small_maxclass < oldsize && oldsize <= - bin_maxclass && MEDIUM_CEILING(size) == - MEDIUM_CEILING(oldsize)) - goto IN_PLACE; - } - } else { - assert(size <= arena_maxclass); - if (size > bin_maxclass) { - if (arena_ralloc_large(ptr, size, oldsize) == - false) - return (ptr); - } - } - } - - /* Try to avoid moving the allocation. */ - if (size <= small_maxclass) { - if (oldsize <= small_maxclass && small_size2bin[size] == - small_size2bin[oldsize]) - goto IN_PLACE; - } else if (size <= bin_maxclass) { - if (small_maxclass < oldsize && oldsize <= bin_maxclass && - MEDIUM_CEILING(size) == MEDIUM_CEILING(oldsize)) - goto IN_PLACE; - } else { - if (bin_maxclass < oldsize && oldsize <= arena_maxclass) { - assert(size > bin_maxclass); - if (arena_ralloc_large(ptr, size, oldsize) == false) - return (ptr); - } - } - - /* - * If we get here, then size and oldsize are different enough that we - * need to move the object. In that case, fall back to allocating new - * space and copying. - */ - ret = arena_malloc(size, false); - if (ret == NULL) - return (NULL); - - /* Junk/zero-filling were already done by arena_malloc(). */ - copysize = (size < oldsize) ? size : oldsize; - memcpy(ret, ptr, copysize); - idalloc(ptr); - return (ret); -IN_PLACE: - if (opt_junk && size < oldsize) - memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize - size); - else if (opt_zero && size > oldsize) - memset((void *)((uintptr_t)ptr + oldsize), 0, size - oldsize); - return (ptr); -} - -static inline void * -iralloc(void *ptr, size_t size) -{ - size_t oldsize; - - assert(ptr != NULL); - assert(size != 0); - - oldsize = isalloc(ptr); - - if (size <= arena_maxclass) - return (arena_ralloc(ptr, size, oldsize)); - else - return (huge_ralloc(ptr, size, oldsize)); -} - -static bool -arena_new(arena_t *arena, unsigned ind) -{ - unsigned i; - arena_bin_t *bin; - size_t prev_run_size; - - if (malloc_spin_init(&arena->lock)) - return (true); - -#ifdef MALLOC_STATS - memset(&arena->stats, 0, sizeof(arena_stats_t)); - arena->stats.lstats = (malloc_large_stats_t *)base_alloc( - sizeof(malloc_large_stats_t) * ((chunksize - PAGE_SIZE) >> - PAGE_SHIFT)); - if (arena->stats.lstats == NULL) - return (true); - memset(arena->stats.lstats, 0, sizeof(malloc_large_stats_t) * - ((chunksize - PAGE_SIZE) >> PAGE_SHIFT)); -# ifdef MALLOC_TCACHE - ql_new(&arena->tcache_ql); -# endif -#endif - - /* Initialize chunks. */ - arena_chunk_tree_dirty_new(&arena->chunks_dirty); - arena->spare = NULL; - - arena->nactive = 0; - arena->ndirty = 0; - - arena_avail_tree_new(&arena->runs_avail); - - /* Initialize bins. */ - prev_run_size = PAGE_SIZE; - - i = 0; -#ifdef MALLOC_TINY - /* (2^n)-spaced tiny bins. */ - for (; i < ntbins; i++) { - bin = &arena->bins[i]; - bin->runcur = NULL; - arena_run_tree_new(&bin->runs); - - bin->reg_size = (1U << (LG_TINY_MIN + i)); - - prev_run_size = arena_bin_run_size_calc(bin, prev_run_size); - -#ifdef MALLOC_STATS - memset(&bin->stats, 0, sizeof(malloc_bin_stats_t)); -#endif - } -#endif - - /* Quantum-spaced bins. */ - for (; i < ntbins + nqbins; i++) { - bin = &arena->bins[i]; - bin->runcur = NULL; - arena_run_tree_new(&bin->runs); - - bin->reg_size = (i - ntbins + 1) << LG_QUANTUM; - - prev_run_size = arena_bin_run_size_calc(bin, prev_run_size); - -#ifdef MALLOC_STATS - memset(&bin->stats, 0, sizeof(malloc_bin_stats_t)); -#endif - } - - /* Cacheline-spaced bins. */ - for (; i < ntbins + nqbins + ncbins; i++) { - bin = &arena->bins[i]; - bin->runcur = NULL; - arena_run_tree_new(&bin->runs); - - bin->reg_size = cspace_min + ((i - (ntbins + nqbins)) << - LG_CACHELINE); - - prev_run_size = arena_bin_run_size_calc(bin, prev_run_size); - -#ifdef MALLOC_STATS - memset(&bin->stats, 0, sizeof(malloc_bin_stats_t)); -#endif - } - - /* Subpage-spaced bins. */ - for (; i < ntbins + nqbins + ncbins + nsbins; i++) { - bin = &arena->bins[i]; - bin->runcur = NULL; - arena_run_tree_new(&bin->runs); - - bin->reg_size = sspace_min + ((i - (ntbins + nqbins + ncbins)) - << LG_SUBPAGE); - - prev_run_size = arena_bin_run_size_calc(bin, prev_run_size); - -#ifdef MALLOC_STATS - memset(&bin->stats, 0, sizeof(malloc_bin_stats_t)); -#endif - } - - /* Medium bins. */ - for (; i < nbins; i++) { - bin = &arena->bins[i]; - bin->runcur = NULL; - arena_run_tree_new(&bin->runs); - - bin->reg_size = medium_min + ((i - (ntbins + nqbins + ncbins + - nsbins)) << lg_mspace); - - prev_run_size = arena_bin_run_size_calc(bin, prev_run_size); - -#ifdef MALLOC_STATS - memset(&bin->stats, 0, sizeof(malloc_bin_stats_t)); -#endif - } - -#ifdef MALLOC_DEBUG - arena->magic = ARENA_MAGIC; -#endif - - return (false); -} - -/* Create a new arena and insert it into the arenas array at index ind. */ -static arena_t * -arenas_extend(unsigned ind) -{ - arena_t *ret; - - /* Allocate enough space for trailing bins. */ - ret = (arena_t *)base_alloc(sizeof(arena_t) - + (sizeof(arena_bin_t) * (nbins - 1))); - if (ret != NULL && arena_new(ret, ind) == false) { - arenas[ind] = ret; - return (ret); - } - /* Only reached if there is an OOM error. */ - - /* - * OOM here is quite inconvenient to propagate, since dealing with it - * would require a check for failure in the fast path. Instead, punt - * by using arenas[0]. In practice, this is an extremely unlikely - * failure. - */ - _malloc_message(_getprogname(), - ": (malloc) Error initializing arena\n", "", ""); - if (opt_abort) - abort(); - - return (arenas[0]); -} - -#ifdef MALLOC_TCACHE -static tcache_bin_t * -tcache_bin_create(arena_t *arena) -{ - tcache_bin_t *ret; - size_t tsize; - - tsize = sizeof(tcache_bin_t) + (sizeof(void *) * (tcache_nslots - 1)); - if (tsize <= small_maxclass) - ret = (tcache_bin_t *)arena_malloc_small(arena, tsize, false); - else if (tsize <= bin_maxclass) - ret = (tcache_bin_t *)arena_malloc_medium(arena, tsize, false); - else - ret = (tcache_bin_t *)imalloc(tsize); - if (ret == NULL) - return (NULL); -#ifdef MALLOC_STATS - memset(&ret->tstats, 0, sizeof(tcache_bin_stats_t)); -#endif - ret->low_water = 0; - ret->high_water = 0; - ret->ncached = 0; - - return (ret); -} - -static void -tcache_bin_destroy(tcache_t *tcache, tcache_bin_t *tbin, unsigned binind) -{ - arena_t *arena; - arena_chunk_t *chunk; - size_t pageind, tsize; - arena_chunk_map_t *mapelm; - - chunk = CHUNK_ADDR2BASE(tbin); - arena = chunk->arena; - pageind = (((uintptr_t)tbin - (uintptr_t)chunk) >> PAGE_SHIFT); - mapelm = &chunk->map[pageind]; - -#ifdef MALLOC_STATS - if (tbin->tstats.nrequests != 0) { - arena_t *arena = tcache->arena; - arena_bin_t *bin = &arena->bins[binind]; - malloc_spin_lock(&arena->lock); - bin->stats.nrequests += tbin->tstats.nrequests; - if (bin->reg_size <= small_maxclass) - arena->stats.nmalloc_small += tbin->tstats.nrequests; - else - arena->stats.nmalloc_medium += tbin->tstats.nrequests; - malloc_spin_unlock(&arena->lock); - } -#endif - - assert(tbin->ncached == 0); - tsize = sizeof(tcache_bin_t) + (sizeof(void *) * (tcache_nslots - 1)); - if (tsize <= bin_maxclass) { - malloc_spin_lock(&arena->lock); - arena_dalloc_bin(arena, chunk, tbin, mapelm); - malloc_spin_unlock(&arena->lock); - } else - idalloc(tbin); -} - -#ifdef MALLOC_STATS -static void -tcache_stats_merge(tcache_t *tcache, arena_t *arena) -{ - unsigned i; - - /* Merge and reset tcache stats. */ - for (i = 0; i < mbin0; i++) { - arena_bin_t *bin = &arena->bins[i]; - tcache_bin_t *tbin = tcache->tbins[i]; - if (tbin != NULL) { - bin->stats.nrequests += tbin->tstats.nrequests; - arena->stats.nmalloc_small += tbin->tstats.nrequests; - tbin->tstats.nrequests = 0; - } - } - for (; i < nbins; i++) { - arena_bin_t *bin = &arena->bins[i]; - tcache_bin_t *tbin = tcache->tbins[i]; - if (tbin != NULL) { - bin->stats.nrequests += tbin->tstats.nrequests; - arena->stats.nmalloc_medium += tbin->tstats.nrequests; - tbin->tstats.nrequests = 0; - } - } -} -#endif - -static tcache_t * -tcache_create(arena_t *arena) -{ - tcache_t *tcache; - - if (sizeof(tcache_t) + (sizeof(tcache_bin_t *) * (nbins - 1)) <= - small_maxclass) { - tcache = (tcache_t *)arena_malloc_small(arena, sizeof(tcache_t) - + (sizeof(tcache_bin_t *) * (nbins - 1)), true); - } else if (sizeof(tcache_t) + (sizeof(tcache_bin_t *) * (nbins - 1)) <= - bin_maxclass) { - tcache = (tcache_t *)arena_malloc_medium(arena, sizeof(tcache_t) - + (sizeof(tcache_bin_t *) * (nbins - 1)), true); - } else { - tcache = (tcache_t *)icalloc(sizeof(tcache_t) + - (sizeof(tcache_bin_t *) * (nbins - 1))); - } - - if (tcache == NULL) - return (NULL); - -#ifdef MALLOC_STATS - /* Link into list of extant tcaches. */ - malloc_spin_lock(&arena->lock); - ql_elm_new(tcache, link); - ql_tail_insert(&arena->tcache_ql, tcache, link); - malloc_spin_unlock(&arena->lock); -#endif - - tcache->arena = arena; - - tcache_tls = tcache; - - return (tcache); -} - -static void -tcache_destroy(tcache_t *tcache) -{ - unsigned i; - -#ifdef MALLOC_STATS - /* Unlink from list of extant tcaches. */ - malloc_spin_lock(&tcache->arena->lock); - ql_remove(&tcache->arena->tcache_ql, tcache, link); - tcache_stats_merge(tcache, tcache->arena); - malloc_spin_unlock(&tcache->arena->lock); -#endif - - for (i = 0; i < nbins; i++) { - tcache_bin_t *tbin = tcache->tbins[i]; - if (tbin != NULL) { - tcache_bin_flush(tbin, i, 0); - tcache_bin_destroy(tcache, tbin, i); - } - } - - if (arena_salloc(tcache) <= bin_maxclass) { - arena_chunk_t *chunk = CHUNK_ADDR2BASE(tcache); - arena_t *arena = chunk->arena; - size_t pageind = (((uintptr_t)tcache - (uintptr_t)chunk) >> - PAGE_SHIFT); - arena_chunk_map_t *mapelm = &chunk->map[pageind]; - - malloc_spin_lock(&arena->lock); - arena_dalloc_bin(arena, chunk, tcache, mapelm); - malloc_spin_unlock(&arena->lock); - } else - idalloc(tcache); -} -#endif - -/* - * End arena. - */ -/******************************************************************************/ -/* - * Begin general internal functions. - */ - -static void * -huge_malloc(size_t size, bool zero) -{ - void *ret; - size_t csize; - extent_node_t *node; - - /* Allocate one or more contiguous chunks for this request. */ - - csize = CHUNK_CEILING(size); - if (csize == 0) { - /* size is large enough to cause size_t wrap-around. */ - return (NULL); - } - - /* Allocate an extent node with which to track the chunk. */ - node = base_node_alloc(); - if (node == NULL) - return (NULL); - - ret = chunk_alloc(csize, &zero); - if (ret == NULL) { - base_node_dealloc(node); - return (NULL); - } - - /* Insert node into huge. */ - node->addr = ret; - node->size = csize; - - malloc_mutex_lock(&huge_mtx); - extent_tree_ad_insert(&huge, node); -#ifdef MALLOC_STATS - huge_nmalloc++; - huge_allocated += csize; -#endif - malloc_mutex_unlock(&huge_mtx); - - if (zero == false) { - if (opt_junk) - memset(ret, 0xa5, csize); - else if (opt_zero) - memset(ret, 0, csize); - } - - return (ret); -} - -/* Only handles large allocations that require more than chunk alignment. */ -static void * -huge_palloc(size_t alignment, size_t size) -{ - void *ret; - size_t alloc_size, chunk_size, offset; - extent_node_t *node; - bool zero; - - /* - * This allocation requires alignment that is even larger than chunk - * alignment. This means that huge_malloc() isn't good enough. - * - * Allocate almost twice as many chunks as are demanded by the size or - * alignment, in order to assure the alignment can be achieved, then - * unmap leading and trailing chunks. - */ - assert(alignment >= chunksize); - - chunk_size = CHUNK_CEILING(size); - - if (size >= alignment) - alloc_size = chunk_size + alignment - chunksize; - else - alloc_size = (alignment << 1) - chunksize; - - /* Allocate an extent node with which to track the chunk. */ - node = base_node_alloc(); - if (node == NULL) - return (NULL); - - zero = false; - ret = chunk_alloc(alloc_size, &zero); - if (ret == NULL) { - base_node_dealloc(node); - return (NULL); - } - - offset = (uintptr_t)ret & (alignment - 1); - assert((offset & chunksize_mask) == 0); - assert(offset < alloc_size); - if (offset == 0) { - /* Trim trailing space. */ - chunk_dealloc((void *)((uintptr_t)ret + chunk_size), alloc_size - - chunk_size); - } else { - size_t trailsize; - - /* Trim leading space. */ - chunk_dealloc(ret, alignment - offset); - - ret = (void *)((uintptr_t)ret + (alignment - offset)); - - trailsize = alloc_size - (alignment - offset) - chunk_size; - if (trailsize != 0) { - /* Trim trailing space. */ - assert(trailsize < alloc_size); - chunk_dealloc((void *)((uintptr_t)ret + chunk_size), - trailsize); - } - } - - /* Insert node into huge. */ - node->addr = ret; - node->size = chunk_size; - - malloc_mutex_lock(&huge_mtx); - extent_tree_ad_insert(&huge, node); -#ifdef MALLOC_STATS - huge_nmalloc++; - huge_allocated += chunk_size; -#endif - malloc_mutex_unlock(&huge_mtx); - - if (opt_junk) - memset(ret, 0xa5, chunk_size); - else if (opt_zero) - memset(ret, 0, chunk_size); - - return (ret); -} - -static void * -huge_ralloc(void *ptr, size_t size, size_t oldsize) -{ - void *ret; - size_t copysize; - - /* Avoid moving the allocation if the size class would not change. */ - if (oldsize > arena_maxclass && - CHUNK_CEILING(size) == CHUNK_CEILING(oldsize)) { - if (opt_junk && size < oldsize) { - memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize - - size); - } else if (opt_zero && size > oldsize) { - memset((void *)((uintptr_t)ptr + oldsize), 0, size - - oldsize); - } - return (ptr); - } - - /* - * If we get here, then size and oldsize are different enough that we - * need to use a different size class. In that case, fall back to - * allocating new space and copying. - */ - ret = huge_malloc(size, false); - if (ret == NULL) - return (NULL); - - copysize = (size < oldsize) ? size : oldsize; - memcpy(ret, ptr, copysize); - idalloc(ptr); - return (ret); -} - -static void -huge_dalloc(void *ptr) -{ - extent_node_t *node, key; - - malloc_mutex_lock(&huge_mtx); - - /* Extract from tree of huge allocations. */ - key.addr = ptr; - node = extent_tree_ad_search(&huge, &key); - assert(node != NULL); - assert(node->addr == ptr); - extent_tree_ad_remove(&huge, node); - -#ifdef MALLOC_STATS - huge_ndalloc++; - huge_allocated -= node->size; -#endif - - malloc_mutex_unlock(&huge_mtx); - - /* Unmap chunk. */ -#ifdef MALLOC_DSS - if (opt_dss && opt_junk) - memset(node->addr, 0x5a, node->size); -#endif - chunk_dealloc(node->addr, node->size); - - base_node_dealloc(node); -} - -static void -malloc_stats_print(void) -{ - char s[UMAX2S_BUFSIZE]; - - _malloc_message("___ Begin malloc statistics ___\n", "", "", ""); - _malloc_message("Assertions ", -#ifdef NDEBUG - "disabled", -#else - "enabled", -#endif - "\n", ""); - _malloc_message("Boolean MALLOC_OPTIONS: ", opt_abort ? "A" : "a", "", ""); -#ifdef MALLOC_DSS - _malloc_message(opt_dss ? "D" : "d", "", "", ""); -#endif - _malloc_message(opt_junk ? "J" : "j", "", "", ""); -#ifdef MALLOC_DSS - _malloc_message(opt_mmap ? "M" : "m", "", "", ""); -#endif - _malloc_message("P", "", "", ""); - _malloc_message(opt_utrace ? "U" : "u", "", "", ""); - _malloc_message(opt_sysv ? "V" : "v", "", "", ""); - _malloc_message(opt_xmalloc ? "X" : "x", "", "", ""); - _malloc_message(opt_zero ? "Z" : "z", "", "", ""); - _malloc_message("\n", "", "", ""); - - _malloc_message("CPUs: ", umax2s(ncpus, 10, s), "\n", ""); - _malloc_message("Max arenas: ", umax2s(narenas, 10, s), "\n", ""); - _malloc_message("Pointer size: ", umax2s(sizeof(void *), 10, s), "\n", ""); - _malloc_message("Quantum size: ", umax2s(QUANTUM, 10, s), "\n", ""); - _malloc_message("Cacheline size (assumed): ", - umax2s(CACHELINE, 10, s), "\n", ""); - _malloc_message("Subpage spacing: ", umax2s(SUBPAGE, 10, s), "\n", ""); - _malloc_message("Medium spacing: ", umax2s((1U << lg_mspace), 10, s), "\n", - ""); -#ifdef MALLOC_TINY - _malloc_message("Tiny 2^n-spaced sizes: [", umax2s((1U << LG_TINY_MIN), 10, - s), "..", ""); - _malloc_message(umax2s((qspace_min >> 1), 10, s), "]\n", "", ""); -#endif - _malloc_message("Quantum-spaced sizes: [", umax2s(qspace_min, 10, s), "..", - ""); - _malloc_message(umax2s(qspace_max, 10, s), "]\n", "", ""); - _malloc_message("Cacheline-spaced sizes: [", - umax2s(cspace_min, 10, s), "..", ""); - _malloc_message(umax2s(cspace_max, 10, s), "]\n", "", ""); - _malloc_message("Subpage-spaced sizes: [", umax2s(sspace_min, 10, s), "..", - ""); - _malloc_message(umax2s(sspace_max, 10, s), "]\n", "", ""); - _malloc_message("Medium sizes: [", umax2s(medium_min, 10, s), "..", ""); - _malloc_message(umax2s(medium_max, 10, s), "]\n", "", ""); - if (opt_lg_dirty_mult >= 0) { - _malloc_message("Min active:dirty page ratio per arena: ", - umax2s((1U << opt_lg_dirty_mult), 10, s), ":1\n", ""); - } else { - _malloc_message("Min active:dirty page ratio per arena: N/A\n", "", - "", ""); - } -#ifdef MALLOC_TCACHE - _malloc_message("Thread cache slots per size class: ", - tcache_nslots ? umax2s(tcache_nslots, 10, s) : "N/A", "\n", ""); - _malloc_message("Thread cache GC sweep interval: ", - (tcache_nslots && tcache_gc_incr > 0) ? - umax2s((1U << opt_lg_tcache_gc_sweep), 10, s) : "N/A", "", ""); - _malloc_message(" (increment interval: ", - (tcache_nslots && tcache_gc_incr > 0) ? umax2s(tcache_gc_incr, 10, s) - : "N/A", ")\n", ""); -#endif - _malloc_message("Chunk size: ", umax2s(chunksize, 10, s), "", ""); - _malloc_message(" (2^", umax2s(opt_lg_chunk, 10, s), ")\n", ""); - -#ifdef MALLOC_STATS - { - size_t allocated, mapped; - unsigned i; - arena_t *arena; - - /* Calculate and print allocated/mapped stats. */ - - /* arenas. */ - for (i = 0, allocated = 0; i < narenas; i++) { - if (arenas[i] != NULL) { - malloc_spin_lock(&arenas[i]->lock); - allocated += arenas[i]->stats.allocated_small; - allocated += arenas[i]->stats.allocated_large; - malloc_spin_unlock(&arenas[i]->lock); - } - } - - /* huge/base. */ - malloc_mutex_lock(&huge_mtx); - allocated += huge_allocated; - mapped = stats_chunks.curchunks * chunksize; - malloc_mutex_unlock(&huge_mtx); - - malloc_mutex_lock(&base_mtx); - mapped += base_mapped; - malloc_mutex_unlock(&base_mtx); - - malloc_printf("Allocated: %zu, mapped: %zu\n", allocated, - mapped); - - /* Print chunk stats. */ - { - chunk_stats_t chunks_stats; - - malloc_mutex_lock(&huge_mtx); - chunks_stats = stats_chunks; - malloc_mutex_unlock(&huge_mtx); - - malloc_printf("chunks: nchunks " - "highchunks curchunks\n"); - malloc_printf(" %13"PRIu64"%13zu%13zu\n", - chunks_stats.nchunks, chunks_stats.highchunks, - chunks_stats.curchunks); - } - - /* Print chunk stats. */ - malloc_printf( - "huge: nmalloc ndalloc allocated\n"); - malloc_printf(" %12"PRIu64" %12"PRIu64" %12zu\n", huge_nmalloc, - huge_ndalloc, huge_allocated); - - /* Print stats for each arena. */ - for (i = 0; i < narenas; i++) { - arena = arenas[i]; - if (arena != NULL) { - malloc_printf("\narenas[%u]:\n", i); - malloc_spin_lock(&arena->lock); - arena_stats_print(arena); - malloc_spin_unlock(&arena->lock); - } - } - } -#endif /* #ifdef MALLOC_STATS */ - _malloc_message("--- End malloc statistics ---\n", "", "", ""); -} - -#ifdef MALLOC_DEBUG -static void -small_size2bin_validate(void) -{ - size_t i, size, binind; - - assert(small_size2bin[0] == 0xffU); - i = 1; -# ifdef MALLOC_TINY - /* Tiny. */ - for (; i < (1U << LG_TINY_MIN); i++) { - size = pow2_ceil(1U << LG_TINY_MIN); - binind = ffs((int)(size >> (LG_TINY_MIN + 1))); - assert(small_size2bin[i] == binind); - } - for (; i < qspace_min; i++) { - size = pow2_ceil(i); - binind = ffs((int)(size >> (LG_TINY_MIN + 1))); - assert(small_size2bin[i] == binind); - } -# endif - /* Quantum-spaced. */ - for (; i <= qspace_max; i++) { - size = QUANTUM_CEILING(i); - binind = ntbins + (size >> LG_QUANTUM) - 1; - assert(small_size2bin[i] == binind); - } - /* Cacheline-spaced. */ - for (; i <= cspace_max; i++) { - size = CACHELINE_CEILING(i); - binind = ntbins + nqbins + ((size - cspace_min) >> - LG_CACHELINE); - assert(small_size2bin[i] == binind); - } - /* Sub-page. */ - for (; i <= sspace_max; i++) { - size = SUBPAGE_CEILING(i); - binind = ntbins + nqbins + ncbins + ((size - sspace_min) - >> LG_SUBPAGE); - assert(small_size2bin[i] == binind); - } -} -#endif - -static bool -small_size2bin_init(void) -{ - - if (opt_lg_qspace_max != LG_QSPACE_MAX_DEFAULT - || opt_lg_cspace_max != LG_CSPACE_MAX_DEFAULT - || sizeof(const_small_size2bin) != small_maxclass + 1) - return (small_size2bin_init_hard()); - - small_size2bin = const_small_size2bin; -#ifdef MALLOC_DEBUG - assert(sizeof(const_small_size2bin) == small_maxclass + 1); - small_size2bin_validate(); -#endif - return (false); -} - -static bool -small_size2bin_init_hard(void) -{ - size_t i, size, binind; - uint8_t *custom_small_size2bin; - - assert(opt_lg_qspace_max != LG_QSPACE_MAX_DEFAULT - || opt_lg_cspace_max != LG_CSPACE_MAX_DEFAULT - || sizeof(const_small_size2bin) != small_maxclass + 1); - - custom_small_size2bin = (uint8_t *)base_alloc(small_maxclass + 1); - if (custom_small_size2bin == NULL) - return (true); - - custom_small_size2bin[0] = 0xffU; - i = 1; -#ifdef MALLOC_TINY - /* Tiny. */ - for (; i < (1U << LG_TINY_MIN); i++) { - size = pow2_ceil(1U << LG_TINY_MIN); - binind = ffs((int)(size >> (LG_TINY_MIN + 1))); - custom_small_size2bin[i] = binind; - } - for (; i < qspace_min; i++) { - size = pow2_ceil(i); - binind = ffs((int)(size >> (LG_TINY_MIN + 1))); - custom_small_size2bin[i] = binind; - } -#endif - /* Quantum-spaced. */ - for (; i <= qspace_max; i++) { - size = QUANTUM_CEILING(i); - binind = ntbins + (size >> LG_QUANTUM) - 1; - custom_small_size2bin[i] = binind; - } - /* Cacheline-spaced. */ - for (; i <= cspace_max; i++) { - size = CACHELINE_CEILING(i); - binind = ntbins + nqbins + ((size - cspace_min) >> - LG_CACHELINE); - custom_small_size2bin[i] = binind; - } - /* Sub-page. */ - for (; i <= sspace_max; i++) { - size = SUBPAGE_CEILING(i); - binind = ntbins + nqbins + ncbins + ((size - sspace_min) >> - LG_SUBPAGE); - custom_small_size2bin[i] = binind; - } - - small_size2bin = custom_small_size2bin; -#ifdef MALLOC_DEBUG - small_size2bin_validate(); -#endif - return (false); -} - -static unsigned -malloc_ncpus(void) -{ - int mib[2]; - unsigned ret; - int error; - size_t len; - - error = _elf_aux_info(AT_NCPUS, &ret, sizeof(ret)); - if (error != 0 || ret == 0) { - mib[0] = CTL_HW; - mib[1] = HW_NCPU; - len = sizeof(ret); - if (sysctl(mib, 2, &ret, &len, (void *)NULL, 0) == -1) { - /* Error. */ - ret = 1; - } - } - - return (ret); -} - -/* - * FreeBSD's pthreads implementation calls malloc(3), so the malloc - * implementation has to take pains to avoid infinite recursion during - * initialization. - */ -static inline bool -malloc_init(void) -{ - - if (malloc_initialized == false) - return (malloc_init_hard()); - - return (false); -} - -static bool -malloc_init_hard(void) -{ - unsigned i; - int linklen; - char buf[PATH_MAX + 1]; - const char *opts; - - malloc_mutex_lock(&init_lock); - if (malloc_initialized) { - /* - * Another thread initialized the allocator before this one - * acquired init_lock. - */ - malloc_mutex_unlock(&init_lock); - return (false); - } - - /* Get number of CPUs. */ - ncpus = malloc_ncpus(); - - /* - * Increase the chunk size to the largest page size that is greater - * than the default chunk size and less than or equal to 4MB. - */ - { - size_t pagesizes[MAXPAGESIZES]; - int k, nsizes; - - nsizes = getpagesizes(pagesizes, MAXPAGESIZES); - for (k = 0; k < nsizes; k++) - if (pagesizes[k] <= (1LU << 22)) - while ((1LU << opt_lg_chunk) < pagesizes[k]) - opt_lg_chunk++; - } - - for (i = 0; i < 3; i++) { - unsigned j; - - /* Get runtime configuration. */ - switch (i) { - case 0: - if ((linklen = readlink("/etc/malloc.conf", buf, - sizeof(buf) - 1)) != -1) { - /* - * Use the contents of the "/etc/malloc.conf" - * symbolic link's name. - */ - buf[linklen] = '\0'; - opts = buf; - } else { - /* No configuration specified. */ - buf[0] = '\0'; - opts = buf; - } - break; - case 1: - if (issetugid() == 0 && (opts = - getenv("MALLOC_OPTIONS")) != NULL) { - /* - * Do nothing; opts is already initialized to - * the value of the MALLOC_OPTIONS environment - * variable. - */ - } else { - /* No configuration specified. */ - buf[0] = '\0'; - opts = buf; - } - break; - case 2: - if (_malloc_options != NULL) { - /* - * Use options that were compiled into the - * program. - */ - opts = _malloc_options; - } else { - /* No configuration specified. */ - buf[0] = '\0'; - opts = buf; - } - break; - default: - /* NOTREACHED */ - assert(false); - buf[0] = '\0'; - opts = buf; - } - - for (j = 0; opts[j] != '\0'; j++) { - unsigned k, nreps; - bool nseen; - - /* Parse repetition count, if any. */ - for (nreps = 0, nseen = false;; j++, nseen = true) { - switch (opts[j]) { - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - case '8': case '9': - nreps *= 10; - nreps += opts[j] - '0'; - break; - default: - goto MALLOC_OUT; - } - } -MALLOC_OUT: - if (nseen == false) - nreps = 1; - - for (k = 0; k < nreps; k++) { - switch (opts[j]) { - case 'a': - opt_abort = false; - break; - case 'A': - opt_abort = true; - break; - case 'c': - if (opt_lg_cspace_max - 1 > - opt_lg_qspace_max && - opt_lg_cspace_max > - LG_CACHELINE) - opt_lg_cspace_max--; - break; - case 'C': - if (opt_lg_cspace_max < PAGE_SHIFT - - 1) - opt_lg_cspace_max++; - break; - case 'd': -#ifdef MALLOC_DSS - opt_dss = false; -#endif - break; - case 'D': -#ifdef MALLOC_DSS - opt_dss = true; -#endif - break; - case 'e': - if (opt_lg_medium_max > PAGE_SHIFT) - opt_lg_medium_max--; - break; - case 'E': - if (opt_lg_medium_max + 1 < - opt_lg_chunk) - opt_lg_medium_max++; - break; - case 'f': - if (opt_lg_dirty_mult + 1 < - (sizeof(size_t) << 3)) - opt_lg_dirty_mult++; - break; - case 'F': - if (opt_lg_dirty_mult >= 0) - opt_lg_dirty_mult--; - break; -#ifdef MALLOC_TCACHE - case 'g': - if (opt_lg_tcache_gc_sweep >= 0) - opt_lg_tcache_gc_sweep--; - break; - case 'G': - if (opt_lg_tcache_gc_sweep + 1 < - (sizeof(size_t) << 3)) - opt_lg_tcache_gc_sweep++; - break; - case 'h': - if (opt_lg_tcache_nslots > 0) - opt_lg_tcache_nslots--; - break; - case 'H': - if (opt_lg_tcache_nslots + 1 < - (sizeof(size_t) << 3)) - opt_lg_tcache_nslots++; - break; -#endif - case 'j': - opt_junk = false; - break; - case 'J': - opt_junk = true; - break; - case 'k': - /* - * Chunks always require at least one - * header page, plus enough room to - * hold a run for the largest medium - * size class (one page more than the - * size). - */ - if ((1U << (opt_lg_chunk - 1)) >= - (2U << PAGE_SHIFT) + (1U << - opt_lg_medium_max)) - opt_lg_chunk--; - break; - case 'K': - if (opt_lg_chunk + 1 < - (sizeof(size_t) << 3)) - opt_lg_chunk++; - break; - case 'm': -#ifdef MALLOC_DSS - opt_mmap = false; -#endif - break; - case 'M': -#ifdef MALLOC_DSS - opt_mmap = true; -#endif - break; - case 'n': - opt_narenas_lshift--; - break; - case 'N': - opt_narenas_lshift++; - break; - case 'p': - opt_stats_print = false; - break; - case 'P': - opt_stats_print = true; - break; - case 'q': - if (opt_lg_qspace_max > LG_QUANTUM) - opt_lg_qspace_max--; - break; - case 'Q': - if (opt_lg_qspace_max + 1 < - opt_lg_cspace_max) - opt_lg_qspace_max++; - break; - case 'u': - opt_utrace = false; - break; - case 'U': - opt_utrace = true; - break; - case 'v': - opt_sysv = false; - break; - case 'V': - opt_sysv = true; - break; - case 'x': - opt_xmalloc = false; - break; - case 'X': - opt_xmalloc = true; - break; - case 'z': - opt_zero = false; - break; - case 'Z': - opt_zero = true; - break; - default: { - char cbuf[2]; - - cbuf[0] = opts[j]; - cbuf[1] = '\0'; - _malloc_message(_getprogname(), - ": (malloc) Unsupported character " - "in malloc options: '", cbuf, - "'\n"); - } - } - } - } - } - -#ifdef MALLOC_DSS - /* Make sure that there is some method for acquiring memory. */ - if (opt_dss == false && opt_mmap == false) - opt_mmap = true; -#endif - if (opt_stats_print) { - /* Print statistics at exit. */ - atexit(stats_print_atexit); - } - - - /* Set variables according to the value of opt_lg_[qc]space_max. */ - qspace_max = (1U << opt_lg_qspace_max); - cspace_min = CACHELINE_CEILING(qspace_max); - if (cspace_min == qspace_max) - cspace_min += CACHELINE; - cspace_max = (1U << opt_lg_cspace_max); - sspace_min = SUBPAGE_CEILING(cspace_max); - if (sspace_min == cspace_max) - sspace_min += SUBPAGE; - assert(sspace_min < PAGE_SIZE); - sspace_max = PAGE_SIZE - SUBPAGE; - medium_max = (1U << opt_lg_medium_max); - -#ifdef MALLOC_TINY - assert(LG_QUANTUM >= LG_TINY_MIN); -#endif - assert(ntbins <= LG_QUANTUM); - nqbins = qspace_max >> LG_QUANTUM; - ncbins = ((cspace_max - cspace_min) >> LG_CACHELINE) + 1; - nsbins = ((sspace_max - sspace_min) >> LG_SUBPAGE) + 1; - - /* - * Compute medium size class spacing and the number of medium size - * classes. Limit spacing to no more than pagesize, but if possible - * use the smallest spacing that does not exceed NMBINS_MAX medium size - * classes. - */ - lg_mspace = LG_SUBPAGE; - nmbins = ((medium_max - medium_min) >> lg_mspace) + 1; - while (lg_mspace < PAGE_SHIFT && nmbins > NMBINS_MAX) { - lg_mspace = lg_mspace + 1; - nmbins = ((medium_max - medium_min) >> lg_mspace) + 1; - } - mspace_mask = (1U << lg_mspace) - 1U; - - mbin0 = ntbins + nqbins + ncbins + nsbins; - nbins = mbin0 + nmbins; - /* - * The small_size2bin lookup table uses uint8_t to encode each bin - * index, so we cannot support more than 256 small size classes. This - * limit is difficult to exceed (not even possible with 16B quantum and - * 4KiB pages), and such configurations are impractical, but - * nonetheless we need to protect against this case in order to avoid - * undefined behavior. - */ - if (mbin0 > 256) { - char line_buf[UMAX2S_BUFSIZE]; - _malloc_message(_getprogname(), - ": (malloc) Too many small size classes (", - umax2s(mbin0, 10, line_buf), " > max 256)\n"); - abort(); - } - - if (small_size2bin_init()) { - malloc_mutex_unlock(&init_lock); - return (true); - } - -#ifdef MALLOC_TCACHE - if (opt_lg_tcache_nslots > 0) { - tcache_nslots = (1U << opt_lg_tcache_nslots); - - /* Compute incremental GC event threshold. */ - if (opt_lg_tcache_gc_sweep >= 0) { - tcache_gc_incr = ((1U << opt_lg_tcache_gc_sweep) / - nbins) + (((1U << opt_lg_tcache_gc_sweep) % nbins == - 0) ? 0 : 1); - } else - tcache_gc_incr = 0; - } else - tcache_nslots = 0; -#endif - - /* Set variables according to the value of opt_lg_chunk. */ - chunksize = (1LU << opt_lg_chunk); - chunksize_mask = chunksize - 1; - chunk_npages = (chunksize >> PAGE_SHIFT); - { - size_t header_size; - - /* - * Compute the header size such that it is large enough to - * contain the page map. - */ - header_size = sizeof(arena_chunk_t) + - (sizeof(arena_chunk_map_t) * (chunk_npages - 1)); - arena_chunk_header_npages = (header_size >> PAGE_SHIFT) + - ((header_size & PAGE_MASK) != 0); - } - arena_maxclass = chunksize - (arena_chunk_header_npages << - PAGE_SHIFT); - - UTRACE((void *)(intptr_t)(-1), 0, 0); - -#ifdef MALLOC_STATS - malloc_mutex_init(&chunks_mtx); - memset(&stats_chunks, 0, sizeof(chunk_stats_t)); -#endif - - /* Various sanity checks that regard configuration. */ - assert(chunksize >= PAGE_SIZE); - - /* Initialize chunks data. */ - malloc_mutex_init(&huge_mtx); - extent_tree_ad_new(&huge); -#ifdef MALLOC_DSS - malloc_mutex_init(&dss_mtx); - dss_base = sbrk(0); - dss_prev = dss_base; - dss_max = dss_base; - extent_tree_szad_new(&dss_chunks_szad); - extent_tree_ad_new(&dss_chunks_ad); -#endif -#ifdef MALLOC_STATS - huge_nmalloc = 0; - huge_ndalloc = 0; - huge_allocated = 0; -#endif - - /* Initialize base allocation data structures. */ -#ifdef MALLOC_STATS - base_mapped = 0; -#endif -#ifdef MALLOC_DSS - /* - * Allocate a base chunk here, since it doesn't actually have to be - * chunk-aligned. Doing this before allocating any other chunks allows - * the use of space that would otherwise be wasted. - */ - if (opt_dss) - base_pages_alloc(0); -#endif - base_nodes = NULL; - malloc_mutex_init(&base_mtx); - - if (ncpus > 1) { - /* - * For SMP systems, create more than one arena per CPU by - * default. - */ -#ifdef MALLOC_TCACHE - if (tcache_nslots) { - /* - * Only large object allocation/deallocation is - * guaranteed to acquire an arena mutex, so we can get - * away with fewer arenas than without thread caching. - */ - opt_narenas_lshift += 1; - } else { -#endif - /* - * All allocations must acquire an arena mutex, so use - * plenty of arenas. - */ - opt_narenas_lshift += 2; -#ifdef MALLOC_TCACHE - } -#endif - } - - /* Determine how many arenas to use. */ - narenas = ncpus; - if (opt_narenas_lshift > 0) { - if ((narenas << opt_narenas_lshift) > narenas) - narenas <<= opt_narenas_lshift; - /* - * Make sure not to exceed the limits of what base_alloc() can - * handle. - */ - if (narenas * sizeof(arena_t *) > chunksize) - narenas = chunksize / sizeof(arena_t *); - } else if (opt_narenas_lshift < 0) { - if ((narenas >> -opt_narenas_lshift) < narenas) - narenas >>= -opt_narenas_lshift; - /* Make sure there is at least one arena. */ - if (narenas == 0) - narenas = 1; - } - -#ifdef NO_TLS - if (narenas > 1) { - static const unsigned primes[] = {1, 3, 5, 7, 11, 13, 17, 19, - 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, - 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, - 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, - 223, 227, 229, 233, 239, 241, 251, 257, 263}; - unsigned nprimes, parenas; - - /* - * Pick a prime number of hash arenas that is more than narenas - * so that direct hashing of pthread_self() pointers tends to - * spread allocations evenly among the arenas. - */ - assert((narenas & 1) == 0); /* narenas must be even. */ - nprimes = (sizeof(primes) >> LG_SIZEOF_INT); - parenas = primes[nprimes - 1]; /* In case not enough primes. */ - for (i = 1; i < nprimes; i++) { - if (primes[i] > narenas) { - parenas = primes[i]; - break; - } - } - narenas = parenas; - } -#endif - -#ifndef NO_TLS - next_arena = 0; -#endif - - /* Allocate and initialize arenas. */ - arenas = (arena_t **)base_alloc(sizeof(arena_t *) * narenas); - if (arenas == NULL) { - malloc_mutex_unlock(&init_lock); - return (true); - } - /* - * Zero the array. In practice, this should always be pre-zeroed, - * since it was just mmap()ed, but let's be sure. - */ - memset(arenas, 0, sizeof(arena_t *) * narenas); - - /* - * Initialize one arena here. The rest are lazily created in - * choose_arena_hard(). - */ - arenas_extend(0); - if (arenas[0] == NULL) { - malloc_mutex_unlock(&init_lock); - return (true); - } -#ifndef NO_TLS - /* - * Assign the initial arena to the initial thread, in order to avoid - * spurious creation of an extra arena if the application switches to - * threaded mode. - */ - arenas_map = arenas[0]; -#endif - malloc_spin_init(&arenas_lock); - - malloc_initialized = true; - malloc_mutex_unlock(&init_lock); - return (false); -} - -/* - * End general internal functions. - */ -/******************************************************************************/ -/* - * Begin malloc(3)-compatible functions. - */ - -void * -malloc(size_t size) -{ - void *ret; - - if (malloc_init()) { - ret = NULL; - goto OOM; - } - - if (size == 0) { - if (opt_sysv == false) - size = 1; - else { - if (opt_xmalloc) { - _malloc_message(_getprogname(), - ": (malloc) Error in malloc(): " - "invalid size 0\n", "", ""); - abort(); - } - ret = NULL; - goto RETURN; - } - } - - ret = imalloc(size); - -OOM: - if (ret == NULL) { - if (opt_xmalloc) { - _malloc_message(_getprogname(), - ": (malloc) Error in malloc(): out of memory\n", "", - ""); - abort(); - } - errno = ENOMEM; - } - -RETURN: - UTRACE(0, size, ret); - return (ret); -} - -int -posix_memalign(void **memptr, size_t alignment, size_t size) -{ - int ret; - void *result; - - if (malloc_init()) - result = NULL; - else { - if (size == 0) { - if (opt_sysv == false) - size = 1; - else { - if (opt_xmalloc) { - _malloc_message(_getprogname(), - ": (malloc) Error in " - "posix_memalign(): invalid " - "size 0\n", "", ""); - abort(); - } - result = NULL; - *memptr = NULL; - ret = 0; - goto RETURN; - } - } - - /* Make sure that alignment is a large enough power of 2. */ - if (((alignment - 1) & alignment) != 0 - || alignment < sizeof(void *)) { - if (opt_xmalloc) { - _malloc_message(_getprogname(), - ": (malloc) Error in posix_memalign(): " - "invalid alignment\n", "", ""); - abort(); - } - result = NULL; - ret = EINVAL; - goto RETURN; - } - - result = ipalloc(alignment, size); - } - - if (result == NULL) { - if (opt_xmalloc) { - _malloc_message(_getprogname(), - ": (malloc) Error in posix_memalign(): out of memory\n", - "", ""); - abort(); - } - ret = ENOMEM; - goto RETURN; - } - - *memptr = result; - ret = 0; - -RETURN: - UTRACE(0, size, result); - return (ret); -} - -void * -calloc(size_t num, size_t size) -{ - void *ret; - size_t num_size; - - if (malloc_init()) { - num_size = 0; - ret = NULL; - goto RETURN; - } - - num_size = num * size; - if (num_size == 0) { - if ((opt_sysv == false) && ((num == 0) || (size == 0))) - num_size = 1; - else { - ret = NULL; - goto RETURN; - } - /* - * Try to avoid division here. We know that it isn't possible to - * overflow during multiplication if neither operand uses any of the - * most significant half of the bits in a size_t. - */ - } else if (((num | size) & (SIZE_T_MAX << (sizeof(size_t) << 2))) - && (num_size / size != num)) { - /* size_t overflow. */ - ret = NULL; - goto RETURN; - } - - ret = icalloc(num_size); - -RETURN: - if (ret == NULL) { - if (opt_xmalloc) { - _malloc_message(_getprogname(), - ": (malloc) Error in calloc(): out of memory\n", "", - ""); - abort(); - } - errno = ENOMEM; - } - - UTRACE(0, num_size, ret); - return (ret); -} - -void * -realloc(void *ptr, size_t size) -{ - void *ret; - - if (size == 0) { - if (opt_sysv == false) - size = 1; - else { - if (ptr != NULL) - idalloc(ptr); - ret = NULL; - goto RETURN; - } - } - - if (ptr != NULL) { - assert(malloc_initialized); - - ret = iralloc(ptr, size); - - if (ret == NULL) { - if (opt_xmalloc) { - _malloc_message(_getprogname(), - ": (malloc) Error in realloc(): out of " - "memory\n", "", ""); - abort(); - } - errno = ENOMEM; - } - } else { - if (malloc_init()) - ret = NULL; - else - ret = imalloc(size); - - if (ret == NULL) { - if (opt_xmalloc) { - _malloc_message(_getprogname(), - ": (malloc) Error in realloc(): out of " - "memory\n", "", ""); - abort(); - } - errno = ENOMEM; - } - } - -RETURN: - UTRACE(ptr, size, ret); - return (ret); -} - -void -free(void *ptr) -{ - - UTRACE(ptr, 0, 0); - if (ptr != NULL) { - assert(malloc_initialized); - - idalloc(ptr); - } -} - -/* - * End malloc(3)-compatible functions. - */ -/******************************************************************************/ -/* - * Begin non-standard functions. - */ - -size_t -malloc_usable_size(const void *ptr) -{ - - assert(ptr != NULL); - - return (isalloc(ptr)); -} - -/* - * End non-standard functions. - */ -/******************************************************************************/ -/* - * Begin library-private functions. - */ - -/* - * We provide an unpublished interface in order to receive notifications from - * the pthreads library whenever a thread exits. This allows us to clean up - * thread caches. - */ -void -_malloc_thread_cleanup(void) -{ - -#ifdef MALLOC_TCACHE - tcache_t *tcache = tcache_tls; - - if (tcache != NULL) { - assert(tcache != (void *)(uintptr_t)1); - tcache_destroy(tcache); - tcache_tls = (void *)(uintptr_t)1; - } -#endif -} - -/* - * The following functions are used by threading libraries for protection of - * malloc during fork(). These functions are only called if the program is - * running in threaded mode, so there is no need to check whether the program - * is threaded here. - */ - -void -_malloc_prefork(void) -{ - unsigned i; - - /* Acquire all mutexes in a safe order. */ - malloc_spin_lock(&arenas_lock); - for (i = 0; i < narenas; i++) { - if (arenas[i] != NULL) - malloc_spin_lock(&arenas[i]->lock); - } - - malloc_mutex_lock(&base_mtx); - - malloc_mutex_lock(&huge_mtx); - -#ifdef MALLOC_DSS - malloc_mutex_lock(&dss_mtx); -#endif -} - -void -_malloc_postfork(void) -{ - unsigned i; - - /* Release all mutexes, now that fork() has completed. */ - -#ifdef MALLOC_DSS - malloc_mutex_unlock(&dss_mtx); -#endif - - malloc_mutex_unlock(&huge_mtx); - - malloc_mutex_unlock(&base_mtx); - - for (i = 0; i < narenas; i++) { - if (arenas[i] != NULL) - malloc_spin_unlock(&arenas[i]->lock); - } - malloc_spin_unlock(&arenas_lock); -} - -/* - * End library-private functions. - */ -/******************************************************************************/ diff --git a/lib/libc/stdlib/memory.3 b/lib/libc/stdlib/memory.3 deleted file mode 100644 index 9f42fa6..0000000 --- a/lib/libc/stdlib/memory.3 +++ /dev/null @@ -1,77 +0,0 @@ -.\" Copyright (c) 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)memory.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD$ -.\" -.Dd June 4, 1993 -.Dt MEMORY 3 -.Os -.Sh NAME -.Nm malloc , -.Nm free , -.Nm realloc , -.Nm calloc , -.Nm alloca , -.Nm mmap -.Nd general memory allocation operations -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In stdlib.h -.Ft void * -.Fn malloc "size_t size" -.Ft void -.Fn free "void *ptr" -.Ft void * -.Fn realloc "void *ptr" "size_t size" -.Ft void * -.Fn calloc "size_t nelem" "size_t elsize" -.Ft void * -.Fn alloca "size_t size" -.In sys/types.h -.In sys/mman.h -.Ft void * -.Fn mmap "void * addr" "size_t len" "int prot" "int flags" "int fd" "off_t offset" -.Sh DESCRIPTION -These functions allocate and free memory for the calling process. -They are described in the -individual manual pages. -.Sh SEE ALSO -.Xr mmap 2 , -.Xr alloca 3 , -.Xr calloc 3 , -.Xr free 3 , -.Xr malloc 3 , -.Xr realloc 3 -.Sh STANDARDS -These functions, with the exception of -.Fn alloca -and -.Fn mmap -conform to -.St -isoC . diff --git a/lib/libc/stdlib/merge.c b/lib/libc/stdlib/merge.c deleted file mode 100644 index e1078e7..0000000 --- a/lib/libc/stdlib/merge.c +++ /dev/null @@ -1,351 +0,0 @@ -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Peter McIlroy. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)merge.c 8.2 (Berkeley) 2/14/94"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/* - * Hybrid exponential search/linear search merge sort with hybrid - * natural/pairwise first pass. Requires about .3% more comparisons - * for random data than LSMS with pairwise first pass alone. - * It works for objects as small as two bytes. - */ - -#define NATURAL -#define THRESHOLD 16 /* Best choice for natural merge cut-off. */ - -/* #define NATURAL to get hybrid natural merge. - * (The default is pairwise merging.) - */ - -#include <sys/types.h> - -#include <errno.h> -#include <stdlib.h> -#include <string.h> - -static void setup(u_char *, u_char *, size_t, size_t, - int (*)(const void *, const void *)); -static void insertionsort(u_char *, size_t, size_t, - int (*)(const void *, const void *)); - -#define ISIZE sizeof(int) -#define PSIZE sizeof(u_char *) -#define ICOPY_LIST(src, dst, last) \ - do \ - *(int*)dst = *(int*)src, src += ISIZE, dst += ISIZE; \ - while(src < last) -#define ICOPY_ELT(src, dst, i) \ - do \ - *(int*) dst = *(int*) src, src += ISIZE, dst += ISIZE; \ - while (i -= ISIZE) - -#define CCOPY_LIST(src, dst, last) \ - do \ - *dst++ = *src++; \ - while (src < last) -#define CCOPY_ELT(src, dst, i) \ - do \ - *dst++ = *src++; \ - while (i -= 1) - -/* - * Find the next possible pointer head. (Trickery for forcing an array - * to do double duty as a linked list when objects do not align with word - * boundaries. - */ -/* Assumption: PSIZE is a power of 2. */ -#define EVAL(p) (u_char **) \ - ((u_char *)0 + \ - (((u_char *)p + PSIZE - 1 - (u_char *) 0) & ~(PSIZE - 1))) - -/* - * Arguments are as for qsort. - */ -int -mergesort(base, nmemb, size, cmp) - void *base; - size_t nmemb; - size_t size; - int (*cmp)(const void *, const void *); -{ - size_t i; - int sense; - int big, iflag; - u_char *f1, *f2, *t, *b, *tp2, *q, *l1, *l2; - u_char *list2, *list1, *p2, *p, *last, **p1; - - if (size < PSIZE / 2) { /* Pointers must fit into 2 * size. */ - errno = EINVAL; - return (-1); - } - - if (nmemb == 0) - return (0); - - /* - * XXX - * Stupid subtraction for the Cray. - */ - iflag = 0; - if (!(size % ISIZE) && !(((char *)base - (char *)0) % ISIZE)) - iflag = 1; - - if ((list2 = malloc(nmemb * size + PSIZE)) == NULL) - return (-1); - - list1 = base; - setup(list1, list2, nmemb, size, cmp); - last = list2 + nmemb * size; - i = big = 0; - while (*EVAL(list2) != last) { - l2 = list1; - p1 = EVAL(list1); - for (tp2 = p2 = list2; p2 != last; p1 = EVAL(l2)) { - p2 = *EVAL(p2); - f1 = l2; - f2 = l1 = list1 + (p2 - list2); - if (p2 != last) - p2 = *EVAL(p2); - l2 = list1 + (p2 - list2); - while (f1 < l1 && f2 < l2) { - if ((*cmp)(f1, f2) <= 0) { - q = f2; - b = f1, t = l1; - sense = -1; - } else { - q = f1; - b = f2, t = l2; - sense = 0; - } - if (!big) { /* here i = 0 */ - while ((b += size) < t && cmp(q, b) >sense) - if (++i == 6) { - big = 1; - goto EXPONENTIAL; - } - } else { -EXPONENTIAL: for (i = size; ; i <<= 1) - if ((p = (b + i)) >= t) { - if ((p = t - size) > b && - (*cmp)(q, p) <= sense) - t = p; - else - b = p; - break; - } else if ((*cmp)(q, p) <= sense) { - t = p; - if (i == size) - big = 0; - goto FASTCASE; - } else - b = p; - while (t > b+size) { - i = (((t - b) / size) >> 1) * size; - if ((*cmp)(q, p = b + i) <= sense) - t = p; - else - b = p; - } - goto COPY; -FASTCASE: while (i > size) - if ((*cmp)(q, - p = b + (i >>= 1)) <= sense) - t = p; - else - b = p; -COPY: b = t; - } - i = size; - if (q == f1) { - if (iflag) { - ICOPY_LIST(f2, tp2, b); - ICOPY_ELT(f1, tp2, i); - } else { - CCOPY_LIST(f2, tp2, b); - CCOPY_ELT(f1, tp2, i); - } - } else { - if (iflag) { - ICOPY_LIST(f1, tp2, b); - ICOPY_ELT(f2, tp2, i); - } else { - CCOPY_LIST(f1, tp2, b); - CCOPY_ELT(f2, tp2, i); - } - } - } - if (f2 < l2) { - if (iflag) - ICOPY_LIST(f2, tp2, l2); - else - CCOPY_LIST(f2, tp2, l2); - } else if (f1 < l1) { - if (iflag) - ICOPY_LIST(f1, tp2, l1); - else - CCOPY_LIST(f1, tp2, l1); - } - *p1 = l2; - } - tp2 = list1; /* swap list1, list2 */ - list1 = list2; - list2 = tp2; - last = list2 + nmemb*size; - } - if (base == list2) { - memmove(list2, list1, nmemb*size); - list2 = list1; - } - free(list2); - return (0); -} - -#define swap(a, b) { \ - s = b; \ - i = size; \ - do { \ - tmp = *a; *a++ = *s; *s++ = tmp; \ - } while (--i); \ - a -= size; \ - } -#define reverse(bot, top) { \ - s = top; \ - do { \ - i = size; \ - do { \ - tmp = *bot; *bot++ = *s; *s++ = tmp; \ - } while (--i); \ - s -= size2; \ - } while(bot < s); \ -} - -/* - * Optional hybrid natural/pairwise first pass. Eats up list1 in runs of - * increasing order, list2 in a corresponding linked list. Checks for runs - * when THRESHOLD/2 pairs compare with same sense. (Only used when NATURAL - * is defined. Otherwise simple pairwise merging is used.) - */ -void -setup(list1, list2, n, size, cmp) - size_t n, size; - int (*cmp)(const void *, const void *); - u_char *list1, *list2; -{ - int i, length, size2, tmp, sense; - u_char *f1, *f2, *s, *l2, *last, *p2; - - size2 = size*2; - if (n <= 5) { - insertionsort(list1, n, size, cmp); - *EVAL(list2) = (u_char*) list2 + n*size; - return; - } - /* - * Avoid running pointers out of bounds; limit n to evens - * for simplicity. - */ - i = 4 + (n & 1); - insertionsort(list1 + (n - i) * size, i, size, cmp); - last = list1 + size * (n - i); - *EVAL(list2 + (last - list1)) = list2 + n * size; - -#ifdef NATURAL - p2 = list2; - f1 = list1; - sense = (cmp(f1, f1 + size) > 0); - for (; f1 < last; sense = !sense) { - length = 2; - /* Find pairs with same sense. */ - for (f2 = f1 + size2; f2 < last; f2 += size2) { - if ((cmp(f2, f2+ size) > 0) != sense) - break; - length += 2; - } - if (length < THRESHOLD) { /* Pairwise merge */ - do { - p2 = *EVAL(p2) = f1 + size2 - list1 + list2; - if (sense > 0) - swap (f1, f1 + size); - } while ((f1 += size2) < f2); - } else { /* Natural merge */ - l2 = f2; - for (f2 = f1 + size2; f2 < l2; f2 += size2) { - if ((cmp(f2-size, f2) > 0) != sense) { - p2 = *EVAL(p2) = f2 - list1 + list2; - if (sense > 0) - reverse(f1, f2-size); - f1 = f2; - } - } - if (sense > 0) - reverse (f1, f2-size); - f1 = f2; - if (f2 < last || cmp(f2 - size, f2) > 0) - p2 = *EVAL(p2) = f2 - list1 + list2; - else - p2 = *EVAL(p2) = list2 + n*size; - } - } -#else /* pairwise merge only. */ - for (f1 = list1, p2 = list2; f1 < last; f1 += size2) { - p2 = *EVAL(p2) = p2 + size2; - if (cmp (f1, f1 + size) > 0) - swap(f1, f1 + size); - } -#endif /* NATURAL */ -} - -/* - * This is to avoid out-of-bounds addresses in sorting the - * last 4 elements. - */ -static void -insertionsort(a, n, size, cmp) - u_char *a; - size_t n, size; - int (*cmp)(const void *, const void *); -{ - u_char *ai, *s, *t, *u, tmp; - int i; - - for (ai = a+size; --n >= 1; ai += size) - for (t = ai; t > a; t -= size) { - u = t - size; - if (cmp(u, t) <= 0) - break; - swap(u, t); - } -} diff --git a/lib/libc/stdlib/posix_memalign.3 b/lib/libc/stdlib/posix_memalign.3 deleted file mode 100644 index b092ced..0000000 --- a/lib/libc/stdlib/posix_memalign.3 +++ /dev/null @@ -1,96 +0,0 @@ -.\" Copyright (C) 2006 Jason Evans <jasone@FreeBSD.org>. -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice(s), this list of conditions and the following disclaimer as -.\" the first lines of this file unmodified other than the possible -.\" addition of one or more copyright notices. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice(s), this list of conditions and the following disclaimer in -.\" the documentation and/or other materials provided with the -.\" distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY -.\" EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE -.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -.\" BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -.\" OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -.\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -.\" -.\" $FreeBSD$ -.\" -.Dd January 11, 2006 -.Dt POSIX_MEMALIGN 3 -.Os -.Sh NAME -.Nm posix_memalign -.Nd aligned memory allocation -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In stdlib.h -.Ft int -.Fn posix_memalign "void **ptr" "size_t alignment" "size_t size" -.Sh DESCRIPTION -The -.Fn posix_memalign -function allocates -.Fa size -bytes of memory such that the allocation's base address is an even multiple of -.Fa alignment , -and returns the allocation in the value pointed to by -.Fa ptr . -.Pp -The requested -.Fa alignment -must be a power of 2 at least as large as -.Fn sizeof "void *" . -.Pp -Memory that is allocated via -.Fn posix_memalign -can be used as an argument in subsequent calls to -.Xr realloc 3 , -.Xr reallocf 3 , -and -.Xr free 3 . -.Sh RETURN VALUES -The -.Fn posix_memalign -function returns the value 0 if successful; otherwise it returns an error value. -.Sh ERRORS -The -.Fn posix_memalign -function will fail if: -.Bl -tag -width Er -.It Bq Er EINVAL -The -.Fa alignment -parameter is not a power of 2 at least as large as -.Fn sizeof "void *" . -.It Bq Er ENOMEM -Memory allocation error. -.El -.Sh SEE ALSO -.Xr free 3 , -.Xr malloc 3 , -.Xr realloc 3 , -.Xr reallocf 3 , -.Xr valloc 3 -.Sh STANDARDS -The -.Fn posix_memalign -function conforms to -.St -p1003.1-2001 . -.Sh HISTORY -The -.Fn posix_memalign -function first appeared in -.Fx 7.0 . diff --git a/lib/libc/stdlib/ptsname.3 b/lib/libc/stdlib/ptsname.3 deleted file mode 100644 index 48da3bd..0000000 --- a/lib/libc/stdlib/ptsname.3 +++ /dev/null @@ -1,160 +0,0 @@ -.\" -.\" Copyright (c) 2002 The FreeBSD Project, Inc. -.\" All rights reserved. -.\" -.\" This software includes code contributed to the FreeBSD Project -.\" by Ryan Younce of North Carolina State University. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the FreeBSD Project nor the names of its -.\" contributors may be used to endorse or promote products derived from -.\" this software without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT AND CONTRIBUTORS -.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -.\" PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FREEBSD PROJECT -.\" OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -.\" TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -.\" PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -.\" LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -.\" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -.\" SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -.\" -.\" $FreeBSD$ -.\" -.Dd August 20, 2008 -.Dt PTSNAME 3 -.Os -.Sh NAME -.Nm grantpt , -.Nm ptsname , -.Nm unlockpt -.Nd pseudo-terminal access functions -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In stdlib.h -.Ft int -.Fn grantpt "int fildes" -.Ft "char *" -.Fn ptsname "int fildes" -.Ft int -.Fn unlockpt "int fildes" -.Sh DESCRIPTION -The -.Fn grantpt , -.Fn ptsname , -and -.Fn unlockpt -functions allow access to pseudo-terminal devices. -These three functions accept a file descriptor that references the -master half of a pseudo-terminal pair. -This file descriptor is created with -.Xr posix_openpt 2 . -.Pp -The -.Fn grantpt -function is used to establish ownership and permissions -of the slave device counterpart to the master device -specified with -.Fa fildes . -The slave device's ownership is set to the real user ID -of the calling process, and the permissions are set to -user readable-writable and group writable. -The group owner of the slave device is also set to the -group -.Dq Li tty . -.Pp -The -.Fn ptsname -function returns the full pathname of the slave device -counterpart to the master device specified with -.Fa fildes . -This value can be used -to subsequently open the appropriate slave after -.Xr posix_openpt 2 -and -.Fn grantpt -have been called. -.Pp -The -.Fn unlockpt -function clears the lock held on the pseudo-terminal pair -for the master device specified with -.Fa fildes . -.Sh RETURN VALUES -.Rv -std grantpt unlockpt -.Pp -The -.Fn ptsname -function returns a pointer to the name -of the slave device on success; otherwise a -.Dv NULL -pointer is returned. -.Sh ERRORS -The -.Fn grantpt -and -.Fn unlockpt -functions may fail and set -.Va errno -to: -.Bl -tag -width Er -.It Bq Er EBADF -.Fa fildes -is not a valid open file descriptor. -.It Bq Er EINVAL -.Fa fildes -is not a master pseudo-terminal device. -.El -.Pp -In addition, the -.Fn grantpt -function may set -.Va errno -to: -.Bl -tag -width Er -.It Bq Er EACCES -The slave pseudo-terminal device could not be accessed. -.El -.Sh SEE ALSO -.Xr posix_openpt 2 , -.Xr pts 4 , -.Xr tty 4 -.Sh STANDARDS -The -.Fn ptsname -function conforms to -.St -p1003.1-2008 . -.Pp -This implementation of -.Fn grantpt -and -.Fn unlockpt -does not conform to -.St -p1003.1-2008 , -because it depends on -.Xr posix_openpt 2 -to create the pseudo-terminal device with proper permissions in place. -It only validates whether -.Fa fildes -is a valid pseudo-terminal master device. -Future revisions of the specification will likely allow this behaviour, -as stated by the Austin Group. -.Sh HISTORY -The -.Fn grantpt , -.Fn ptsname -and -.Fn unlockpt -functions appeared in -.Fx 5.0 . diff --git a/lib/libc/stdlib/ptsname.c b/lib/libc/stdlib/ptsname.c deleted file mode 100644 index fc3b719..0000000 --- a/lib/libc/stdlib/ptsname.c +++ /dev/null @@ -1,93 +0,0 @@ -/*- - * Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org> - * All rights reserved. - * - * Portions of this software were developed under sponsorship from Snow - * B.V., the Netherlands. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -#ifndef lint -__FBSDID("$FreeBSD$"); -#endif /* not lint */ - -#include "namespace.h" -#include <sys/param.h> -#include <sys/ioctl.h> - -#include <errno.h> -#include <paths.h> -#include <stdlib.h> -#include "un-namespace.h" - -/* - * __isptmaster(): return whether the file descriptor refers to a - * pseudo-terminal master device. - */ -static int -__isptmaster(int fildes) -{ - - if (_ioctl(fildes, TIOCPTMASTER) == 0) - return (0); - - if (errno != EBADF) - errno = EINVAL; - - return (-1); -} - -/* - * In our implementation, grantpt() and unlockpt() don't actually have - * any use, because PTY's are created on the fly and already have proper - * permissions upon creation. - * - * Just make sure `fildes' actually points to a real PTY master device. - */ -__strong_reference(__isptmaster, grantpt); -__strong_reference(__isptmaster, unlockpt); - -/* - * ptsname(): return the pathname of the slave pseudo-terminal device - * associated with the specified master. - */ -char * -ptsname(int fildes) -{ - static char pt_slave[sizeof _PATH_DEV + SPECNAMELEN] = _PATH_DEV; - char *ret = NULL; - int sverrno = errno; - - /* Make sure fildes points to a master device. */ - if (__isptmaster(fildes) != 0) - goto done; - - if (fdevname_r(fildes, pt_slave + (sizeof _PATH_DEV - 1), - sizeof pt_slave - (sizeof _PATH_DEV - 1)) != NULL) - ret = pt_slave; - -done: /* Make sure ptsname() does not overwrite errno. */ - errno = sverrno; - return (ret); -} diff --git a/lib/libc/stdlib/ql.h b/lib/libc/stdlib/ql.h deleted file mode 100644 index a1bc3ab..0000000 --- a/lib/libc/stdlib/ql.h +++ /dev/null @@ -1,122 +0,0 @@ -/****************************************************************************** - * - * Copyright (C) 2002 Jason Evans <jasone@FreeBSD.org>. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice(s), this list of conditions and the following disclaimer - * unmodified other than the allowable addition of one or more - * copyright notices. - * 2. Redistributions in binary form must reproduce the above copyright - * notice(s), this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ******************************************************************************/ - -#ifndef QL_H_ -#define QL_H_ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/* - * List definitions. - */ -#define ql_head(a_type) \ -struct { \ - a_type *qlh_first; \ -} - -#define ql_head_initializer(a_head) {NULL} - -#define ql_elm(a_type) qr(a_type) - -/* List functions. */ -#define ql_new(a_head) do { \ - (a_head)->qlh_first = NULL; \ -} while (0) - -#define ql_elm_new(a_elm, a_field) qr_new((a_elm), a_field) - -#define ql_first(a_head) ((a_head)->qlh_first) - -#define ql_last(a_head, a_field) \ - ((ql_first(a_head) != NULL) \ - ? qr_prev(ql_first(a_head), a_field) : NULL) - -#define ql_next(a_head, a_elm, a_field) \ - ((ql_last(a_head, a_field) != (a_elm)) \ - ? qr_next((a_elm), a_field) : NULL) - -#define ql_prev(a_head, a_elm, a_field) \ - ((ql_first(a_head) != (a_elm)) ? qr_prev((a_elm), a_field) \ - : NULL) - -#define ql_before_insert(a_head, a_qlelm, a_elm, a_field) do { \ - qr_before_insert((a_qlelm), (a_elm), a_field); \ - if (ql_first(a_head) == (a_qlelm)) { \ - ql_first(a_head) = (a_elm); \ - } \ -} while (0) - -#define ql_after_insert(a_qlelm, a_elm, a_field) \ - qr_after_insert((a_qlelm), (a_elm), a_field) - -#define ql_head_insert(a_head, a_elm, a_field) do { \ - if (ql_first(a_head) != NULL) { \ - qr_before_insert(ql_first(a_head), (a_elm), a_field); \ - } \ - ql_first(a_head) = (a_elm); \ -} while (0) - -#define ql_tail_insert(a_head, a_elm, a_field) do { \ - if (ql_first(a_head) != NULL) { \ - qr_before_insert(ql_first(a_head), (a_elm), a_field); \ - } \ - ql_first(a_head) = qr_next((a_elm), a_field); \ -} while (0) - -#define ql_remove(a_head, a_elm, a_field) do { \ - if (ql_first(a_head) == (a_elm)) { \ - ql_first(a_head) = qr_next(ql_first(a_head), a_field); \ - } \ - if (ql_first(a_head) != (a_elm)) { \ - qr_remove((a_elm), a_field); \ - } else { \ - ql_first(a_head) = NULL; \ - } \ -} while (0) - -#define ql_head_remove(a_head, a_type, a_field) do { \ - a_type *t = ql_first(a_head); \ - ql_remove((a_head), t, a_field); \ -} while (0) - -#define ql_tail_remove(a_head, a_type, a_field) do { \ - a_type *t = ql_last(a_head, a_field); \ - ql_remove((a_head), t, a_field); \ -} while (0) - -#define ql_foreach(a_var, a_head, a_field) \ - qr_foreach((a_var), ql_first(a_head), a_field) - -#define ql_reverse_foreach(a_var, a_head, a_field) \ - qr_reverse_foreach((a_var), ql_first(a_head), a_field) - -#endif /* QL_H_ */ diff --git a/lib/libc/stdlib/qr.h b/lib/libc/stdlib/qr.h deleted file mode 100644 index 6e02321..0000000 --- a/lib/libc/stdlib/qr.h +++ /dev/null @@ -1,106 +0,0 @@ -/****************************************************************************** - * - * Copyright (C) 2002 Jason Evans <jasone@FreeBSD.org>. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice(s), this list of conditions and the following disclaimer - * unmodified other than the allowable addition of one or more - * copyright notices. - * 2. Redistributions in binary form must reproduce the above copyright - * notice(s), this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ******************************************************************************/ - -#ifndef QR_H_ -#define QR_H_ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/* Ring definitions. */ -#define qr(a_type) \ -struct { \ - a_type *qre_next; \ - a_type *qre_prev; \ -} - -/* Ring functions. */ -#define qr_new(a_qr, a_field) do { \ - (a_qr)->a_field.qre_next = (a_qr); \ - (a_qr)->a_field.qre_prev = (a_qr); \ -} while (0) - -#define qr_next(a_qr, a_field) ((a_qr)->a_field.qre_next) - -#define qr_prev(a_qr, a_field) ((a_qr)->a_field.qre_prev) - -#define qr_before_insert(a_qrelm, a_qr, a_field) do { \ - (a_qr)->a_field.qre_prev = (a_qrelm)->a_field.qre_prev; \ - (a_qr)->a_field.qre_next = (a_qrelm); \ - (a_qr)->a_field.qre_prev->a_field.qre_next = (a_qr); \ - (a_qrelm)->a_field.qre_prev = (a_qr); \ -} while (0) - -#define qr_after_insert(a_qrelm, a_qr, a_field) \ - do \ - { \ - (a_qr)->a_field.qre_next = (a_qrelm)->a_field.qre_next; \ - (a_qr)->a_field.qre_prev = (a_qrelm); \ - (a_qr)->a_field.qre_next->a_field.qre_prev = (a_qr); \ - (a_qrelm)->a_field.qre_next = (a_qr); \ - } while (0) - -#define qr_meld(a_qr_a, a_qr_b, a_field) do { \ - void *t; \ - (a_qr_a)->a_field.qre_prev->a_field.qre_next = (a_qr_b); \ - (a_qr_b)->a_field.qre_prev->a_field.qre_next = (a_qr_a); \ - t = (a_qr_a)->a_field.qre_prev; \ - (a_qr_a)->a_field.qre_prev = (a_qr_b)->a_field.qre_prev; \ - (a_qr_b)->a_field.qre_prev = t; \ -} while (0) - -/* qr_meld() and qr_split() are functionally equivalent, so there's no need to - * have two copies of the code. */ -#define qr_split(a_qr_a, a_qr_b, a_field) \ - qr_meld((a_qr_a), (a_qr_b), a_field) - -#define qr_remove(a_qr, a_field) do { \ - (a_qr)->a_field.qre_prev->a_field.qre_next \ - = (a_qr)->a_field.qre_next; \ - (a_qr)->a_field.qre_next->a_field.qre_prev \ - = (a_qr)->a_field.qre_prev; \ - (a_qr)->a_field.qre_next = (a_qr); \ - (a_qr)->a_field.qre_prev = (a_qr); \ -} while (0) - -#define qr_foreach(var, a_qr, a_field) \ - for ((var) = (a_qr); \ - (var) != NULL; \ - (var) = (((var)->a_field.qre_next != (a_qr)) \ - ? (var)->a_field.qre_next : NULL)) - -#define qr_reverse_foreach(var, a_qr, a_field) \ - for ((var) = ((a_qr) != NULL) ? qr_prev(a_qr, a_field) : NULL; \ - (var) != NULL; \ - (var) = (((var) != (a_qr)) \ - ? (var)->a_field.qre_prev : NULL)) - -#endif /* QR_H_ */ diff --git a/lib/libc/stdlib/qsort.3 b/lib/libc/stdlib/qsort.3 deleted file mode 100644 index 0f7ef73..0000000 --- a/lib/libc/stdlib/qsort.3 +++ /dev/null @@ -1,286 +0,0 @@ -.\" Copyright (c) 1990, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the American National Standards Committee X3, on Information -.\" Processing Systems. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)qsort.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD$ -.\" -.Dd September 30, 2003 -.Dt QSORT 3 -.Os -.Sh NAME -.Nm qsort , qsort_r , heapsort , mergesort -.Nd sort functions -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In stdlib.h -.Ft void -.Fo qsort -.Fa "void *base" -.Fa "size_t nmemb" -.Fa "size_t size" -.Fa "int \*[lp]*compar\*[rp]\*[lp]const void *, const void *\*[rp]" -.Fc -.Ft void -.Fo qsort_r -.Fa "void *base" -.Fa "size_t nmemb" -.Fa "size_t size" -.Fa "void *thunk" -.Fa "int \*[lp]*compar\*[rp]\*[lp]void *, const void *, const void *\*[rp]" -.Fc -.Ft int -.Fo heapsort -.Fa "void *base" -.Fa "size_t nmemb" -.Fa "size_t size" -.Fa "int \*[lp]*compar\*[rp]\*[lp]const void *, const void *\*[rp]" -.Fc -.Ft int -.Fo mergesort -.Fa "void *base" -.Fa "size_t nmemb" -.Fa "size_t size" -.Fa "int \*[lp]*compar\*[rp]\*[lp]const void *, const void *\*[rp]" -.Fc -.Sh DESCRIPTION -The -.Fn qsort -function is a modified partition-exchange sort, or quicksort. -The -.Fn heapsort -function is a modified selection sort. -The -.Fn mergesort -function is a modified merge sort with exponential search -intended for sorting data with pre-existing order. -.Pp -The -.Fn qsort -and -.Fn heapsort -functions sort an array of -.Fa nmemb -objects, the initial member of which is pointed to by -.Fa base . -The size of each object is specified by -.Fa size . -The -.Fn mergesort -function -behaves similarly, but -.Em requires -that -.Fa size -be greater than -.Dq "sizeof(void *) / 2" . -.Pp -The contents of the array -.Fa base -are sorted in ascending order according to -a comparison function pointed to by -.Fa compar , -which requires two arguments pointing to the objects being -compared. -.Pp -The comparison function must return an integer less than, equal to, or -greater than zero if the first argument is considered to be respectively -less than, equal to, or greater than the second. -.Pp -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 -.Fn mergesort -algorithm is stable. -.Pp -The -.Fn qsort -and -.Fn qsort_r -functions are an implementation of C.A.R. -Hoare's -.Dq quicksort -algorithm, -a variant of partition-exchange sorting; in particular, see -.An D.E. Knuth Ns 's -.%T "Algorithm Q" . -.Sy Quicksort -takes O N lg N average time. -This implementation uses median selection to avoid its -O N**2 worst-case behavior. -.Pp -The -.Fn heapsort -function is an implementation of -.An "J.W.J. William" Ns 's -.Dq heapsort -algorithm, -a variant of selection sorting; in particular, see -.An "D.E. Knuth" Ns 's -.%T "Algorithm H" . -.Sy Heapsort -takes O N lg N worst-case time. -Its -.Em only -advantage over -.Fn qsort -is that it uses almost no additional memory; while -.Fn qsort -does not allocate memory, it is implemented using recursion. -.Pp -The function -.Fn mergesort -requires additional memory of size -.Fa nmemb * -.Fa size -bytes; it should be used only when space is not at a premium. -The -.Fn mergesort -function -is optimized for data with pre-existing order; its worst case -time is O N lg N; its best case is O N. -.Pp -Normally, -.Fn qsort -is faster than -.Fn mergesort -is faster than -.Fn heapsort . -Memory availability and pre-existing order in the data can make this -untrue. -.Sh RETURN VALUES -The -.Fn qsort -and -.Fn qsort_r -functions -return no value. -.Pp -.Rv -std heapsort mergesort -.Sh COMPATIBILITY -Previous versions of -.Fn qsort -did not permit the comparison routine itself to call -.Fn qsort 3 . -This is no longer true. -.Sh ERRORS -The -.Fn heapsort -and -.Fn mergesort -functions succeed unless: -.Bl -tag -width Er -.It Bq Er EINVAL -The -.Fa size -argument is zero, or, -the -.Fa size -argument to -.Fn mergesort -is less than -.Dq "sizeof(void *) / 2" . -.It Bq Er ENOMEM -The -.Fn heapsort -or -.Fn mergesort -functions -were unable to allocate memory. -.El -.Sh SEE ALSO -.Xr sort 1 , -.Xr radixsort 3 -.Rs -.%A Hoare, C.A.R. -.%D 1962 -.%T "Quicksort" -.%J "The Computer Journal" -.%V 5:1 -.%P pp. 10-15 -.Re -.Rs -.%A Williams, J.W.J -.%D 1964 -.%T "Heapsort" -.%J "Communications of the ACM" -.%V 7:1 -.%P pp. 347-348 -.Re -.Rs -.%A Knuth, D.E. -.%D 1968 -.%B "The Art of Computer Programming" -.%V Vol. 3 -.%T "Sorting and Searching" -.%P pp. 114-123, 145-149 -.Re -.Rs -.%A McIlroy, P.M. -.%T "Optimistic Sorting and Information Theoretic Complexity" -.%J "Fourth Annual ACM-SIAM Symposium on Discrete Algorithms" -.%V January 1992 -.Re -.Rs -.%A Bentley, J.L. -.%A McIlroy, M.D. -.%T "Engineering a Sort Function" -.%J "Software--Practice and Experience" -.%V Vol. 23(11) -.%P pp. 1249-1265 -.%D November\ 1993 -.Re -.Sh STANDARDS -The -.Fn qsort -function -conforms to -.St -isoC . diff --git a/lib/libc/stdlib/qsort.c b/lib/libc/stdlib/qsort.c deleted file mode 100644 index 3687b05..0000000 --- a/lib/libc/stdlib/qsort.c +++ /dev/null @@ -1,195 +0,0 @@ -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)qsort.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#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 *); -#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 - -/* - * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function". - */ -#define swapcode(TYPE, parmi, parmj, n) { \ - long i = (n) / sizeof (TYPE); \ - TYPE *pi = (TYPE *) (parmi); \ - TYPE *pj = (TYPE *) (parmj); \ - do { \ - TYPE t = *pi; \ - *pi++ = *pj; \ - *pj++ = t; \ - } while (--i > 0); \ -} - -#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \ - es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1; - -static inline void -swapfunc(a, b, n, swaptype) - char *a, *b; - int n, swaptype; -{ - if(swaptype <= 1) - swapcode(long, a, b, n) - else - swapcode(char, a, b, n) -} - -#define swap(a, b) \ - if (swaptype == 0) { \ - long t = *(long *)(a); \ - *(long *)(a) = *(long *)(b); \ - *(long *)(b) = t; \ - } else \ - swapfunc(a, b, es, swaptype) - -#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(char *a, char *b, char *c, cmp_t *cmp, void *thunk -#ifndef I_AM_QSORT_R -__unused -#endif -) -{ - 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(void *a, size_t n, size_t es, cmp_t *cmp) -#endif -{ - char *pa, *pb, *pc, *pd, *pl, *pm, *pn; - size_t d, r; - int cmp_result; - int swaptype, swap_cnt; - -loop: SWAPINIT(a, es); - swap_cnt = 0; - if (n < 7) { - for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) - for (pl = pm; - pl > (char *)a && CMP(thunk, pl - es, pl) > 0; - pl -= es) - swap(pl, pl - es); - return; - } - pm = (char *)a + (n / 2) * es; - if (n > 7) { - pl = a; - pn = (char *)a + (n - 1) * es; - if (n > 40) { - d = (n / 8) * es; - 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, thunk); - } - swap(a, pm); - pa = pb = (char *)a + es; - - pc = pd = (char *)a + (n - 1) * es; - for (;;) { - while (pb <= pc && (cmp_result = CMP(thunk, pb, a)) <= 0) { - if (cmp_result == 0) { - swap_cnt = 1; - swap(pa, pb); - pa += es; - } - pb += es; - } - while (pb <= pc && (cmp_result = CMP(thunk, pc, a)) >= 0) { - if (cmp_result == 0) { - swap_cnt = 1; - swap(pc, pd); - pd -= es; - } - pc -= es; - } - if (pb > pc) - break; - swap(pb, pc); - swap_cnt = 1; - pb += es; - pc -= es; - } - if (swap_cnt == 0) { /* Switch to insertion sort */ - for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) - for (pl = pm; - pl > (char *)a && CMP(thunk, pl - es, pl) > 0; - pl -= es) - swap(pl, pl - es); - return; - } - - pn = (char *)a + n * es; - r = min(pa - (char *)a, pb - pa); - vecswap(a, pb - r, r); - 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; - n = r / es; - goto loop; - } -/* qsort(pn - r, r / es, es, cmp);*/ -} diff --git a/lib/libc/stdlib/qsort_r.c b/lib/libc/stdlib/qsort_r.c deleted file mode 100644 index d868736..0000000 --- a/lib/libc/stdlib/qsort_r.c +++ /dev/null @@ -1,8 +0,0 @@ -/* - * This file is in the public domain. Originally written by Garrett - * A. Wollman. - * - * $FreeBSD$ - */ -#define I_AM_QSORT_R -#include "qsort.c" diff --git a/lib/libc/stdlib/radixsort.3 b/lib/libc/stdlib/radixsort.3 deleted file mode 100644 index dfa65f1..0000000 --- a/lib/libc/stdlib/radixsort.3 +++ /dev/null @@ -1,160 +0,0 @@ -.\" Copyright (c) 1990, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)radixsort.3 8.2 (Berkeley) 1/27/94 -.\" $FreeBSD$ -.\" -.Dd January 27, 1994 -.Dt RADIXSORT 3 -.Os -.Sh NAME -.Nm radixsort , sradixsort -.Nd radix sort -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In limits.h -.In stdlib.h -.Ft int -.Fn radixsort "const unsigned char **base" "int nmemb" "const unsigned char *table" "unsigned endbyte" -.Ft int -.Fn sradixsort "const unsigned char **base" "int nmemb" "const unsigned char *table" "unsigned endbyte" -.Sh DESCRIPTION -The -.Fn radixsort -and -.Fn sradixsort -functions -are implementations of radix sort. -.Pp -These functions sort an array of pointers to byte strings, the initial -member of which is referenced by -.Fa base . -The byte strings may contain any values; the end of each string -is denoted by the user-specified value -.Fa endbyte . -.Pp -Applications may specify a sort order by providing the -.Fa table -argument. -If -.Pf non- Dv NULL , -.Fa table -must reference an array of -.Dv UCHAR_MAX -+ 1 bytes which contains the sort -weight of each possible byte value. -The end-of-string byte must have a sort weight of 0 or 255 -(for sorting in reverse order). -More than one byte may have the same sort weight. -The -.Fa table -argument -is useful for applications which wish to sort different characters -equally, for example, providing a table with the same weights -for A-Z as for a-z will result in a case-insensitive sort. -If -.Fa table -is NULL, the contents of the array are sorted in ascending order -according to the -.Tn ASCII -order of the byte strings they reference and -.Fa endbyte -has a sorting weight of 0. -.Pp -The -.Fn sradixsort -function is stable, that is, if two elements compare as equal, their -order in the sorted array is unchanged. -The -.Fn sradixsort -function uses additional memory sufficient to hold -.Fa nmemb -pointers. -.Pp -The -.Fn radixsort -function is not stable, but uses no additional memory. -.Pp -These functions are variants of most-significant-byte radix sorting; in -particular, see -.An "D.E. Knuth" Ns 's -.%T "Algorithm R" -and section 5.2.5, exercise 10. -They take linear time relative to the number of bytes in the strings. -.Sh RETURN VALUES -.Rv -std radixsort -.Sh ERRORS -.Bl -tag -width Er -.It Bq Er EINVAL -The value of the -.Fa endbyte -element of -.Fa table -is not 0 or 255. -.El -.Pp -Additionally, the -.Fn sradixsort -function -may fail and set -.Va errno -for any of the errors specified for the library routine -.Xr malloc 3 . -.Sh SEE ALSO -.Xr sort 1 , -.Xr qsort 3 -.Pp -.Rs -.%A Knuth, D.E. -.%D 1968 -.%B "The Art of Computer Programming" -.%T "Sorting and Searching" -.%V Vol. 3 -.%P pp. 170-178 -.Re -.Rs -.%A Paige, R. -.%D 1987 -.%T "Three Partition Refinement Algorithms" -.%J "SIAM J. Comput." -.%V Vol. 16 -.%N No. 6 -.Re -.Rs -.%A McIlroy, P. -.%D 1993 -.%B "Engineering Radix Sort" -.%T "Computing Systems" -.%V Vol. 6:1 -.%P pp. 5-27 -.Re -.Sh HISTORY -The -.Fn radixsort -function first appeared in -.Bx 4.4 . diff --git a/lib/libc/stdlib/radixsort.c b/lib/libc/stdlib/radixsort.c deleted file mode 100644 index 82ff1bc..0000000 --- a/lib/libc/stdlib/radixsort.c +++ /dev/null @@ -1,327 +0,0 @@ -/*- - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Peter McIlroy and by Dan Bernstein at New York University, - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)radixsort.c 8.2 (Berkeley) 4/28/95"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/* - * Radixsort routines. - * - * Program r_sort_a() is unstable but uses O(logN) extra memory for a stack. - * Use radixsort(a, n, trace, endchar) for this case. - * - * For stable sorting (using N extra pointers) use sradixsort(), which calls - * r_sort_b(). - * - * For a description of this code, see D. McIlroy, P. McIlroy, K. Bostic, - * "Engineering Radix Sort". - */ - -#include <sys/types.h> -#include <stdlib.h> -#include <stddef.h> -#include <errno.h> - -typedef struct { - const u_char **sa; - int sn, si; -} stack; - -static inline void simplesort -(const u_char **, int, int, const u_char *, u_int); -static void r_sort_a(const u_char **, int, int, const u_char *, u_int); -static void r_sort_b(const u_char **, const u_char **, int, int, - const u_char *, u_int); - -#define THRESHOLD 20 /* Divert to simplesort(). */ -#define SIZE 512 /* Default stack size. */ - -#define SETUP { \ - if (tab == NULL) { \ - tr = tr0; \ - for (c = 0; c < endch; c++) \ - tr0[c] = c + 1; \ - tr0[c] = 0; \ - for (c++; c < 256; c++) \ - tr0[c] = c; \ - endch = 0; \ - } else { \ - endch = tab[endch]; \ - tr = tab; \ - if (endch != 0 && endch != 255) { \ - errno = EINVAL; \ - return (-1); \ - } \ - } \ -} - -int -radixsort(a, n, tab, endch) - const u_char **a, *tab; - int n; - u_int endch; -{ - const u_char *tr; - int c; - u_char tr0[256]; - - SETUP; - r_sort_a(a, n, 0, tr, endch); - return (0); -} - -int -sradixsort(a, n, tab, endch) - const u_char **a, *tab; - int n; - u_int endch; -{ - const u_char *tr, **ta; - int c; - u_char tr0[256]; - - SETUP; - if (n < THRESHOLD) - simplesort(a, n, 0, tr, endch); - else { - if ((ta = malloc(n * sizeof(a))) == NULL) - return (-1); - r_sort_b(a, ta, n, 0, tr, endch); - free(ta); - } - return (0); -} - -#define empty(s) (s >= sp) -#define pop(a, n, i) a = (--sp)->sa, n = sp->sn, i = sp->si -#define push(a, n, i) sp->sa = a, sp->sn = n, (sp++)->si = i -#define swap(a, b, t) t = a, a = b, b = t - -/* Unstable, in-place sort. */ -static void -r_sort_a(a, n, i, tr, endch) - const u_char **a; - int n, i; - const u_char *tr; - u_int endch; -{ - static int count[256], nc, bmin; - int c; - const u_char **ak, *r; - stack s[SIZE], *sp, *sp0, *sp1, temp; - int *cp, bigc; - const u_char **an, *t, **aj, **top[256]; - - /* Set up stack. */ - sp = s; - push(a, n, i); - while (!empty(s)) { - pop(a, n, i); - if (n < THRESHOLD) { - simplesort(a, n, i, tr, endch); - continue; - } - an = a + n; - - /* Make character histogram. */ - if (nc == 0) { - bmin = 255; /* First occupied bin, excluding eos. */ - for (ak = a; ak < an;) { - c = tr[(*ak++)[i]]; - if (++count[c] == 1 && c != endch) { - if (c < bmin) - bmin = c; - nc++; - } - } - if (sp + nc > s + SIZE) { /* Get more stack. */ - r_sort_a(a, n, i, tr, endch); - continue; - } - } - - /* - * Special case: if all strings have the same - * character at position i, move on to the next - * character. - */ - if (nc == 1 && count[bmin] == n) { - push(a, n, i+1); - nc = count[bmin] = 0; - continue; - } - - /* - * Set top[]; push incompletely sorted bins onto stack. - * top[] = pointers to last out-of-place element in bins. - * count[] = counts of elements in bins. - * Before permuting: top[c-1] + count[c] = top[c]; - * during deal: top[c] counts down to top[c-1]. - */ - sp0 = sp1 = sp; /* Stack position of biggest bin. */ - bigc = 2; /* Size of biggest bin. */ - if (endch == 0) /* Special case: set top[eos]. */ - top[0] = ak = a + count[0]; - else { - ak = a; - top[255] = an; - } - for (cp = count + bmin; nc > 0; cp++) { - while (*cp == 0) /* Find next non-empty pile. */ - cp++; - if (*cp > 1) { - if (*cp > bigc) { - bigc = *cp; - sp1 = sp; - } - push(ak, *cp, i+1); - } - top[cp-count] = ak += *cp; - nc--; - } - swap(*sp0, *sp1, temp); /* Play it safe -- biggest bin last. */ - - /* - * Permute misplacements home. Already home: everything - * before aj, and in bin[c], items from top[c] on. - * Inner loop: - * r = next element to put in place; - * ak = top[r[i]] = location to put the next element. - * aj = bottom of 1st disordered bin. - * Outer loop: - * Once the 1st disordered bin is done, ie. aj >= ak, - * aj<-aj + count[c] connects the bins in a linked list; - * reset count[c]. - */ - for (aj = a; aj < an; *aj = r, aj += count[c], count[c] = 0) - for (r = *aj; aj < (ak = --top[c = tr[r[i]]]);) - swap(*ak, r, t); - } -} - -/* Stable sort, requiring additional memory. */ -static void -r_sort_b(a, ta, n, i, tr, endch) - const u_char **a, **ta; - int n, i; - const u_char *tr; - u_int endch; -{ - static int count[256], nc, bmin; - int c; - const u_char **ak, **ai; - stack s[512], *sp, *sp0, *sp1, temp; - const u_char **top[256]; - int *cp, bigc; - - sp = s; - push(a, n, i); - while (!empty(s)) { - pop(a, n, i); - if (n < THRESHOLD) { - simplesort(a, n, i, tr, endch); - continue; - } - - if (nc == 0) { - bmin = 255; - for (ak = a + n; --ak >= a;) { - c = tr[(*ak)[i]]; - if (++count[c] == 1 && c != endch) { - if (c < bmin) - bmin = c; - nc++; - } - } - if (sp + nc > s + SIZE) { - r_sort_b(a, ta, n, i, tr, endch); - continue; - } - } - - sp0 = sp1 = sp; - bigc = 2; - if (endch == 0) { - top[0] = ak = a + count[0]; - count[0] = 0; - } else { - ak = a; - top[255] = a + n; - count[255] = 0; - } - for (cp = count + bmin; nc > 0; cp++) { - while (*cp == 0) - cp++; - if ((c = *cp) > 1) { - if (c > bigc) { - bigc = c; - sp1 = sp; - } - push(ak, c, i+1); - } - top[cp-count] = ak += c; - *cp = 0; /* Reset count[]. */ - nc--; - } - swap(*sp0, *sp1, temp); - - for (ak = ta + n, ai = a+n; ak > ta;) /* Copy to temp. */ - *--ak = *--ai; - for (ak = ta+n; --ak >= ta;) /* Deal to piles. */ - *--top[tr[(*ak)[i]]] = *ak; - } -} - -static inline void -simplesort(a, n, b, tr, endch) /* insertion sort */ - const u_char **a; - int n, b; - const u_char *tr; - u_int endch; -{ - u_char ch; - const u_char **ak, **ai, *s, *t; - - for (ak = a+1; --n >= 1; ak++) - for (ai = ak; ai > a; ai--) { - for (s = ai[0] + b, t = ai[-1] + b; - (ch = tr[*s]) != endch; s++, t++) - if (ch != tr[*t]) - break; - if (ch >= tr[*t]) - break; - swap(ai[0], ai[-1], s); - } -} diff --git a/lib/libc/stdlib/rand.3 b/lib/libc/stdlib/rand.3 deleted file mode 100644 index 3eb1a1d..0000000 --- a/lib/libc/stdlib/rand.3 +++ /dev/null @@ -1,126 +0,0 @@ -.\" Copyright (c) 1990, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the American National Standards Committee X3, on Information -.\" Processing Systems. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)rand.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD$ -.\" -.Dd October 6, 2010 -.Dt RAND 3 -.Os -.Sh NAME -.Nm rand , -.Nm srand , -.Nm sranddev , -.Nm rand_r -.Nd bad random number generator -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In stdlib.h -.Ft void -.Fn srand "unsigned seed" -.Ft void -.Fn sranddev void -.Ft int -.Fn rand void -.Ft int -.Fn rand_r "unsigned *ctx" -.Sh DESCRIPTION -.Bf -symbolic -These interfaces are obsoleted by -.Xr random 3 . -.Ef -.Pp -The -.Fn rand -function computes a sequence of pseudo-random integers in the range -of 0 to -.Dv RAND_MAX -(as defined by the header file -.In stdlib.h ) . -.Pp -The -.Fn srand -function sets its argument -.Fa seed -as the seed for a new sequence of -pseudo-random numbers to be returned by -.Fn rand . -These sequences are repeatable by calling -.Fn srand -with the same seed value. -.Pp -If no -.Fa seed -value is provided, the functions are automatically -seeded with a value of 1. -.Pp -The -.Fn sranddev -function initializes a seed using the -.Xr random 4 -random number device which returns good random numbers. -However, the -.Fn rand -function still remains unsuitable for cryptographic use. -.Pp -The -.Fn rand_r -function -provides the same functionality as -.Fn rand . -A pointer to the context value -.Fa ctx -must be supplied by the caller. -.Pp -For better generator quality, use -.Xr random 3 -or -.Xr lrand48 3 . -Applications requiring cryptographic quality randomness should use -.Xr arc4random 3 . -.Sh SEE ALSO -.Xr arc4random 3 , -.Xr lrand48 3 , -.Xr random 3 , -.Xr random 4 -.Sh STANDARDS -The -.Fn rand -and -.Fn srand -functions -conform to -.St -isoC . -.Pp -The -.Fn rand_r -function is as proposed in the POSIX.4a Draft #6 document. diff --git a/lib/libc/stdlib/rand.c b/lib/libc/stdlib/rand.c deleted file mode 100644 index 077c1ba..0000000 --- a/lib/libc/stdlib/rand.c +++ /dev/null @@ -1,168 +0,0 @@ -/*- - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Posix rand_r function added May 1999 by Wes Peters <wes@softweyr.com>. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)rand.c 8.1 (Berkeley) 6/14/93"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include "namespace.h" -#include <sys/time.h> /* for sranddev() */ -#include <sys/types.h> -#include <fcntl.h> /* for sranddev() */ -#include <stdlib.h> -#include <unistd.h> /* for sranddev() */ -#include "un-namespace.h" - -#ifdef TEST -#include <stdio.h> -#endif /* TEST */ - -static int -do_rand(unsigned long *ctx) -{ -#ifdef USE_WEAK_SEEDING -/* - * Historic implementation compatibility. - * The random sequences do not vary much with the seed, - * even with overflowing. - */ - return ((*ctx = *ctx * 1103515245 + 12345) % ((u_long)RAND_MAX + 1)); -#else /* !USE_WEAK_SEEDING */ -/* - * Compute x = (7^5 * x) mod (2^31 - 1) - * without overflowing 31 bits: - * (2^31 - 1) = 127773 * (7^5) + 2836 - * From "Random number generators: good ones are hard to find", - * Park and Miller, Communications of the ACM, vol. 31, no. 10, - * October 1988, p. 1195. - */ - long hi, lo, x; - - /* Can't be initialized with 0, so use another value. */ - if (*ctx == 0) - *ctx = 123459876; - hi = *ctx / 127773; - lo = *ctx % 127773; - x = 16807 * lo - 2836 * hi; - if (x < 0) - x += 0x7fffffff; - return ((*ctx = x) % ((u_long)RAND_MAX + 1)); -#endif /* !USE_WEAK_SEEDING */ -} - - -int -rand_r(unsigned int *ctx) -{ - u_long val = (u_long) *ctx; - int r = do_rand(&val); - - *ctx = (unsigned int) val; - return (r); -} - - -static u_long next = 1; - -int -rand() -{ - return (do_rand(&next)); -} - -void -srand(seed) -u_int seed; -{ - next = seed; -} - - -/* - * sranddev: - * - * Many programs choose the seed value in a totally predictable manner. - * This often causes problems. We seed the generator using the much more - * secure random(4) interface. - */ -void -sranddev() -{ - int fd, done; - - done = 0; - fd = _open("/dev/random", O_RDONLY, 0); - if (fd >= 0) { - if (_read(fd, (void *) &next, sizeof(next)) == sizeof(next)) - done = 1; - _close(fd); - } - - if (!done) { - struct timeval tv; - unsigned long junk; - - gettimeofday(&tv, NULL); - srand((getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec ^ junk); - } -} - - -#ifdef TEST - -main() -{ - int i; - unsigned myseed; - - printf("seeding rand with 0x19610910: \n"); - srand(0x19610910); - - printf("generating three pseudo-random numbers:\n"); - for (i = 0; i < 3; i++) - { - printf("next random number = %d\n", rand()); - } - - printf("generating the same sequence with rand_r:\n"); - myseed = 0x19610910; - for (i = 0; i < 3; i++) - { - printf("next random number = %d\n", rand_r(&myseed)); - } - - return 0; -} - -#endif /* TEST */ - diff --git a/lib/libc/stdlib/random.3 b/lib/libc/stdlib/random.3 deleted file mode 100644 index c6502bf..0000000 --- a/lib/libc/stdlib/random.3 +++ /dev/null @@ -1,196 +0,0 @@ -.\" Copyright (c) 1983, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)random.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD$ -.\" -.Dd June 4, 1993 -.Dt RANDOM 3 -.Os -.Sh NAME -.Nm random , -.Nm srandom , -.Nm srandomdev , -.Nm initstate , -.Nm setstate -.Nd better random number generator; routines for changing generators -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In stdlib.h -.Ft long -.Fn random void -.Ft void -.Fn srandom "unsigned long seed" -.Ft void -.Fn srandomdev void -.Ft char * -.Fn initstate "unsigned long seed" "char *state" "long n" -.Ft char * -.Fn setstate "char *state" -.Sh DESCRIPTION -The -.Fn random -function -uses a non-linear additive feedback random number generator employing a -default table of size 31 long integers to return successive pseudo-random -numbers in the range from 0 to -.if t 2\u\s731\s10\d\(mi1. -.if n (2**31)\(mi1. -The period of this random number generator is very large, approximately -.if t 16\(mu(2\u\s731\s10\d\(mi1). -.if n 16*((2**31)\(mi1). -.Pp -The -.Fn random -and -.Fn srandom -functions have (almost) the same calling sequence and initialization properties as the -.Xr rand 3 -and -.Xr srand 3 -functions. -The difference is that -.Xr rand 3 -produces a much less random sequence \(em in fact, the low dozen bits -generated by rand go through a cyclic pattern. -All the bits generated by -.Fn random -are usable. -For example, -.Sq Li random()&01 -will produce a random binary -value. -.Pp -Like -.Xr rand 3 , -.Fn random -will by default produce a sequence of numbers that can be duplicated -by calling -.Fn srandom -with -.Ql 1 -as the seed. -.Pp -The -.Fn srandomdev -routine initializes a state array using the -.Xr random 4 -random number device which returns good random numbers, -suitable for cryptographic use. -Note that this particular seeding -procedure can generate states which are impossible to reproduce by -calling -.Fn srandom -with any value, since the succeeding terms in the -state buffer are no longer derived from the LC algorithm applied to -a fixed seed. -.Pp -The -.Fn initstate -routine allows a state array, passed in as an argument, to be initialized -for future use. -The size of the state array (in bytes) is used by -.Fn initstate -to decide how sophisticated a random number generator it should use \(em the -more state, the better the random numbers will be. -(Current "optimal" values for the amount of state information are -8, 32, 64, 128, and 256 bytes; other amounts will be rounded down to -the nearest known amount. -Using less than 8 bytes will cause an error.) -The seed for the initialization (which specifies a starting point for -the random number sequence, and provides for restarting at the same -point) is also an argument. -The -.Fn initstate -function -returns a pointer to the previous state information array. -.Pp -Once a state has been initialized, the -.Fn setstate -routine provides for rapid switching between states. -The -.Fn setstate -function -returns a pointer to the previous state array; its -argument state array is used for further random number generation -until the next call to -.Fn initstate -or -.Fn setstate . -.Pp -Once a state array has been initialized, it may be restarted at a -different point either by calling -.Fn initstate -(with the desired seed, the state array, and its size) or by calling -both -.Fn setstate -(with the state array) and -.Fn srandom -(with the desired seed). -The advantage of calling both -.Fn setstate -and -.Fn srandom -is that the size of the state array does not have to be remembered after -it is initialized. -.Pp -With 256 bytes of state information, the period of the random number -generator is greater than -.if t 2\u\s769\s10\d, -.if n 2**69 -which should be sufficient for most purposes. -.Sh DIAGNOSTICS -If -.Fn initstate -is called with less than 8 bytes of state information, or if -.Fn setstate -detects that the state information has been garbled, error -messages are printed on the standard error output. -.Sh SEE ALSO -.Xr arc4random 3 , -.Xr lrand48 3 , -.Xr rand 3 , -.Xr srand 3 , -.Xr random 4 -.Sh HISTORY -These -functions appeared in -.Bx 4.2 . -.Sh AUTHORS -.An Earl T. Cohen -.Sh BUGS -About 2/3 the speed of -.Xr rand 3 . -.Pp -The historical implementation used to have a very weak seeding; the -random sequence did not vary much with the seed. -The current implementation employs a better pseudo-random number -generator for the initial state calculation. -.Pp -Applications requiring cryptographic quality randomness should use -.Xr arc4random 3 . diff --git a/lib/libc/stdlib/random.c b/lib/libc/stdlib/random.c deleted file mode 100644 index f7be4a7..0000000 --- a/lib/libc/stdlib/random.c +++ /dev/null @@ -1,502 +0,0 @@ -/* - * Copyright (c) 1983, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)random.c 8.2 (Berkeley) 5/19/95"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include "namespace.h" -#include <sys/time.h> /* for srandomdev() */ -#include <fcntl.h> /* for srandomdev() */ -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> /* for srandomdev() */ -#include "un-namespace.h" - -/* - * random.c: - * - * An improved random number generation package. In addition to the standard - * rand()/srand() like interface, this package also has a special state info - * interface. The initstate() routine is called with a seed, an array of - * bytes, and a count of how many bytes are being passed in; this array is - * then initialized to contain information for random number generation with - * that much state information. Good sizes for the amount of state - * information are 32, 64, 128, and 256 bytes. The state can be switched by - * calling the setstate() routine with the same array as was initiallized - * with initstate(). By default, the package runs with 128 bytes of state - * information and generates far better random numbers than a linear - * congruential generator. If the amount of state information is less than - * 32 bytes, a simple linear congruential R.N.G. is used. - * - * Internally, the state information is treated as an array of uint32_t's; the - * zeroeth element of the array is the type of R.N.G. being used (small - * integer); the remainder of the array is the state information for the - * R.N.G. Thus, 32 bytes of state information will give 7 ints worth of - * state information, which will allow a degree seven polynomial. (Note: - * the zeroeth word of state information also has some other information - * stored in it -- see setstate() for details). - * - * The random number generation technique is a linear feedback shift register - * approach, employing trinomials (since there are fewer terms to sum up that - * way). In this approach, the least significant bit of all the numbers in - * the state table will act as a linear feedback shift register, and will - * have period 2^deg - 1 (where deg is the degree of the polynomial being - * used, assuming that the polynomial is irreducible and primitive). The - * higher order bits will have longer periods, since their values are also - * influenced by pseudo-random carries out of the lower bits. The total - * period of the generator is approximately deg*(2**deg - 1); thus doubling - * the amount of state information has a vast influence on the period of the - * generator. Note: the deg*(2**deg - 1) is an approximation only good for - * large deg, when the period of the shift is the dominant factor. - * With deg equal to seven, the period is actually much longer than the - * 7*(2**7 - 1) predicted by this formula. - * - * Modified 28 December 1994 by Jacob S. Rosenberg. - * The following changes have been made: - * All references to the type u_int have been changed to unsigned long. - * All references to type int have been changed to type long. Other - * cleanups have been made as well. A warning for both initstate and - * setstate has been inserted to the effect that on Sparc platforms - * the 'arg_state' variable must be forced to begin on word boundaries. - * This can be easily done by casting a long integer array to char *. - * The overall logic has been left STRICTLY alone. This software was - * tested on both a VAX and Sun SpacsStation with exactly the same - * results. The new version and the original give IDENTICAL results. - * The new version is somewhat faster than the original. As the - * documentation says: "By default, the package runs with 128 bytes of - * state information and generates far better random numbers than a linear - * congruential generator. If the amount of state information is less than - * 32 bytes, a simple linear congruential R.N.G. is used." For a buffer of - * 128 bytes, this new version runs about 19 percent faster and for a 16 - * byte buffer it is about 5 percent faster. - */ - -/* - * For each of the currently supported random number generators, we have a - * break value on the amount of state information (you need at least this - * many bytes of state info to support this random number generator), a degree - * for the polynomial (actually a trinomial) that the R.N.G. is based on, and - * the separation between the two lower order coefficients of the trinomial. - */ -#define TYPE_0 0 /* linear congruential */ -#define BREAK_0 8 -#define DEG_0 0 -#define SEP_0 0 - -#define TYPE_1 1 /* x**7 + x**3 + 1 */ -#define BREAK_1 32 -#define DEG_1 7 -#define SEP_1 3 - -#define TYPE_2 2 /* x**15 + x + 1 */ -#define BREAK_2 64 -#define DEG_2 15 -#define SEP_2 1 - -#define TYPE_3 3 /* x**31 + x**3 + 1 */ -#define BREAK_3 128 -#define DEG_3 31 -#define SEP_3 3 - -#define TYPE_4 4 /* x**63 + x + 1 */ -#define BREAK_4 256 -#define DEG_4 63 -#define SEP_4 1 - -/* - * Array versions of the above information to make code run faster -- - * relies on fact that TYPE_i == i. - */ -#define MAX_TYPES 5 /* max number of types above */ - -#ifdef USE_WEAK_SEEDING -#define NSHUFF 0 -#else /* !USE_WEAK_SEEDING */ -#define NSHUFF 50 /* to drop some "seed -> 1st value" linearity */ -#endif /* !USE_WEAK_SEEDING */ - -static const int degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 }; -static const int seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 }; - -/* - * Initially, everything is set up as if from: - * - * initstate(1, randtbl, 128); - * - * Note that this initialization takes advantage of the fact that srandom() - * advances the front and rear pointers 10*rand_deg times, and hence the - * rear pointer which starts at 0 will also end up at zero; thus the zeroeth - * element of the state information, which contains info about the current - * position of the rear pointer is just - * - * MAX_TYPES * (rptr - state) + TYPE_3 == TYPE_3. - */ - -static uint32_t randtbl[DEG_3 + 1] = { - TYPE_3, -#ifdef USE_WEAK_SEEDING -/* Historic implementation compatibility */ -/* The random sequences do not vary much with the seed */ - 0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342, 0xde3b81e0, 0xdf0a6fb5, - 0xf103bc02, 0x48f340fb, 0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd, - 0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86, 0xda672e2a, 0x1588ca88, - 0xe369735d, 0x904f35f7, 0xd7158fd6, 0x6fa6f051, 0x616e6b96, 0xac94efdc, - 0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b, 0xf5ad9d0e, 0x8999220b, - 0x27fb47b9, -#else /* !USE_WEAK_SEEDING */ - 0x991539b1, 0x16a5bce3, 0x6774a4cd, 0x3e01511e, 0x4e508aaa, 0x61048c05, - 0xf5500617, 0x846b7115, 0x6a19892c, 0x896a97af, 0xdb48f936, 0x14898454, - 0x37ffd106, 0xb58bff9c, 0x59e17104, 0xcf918a49, 0x09378c83, 0x52c7a471, - 0x8d293ea9, 0x1f4fc301, 0xc3db71be, 0x39b44e1c, 0xf8a44ef9, 0x4c8b80b1, - 0x19edc328, 0x87bf4bdd, 0xc9b240e5, 0xe9ee4b1b, 0x4382aee7, 0x535b6b41, - 0xf3bec5da -#endif /* !USE_WEAK_SEEDING */ -}; - -/* - * fptr and rptr are two pointers into the state info, a front and a rear - * pointer. These two pointers are always rand_sep places aparts, as they - * cycle cyclically through the state information. (Yes, this does mean we - * could get away with just one pointer, but the code for random() is more - * efficient this way). The pointers are left positioned as they would be - * from the call - * - * initstate(1, randtbl, 128); - * - * (The position of the rear pointer, rptr, is really 0 (as explained above - * in the initialization of randtbl) because the state table pointer is set - * to point to randtbl[1] (as explained below). - */ -static uint32_t *fptr = &randtbl[SEP_3 + 1]; -static uint32_t *rptr = &randtbl[1]; - -/* - * The following things are the pointer to the state information table, the - * type of the current generator, the degree of the current polynomial being - * used, and the separation between the two pointers. Note that for efficiency - * of random(), we remember the first location of the state information, not - * the zeroeth. Hence it is valid to access state[-1], which is used to - * store the type of the R.N.G. Also, we remember the last location, since - * this is more efficient than indexing every time to find the address of - * the last element to see if the front and rear pointers have wrapped. - */ -static uint32_t *state = &randtbl[1]; -static int rand_type = TYPE_3; -static int rand_deg = DEG_3; -static int rand_sep = SEP_3; -static uint32_t *end_ptr = &randtbl[DEG_3 + 1]; - -static inline uint32_t good_rand(int32_t); - -static inline uint32_t good_rand (x) - int32_t x; -{ -#ifdef USE_WEAK_SEEDING -/* - * Historic implementation compatibility. - * The random sequences do not vary much with the seed, - * even with overflowing. - */ - return (1103515245 * x + 12345); -#else /* !USE_WEAK_SEEDING */ -/* - * Compute x = (7^5 * x) mod (2^31 - 1) - * wihout overflowing 31 bits: - * (2^31 - 1) = 127773 * (7^5) + 2836 - * From "Random number generators: good ones are hard to find", - * Park and Miller, Communications of the ACM, vol. 31, no. 10, - * October 1988, p. 1195. - */ - int32_t hi, lo; - - /* Can't be initialized with 0, so use another value. */ - if (x == 0) - x = 123459876; - hi = x / 127773; - lo = x % 127773; - x = 16807 * lo - 2836 * hi; - if (x < 0) - x += 0x7fffffff; - return (x); -#endif /* !USE_WEAK_SEEDING */ -} - -/* - * srandom: - * - * Initialize the random number generator based on the given seed. If the - * type is the trivial no-state-information type, just remember the seed. - * Otherwise, initializes state[] based on the given "seed" via a linear - * congruential generator. Then, the pointers are set to known locations - * that are exactly rand_sep places apart. Lastly, it cycles the state - * information a given number of times to get rid of any initial dependencies - * introduced by the L.C.R.N.G. Note that the initialization of randtbl[] - * for default usage relies on values produced by this routine. - */ -void -srandom(x) - unsigned long x; -{ - int i, lim; - - state[0] = (uint32_t)x; - if (rand_type == TYPE_0) - lim = NSHUFF; - else { - for (i = 1; i < rand_deg; i++) - state[i] = good_rand(state[i - 1]); - fptr = &state[rand_sep]; - rptr = &state[0]; - lim = 10 * rand_deg; - } - for (i = 0; i < lim; i++) - (void)random(); -} - -/* - * srandomdev: - * - * Many programs choose the seed value in a totally predictable manner. - * This often causes problems. We seed the generator using the much more - * secure random(4) interface. Note that this particular seeding - * procedure can generate states which are impossible to reproduce by - * calling srandom() with any value, since the succeeding terms in the - * state buffer are no longer derived from the LC algorithm applied to - * a fixed seed. - */ -void -srandomdev() -{ - int fd, done; - size_t len; - - if (rand_type == TYPE_0) - len = sizeof state[0]; - else - len = rand_deg * sizeof state[0]; - - done = 0; - fd = _open("/dev/random", O_RDONLY, 0); - if (fd >= 0) { - if (_read(fd, (void *) state, len) == (ssize_t) len) - done = 1; - _close(fd); - } - - if (!done) { - struct timeval tv; - unsigned long junk; - - gettimeofday(&tv, NULL); - srandom((getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec ^ junk); - return; - } - - if (rand_type != TYPE_0) { - fptr = &state[rand_sep]; - rptr = &state[0]; - } -} - -/* - * initstate: - * - * Initialize the state information in the given array of n bytes for future - * random number generation. Based on the number of bytes we are given, and - * the break values for the different R.N.G.'s, we choose the best (largest) - * one we can and set things up for it. srandom() is then called to - * initialize the state information. - * - * Note that on return from srandom(), we set state[-1] to be the type - * multiplexed with the current value of the rear pointer; this is so - * successive calls to initstate() won't lose this information and will be - * able to restart with setstate(). - * - * Note: the first thing we do is save the current state, if any, just like - * setstate() so that it doesn't matter when initstate is called. - * - * Returns a pointer to the old state. - * - * Note: The Sparc platform requires that arg_state begin on an int - * word boundary; otherwise a bus error will occur. Even so, lint will - * complain about mis-alignment, but you should disregard these messages. - */ -char * -initstate(seed, arg_state, n) - unsigned long seed; /* seed for R.N.G. */ - char *arg_state; /* pointer to state array */ - long n; /* # bytes of state info */ -{ - char *ostate = (char *)(&state[-1]); - uint32_t *int_arg_state = (uint32_t *)arg_state; - - if (rand_type == TYPE_0) - state[-1] = rand_type; - else - state[-1] = MAX_TYPES * (rptr - state) + rand_type; - if (n < BREAK_0) { - (void)fprintf(stderr, - "random: not enough state (%ld bytes); ignored.\n", n); - return(0); - } - if (n < BREAK_1) { - rand_type = TYPE_0; - rand_deg = DEG_0; - rand_sep = SEP_0; - } else if (n < BREAK_2) { - rand_type = TYPE_1; - rand_deg = DEG_1; - rand_sep = SEP_1; - } else if (n < BREAK_3) { - rand_type = TYPE_2; - rand_deg = DEG_2; - rand_sep = SEP_2; - } else if (n < BREAK_4) { - rand_type = TYPE_3; - rand_deg = DEG_3; - rand_sep = SEP_3; - } else { - rand_type = TYPE_4; - rand_deg = DEG_4; - rand_sep = SEP_4; - } - state = int_arg_state + 1; /* first location */ - end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */ - srandom(seed); - if (rand_type == TYPE_0) - int_arg_state[0] = rand_type; - else - int_arg_state[0] = MAX_TYPES * (rptr - state) + rand_type; - return(ostate); -} - -/* - * setstate: - * - * Restore the state from the given state array. - * - * Note: it is important that we also remember the locations of the pointers - * in the current state information, and restore the locations of the pointers - * from the old state information. This is done by multiplexing the pointer - * location into the zeroeth word of the state information. - * - * Note that due to the order in which things are done, it is OK to call - * setstate() with the same state as the current state. - * - * Returns a pointer to the old state information. - * - * Note: The Sparc platform requires that arg_state begin on an int - * word boundary; otherwise a bus error will occur. Even so, lint will - * complain about mis-alignment, but you should disregard these messages. - */ -char * -setstate(arg_state) - char *arg_state; /* pointer to state array */ -{ - uint32_t *new_state = (uint32_t *)arg_state; - uint32_t type = new_state[0] % MAX_TYPES; - uint32_t rear = new_state[0] / MAX_TYPES; - char *ostate = (char *)(&state[-1]); - - if (rand_type == TYPE_0) - state[-1] = rand_type; - else - state[-1] = MAX_TYPES * (rptr - state) + rand_type; - switch(type) { - case TYPE_0: - case TYPE_1: - case TYPE_2: - case TYPE_3: - case TYPE_4: - rand_type = type; - rand_deg = degrees[type]; - rand_sep = seps[type]; - break; - default: - (void)fprintf(stderr, - "random: state info corrupted; not changed.\n"); - } - state = new_state + 1; - if (rand_type != TYPE_0) { - rptr = &state[rear]; - fptr = &state[(rear + rand_sep) % rand_deg]; - } - end_ptr = &state[rand_deg]; /* set end_ptr too */ - return(ostate); -} - -/* - * random: - * - * If we are using the trivial TYPE_0 R.N.G., just do the old linear - * congruential bit. Otherwise, we do our fancy trinomial stuff, which is - * the same in all the other cases due to all the global variables that have - * been set up. The basic operation is to add the number at the rear pointer - * into the one at the front pointer. Then both pointers are advanced to - * the next location cyclically in the table. The value returned is the sum - * generated, reduced to 31 bits by throwing away the "least random" low bit. - * - * Note: the code takes advantage of the fact that both the front and - * rear pointers can't wrap on the same call by not testing the rear - * pointer if the front one has wrapped. - * - * Returns a 31-bit random number. - */ -long -random() -{ - uint32_t i; - uint32_t *f, *r; - - if (rand_type == TYPE_0) { - i = state[0]; - state[0] = i = (good_rand(i)) & 0x7fffffff; - } else { - /* - * Use local variables rather than static variables for speed. - */ - f = fptr; r = rptr; - *f += *r; - i = (*f >> 1) & 0x7fffffff; /* chucking least random bit */ - if (++f >= end_ptr) { - f = state; - ++r; - } - else if (++r >= end_ptr) { - r = state; - } - - fptr = f; rptr = r; - } - return((long)i); -} diff --git a/lib/libc/stdlib/rb.h b/lib/libc/stdlib/rb.h deleted file mode 100644 index baaec7f..0000000 --- a/lib/libc/stdlib/rb.h +++ /dev/null @@ -1,1002 +0,0 @@ -/*- - ******************************************************************************* - * - * Copyright (C) 2008-2010 Jason Evans <jasone@FreeBSD.org>. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice(s), this list of conditions and the following disclaimer - * unmodified other than the allowable addition of one or more - * copyright notices. - * 2. Redistributions in binary form must reproduce the above copyright - * notice(s), this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - * - * cpp macro implementation of left-leaning 2-3 red-black trees. Parent - * pointers are not used, and color bits are stored in the least significant - * bit of right-child pointers (if RB_COMPACT is defined), thus making node - * linkage as compact as is possible for red-black trees. - * - * Usage: - * - * #include <stdint.h> - * #include <stdbool.h> - * #define NDEBUG // (Optional, see assert(3).) - * #include <assert.h> - * #define RB_COMPACT // (Optional, embed color bits in right-child pointers.) - * #include <rb.h> - * ... - * - ******************************************************************************* - */ - -#ifndef RB_H_ -#define RB_H_ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#ifdef RB_COMPACT -/* Node structure. */ -#define rb_node(a_type) \ -struct { \ - a_type *rbn_left; \ - a_type *rbn_right_red; \ -} -#else -#define rb_node(a_type) \ -struct { \ - a_type *rbn_left; \ - a_type *rbn_right; \ - bool rbn_red; \ -} -#endif - -/* Root structure. */ -#define rb_tree(a_type) \ -struct { \ - a_type *rbt_root; \ - a_type rbt_nil; \ -} - -/* Left accessors. */ -#define rbtn_left_get(a_type, a_field, a_node) \ - ((a_node)->a_field.rbn_left) -#define rbtn_left_set(a_type, a_field, a_node, a_left) do { \ - (a_node)->a_field.rbn_left = a_left; \ -} while (0) - -#ifdef RB_COMPACT -/* Right accessors. */ -#define rbtn_right_get(a_type, a_field, a_node) \ - ((a_type *) (((intptr_t) (a_node)->a_field.rbn_right_red) \ - & ((ssize_t)-2))) -#define rbtn_right_set(a_type, a_field, a_node, a_right) do { \ - (a_node)->a_field.rbn_right_red = (a_type *) (((uintptr_t) a_right) \ - | (((uintptr_t) (a_node)->a_field.rbn_right_red) & ((size_t)1))); \ -} while (0) - -/* Color accessors. */ -#define rbtn_red_get(a_type, a_field, a_node) \ - ((bool) (((uintptr_t) (a_node)->a_field.rbn_right_red) \ - & ((size_t)1))) -#define rbtn_color_set(a_type, a_field, a_node, a_red) do { \ - (a_node)->a_field.rbn_right_red = (a_type *) ((((intptr_t) \ - (a_node)->a_field.rbn_right_red) & ((ssize_t)-2)) \ - | ((ssize_t)a_red)); \ -} while (0) -#define rbtn_red_set(a_type, a_field, a_node) do { \ - (a_node)->a_field.rbn_right_red = (a_type *) (((uintptr_t) \ - (a_node)->a_field.rbn_right_red) | ((size_t)1)); \ -} while (0) -#define rbtn_black_set(a_type, a_field, a_node) do { \ - (a_node)->a_field.rbn_right_red = (a_type *) (((intptr_t) \ - (a_node)->a_field.rbn_right_red) & ((ssize_t)-2)); \ -} while (0) -#else -/* Right accessors. */ -#define rbtn_right_get(a_type, a_field, a_node) \ - ((a_node)->a_field.rbn_right) -#define rbtn_right_set(a_type, a_field, a_node, a_right) do { \ - (a_node)->a_field.rbn_right = a_right; \ -} while (0) - -/* Color accessors. */ -#define rbtn_red_get(a_type, a_field, a_node) \ - ((a_node)->a_field.rbn_red) -#define rbtn_color_set(a_type, a_field, a_node, a_red) do { \ - (a_node)->a_field.rbn_red = (a_red); \ -} while (0) -#define rbtn_red_set(a_type, a_field, a_node) do { \ - (a_node)->a_field.rbn_red = true; \ -} while (0) -#define rbtn_black_set(a_type, a_field, a_node) do { \ - (a_node)->a_field.rbn_red = false; \ -} while (0) -#endif - -/* Node initializer. */ -#define rbt_node_new(a_type, a_field, a_rbt, a_node) do { \ - rbtn_left_set(a_type, a_field, (a_node), &(a_rbt)->rbt_nil); \ - rbtn_right_set(a_type, a_field, (a_node), &(a_rbt)->rbt_nil); \ - rbtn_red_set(a_type, a_field, (a_node)); \ -} while (0) - -/* Tree initializer. */ -#define rb_new(a_type, a_field, a_rbt) do { \ - (a_rbt)->rbt_root = &(a_rbt)->rbt_nil; \ - rbt_node_new(a_type, a_field, a_rbt, &(a_rbt)->rbt_nil); \ - rbtn_black_set(a_type, a_field, &(a_rbt)->rbt_nil); \ -} while (0) - -/* Internal utility macros. */ -#define rbtn_first(a_type, a_field, a_rbt, a_root, r_node) do { \ - (r_node) = (a_root); \ - if ((r_node) != &(a_rbt)->rbt_nil) { \ - for (; \ - rbtn_left_get(a_type, a_field, (r_node)) != &(a_rbt)->rbt_nil;\ - (r_node) = rbtn_left_get(a_type, a_field, (r_node))) { \ - } \ - } \ -} while (0) - -#define rbtn_last(a_type, a_field, a_rbt, a_root, r_node) do { \ - (r_node) = (a_root); \ - if ((r_node) != &(a_rbt)->rbt_nil) { \ - for (; rbtn_right_get(a_type, a_field, (r_node)) != \ - &(a_rbt)->rbt_nil; (r_node) = rbtn_right_get(a_type, a_field, \ - (r_node))) { \ - } \ - } \ -} while (0) - -#define rbtn_rotate_left(a_type, a_field, a_node, r_node) do { \ - (r_node) = rbtn_right_get(a_type, a_field, (a_node)); \ - rbtn_right_set(a_type, a_field, (a_node), \ - rbtn_left_get(a_type, a_field, (r_node))); \ - rbtn_left_set(a_type, a_field, (r_node), (a_node)); \ -} while (0) - -#define rbtn_rotate_right(a_type, a_field, a_node, r_node) do { \ - (r_node) = rbtn_left_get(a_type, a_field, (a_node)); \ - rbtn_left_set(a_type, a_field, (a_node), \ - rbtn_right_get(a_type, a_field, (r_node))); \ - rbtn_right_set(a_type, a_field, (r_node), (a_node)); \ -} while (0) - -/* - * The rb_proto() macro generates function prototypes that correspond to the - * functions generated by an equivalently parameterized call to rb_gen(). - */ - -#define rb_proto(a_attr, a_prefix, a_rbt_type, a_type) \ -a_attr void \ -a_prefix##new(a_rbt_type *rbtree); \ -a_attr a_type * \ -a_prefix##first(a_rbt_type *rbtree); \ -a_attr a_type * \ -a_prefix##last(a_rbt_type *rbtree); \ -a_attr a_type * \ -a_prefix##next(a_rbt_type *rbtree, a_type *node); \ -a_attr a_type * \ -a_prefix##prev(a_rbt_type *rbtree, a_type *node); \ -a_attr a_type * \ -a_prefix##search(a_rbt_type *rbtree, a_type *key); \ -a_attr a_type * \ -a_prefix##nsearch(a_rbt_type *rbtree, a_type *key); \ -a_attr a_type * \ -a_prefix##psearch(a_rbt_type *rbtree, a_type *key); \ -a_attr void \ -a_prefix##insert(a_rbt_type *rbtree, a_type *node); \ -a_attr void \ -a_prefix##remove(a_rbt_type *rbtree, a_type *node); \ -a_attr a_type * \ -a_prefix##iter(a_rbt_type *rbtree, a_type *start, a_type *(*cb)( \ - a_rbt_type *, a_type *, void *), void *arg); \ -a_attr a_type * \ -a_prefix##reverse_iter(a_rbt_type *rbtree, a_type *start, \ - a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg); - -/* - * The rb_gen() macro generates a type-specific red-black tree implementation, - * based on the above cpp macros. - * - * Arguments: - * - * a_attr : Function attribute for generated functions (ex: static). - * a_prefix : Prefix for generated functions (ex: extree_). - * a_rb_type : Type for red-black tree data structure (ex: extree_t). - * a_type : Type for red-black tree node data structure (ex: - * extree_node_t). - * a_field : Name of red-black tree node linkage (ex: extree_link). - * a_cmp : Node comparison function name, with the following prototype: - * int (a_cmp *)(a_type *a_node, a_type *a_other); - * ^^^^^^ - * or a_key - * Interpretation of comparision function return values: - * -1 : a_node < a_other - * 0 : a_node == a_other - * 1 : a_node > a_other - * In all cases, the a_node or a_key macro argument is the first - * argument to the comparison function, which makes it possible - * to write comparison functions that treat the first argument - * specially. - * - * Assuming the following setup: - * - * typedef struct ex_node_s ex_node_t; - * struct ex_node_s { - * rb_node(ex_node_t) ex_link; - * }; - * typedef rb(ex_node_t) ex_t; - * rb_gen(static, ex_, ex_t, ex_node_t, ex_link, ex_cmp, 1297, 1301) - * - * The following API is generated: - * - * static void - * ex_new(ex_t *extree); - * Description: Initialize a red-black tree structure. - * Args: - * extree: Pointer to an uninitialized red-black tree object. - * - * static ex_node_t * - * ex_first(ex_t *extree); - * static ex_node_t * - * ex_last(ex_t *extree); - * Description: Get the first/last node in extree. - * Args: - * extree: Pointer to an initialized red-black tree object. - * Ret: First/last node in extree, or NULL if extree is empty. - * - * static ex_node_t * - * ex_next(ex_t *extree, ex_node_t *node); - * static ex_node_t * - * ex_prev(ex_t *extree, ex_node_t *node); - * Description: Get node's successor/predecessor. - * Args: - * extree: Pointer to an initialized red-black tree object. - * node : A node in extree. - * Ret: node's successor/predecessor in extree, or NULL if node is - * last/first. - * - * static ex_node_t * - * ex_search(ex_t *extree, ex_node_t *key); - * Description: Search for node that matches key. - * Args: - * extree: Pointer to an initialized red-black tree object. - * key : Search key. - * Ret: Node in extree that matches key, or NULL if no match. - * - * static ex_node_t * - * ex_nsearch(ex_t *extree, ex_node_t *key); - * static ex_node_t * - * ex_psearch(ex_t *extree, ex_node_t *key); - * Description: Search for node that matches key. If no match is found, - * return what would be key's successor/predecessor, were - * key in extree. - * Args: - * extree: Pointer to an initialized red-black tree object. - * key : Search key. - * Ret: Node in extree that matches key, or if no match, hypothetical - * node's successor/predecessor (NULL if no successor/predecessor). - * - * static void - * ex_insert(ex_t *extree, ex_node_t *node); - * Description: Insert node into extree. - * Args: - * extree: Pointer to an initialized red-black tree object. - * node : Node to be inserted into extree. - * - * static void - * ex_remove(ex_t *extree, ex_node_t *node); - * Description: Remove node from extree. - * Args: - * extree: Pointer to an initialized red-black tree object. - * node : Node in extree to be removed. - * - * static ex_node_t * - * ex_iter(ex_t *extree, ex_node_t *start, ex_node_t *(*cb)(ex_t *, - * ex_node_t *, void *), void *arg); - * static ex_node_t * - * ex_reverse_iter(ex_t *extree, ex_node_t *start, ex_node *(*cb)(ex_t *, - * ex_node_t *, void *), void *arg); - * Description: Iterate forward/backward over extree, starting at node. - * If extree is modified, iteration must be immediately - * terminated by the callback function that causes the - * modification. - * Args: - * extree: Pointer to an initialized red-black tree object. - * start : Node at which to start iteration, or NULL to start at - * first/last node. - * cb : Callback function, which is called for each node during - * iteration. Under normal circumstances the callback function - * should return NULL, which causes iteration to continue. If a - * callback function returns non-NULL, iteration is immediately - * terminated and the non-NULL return value is returned by the - * iterator. This is useful for re-starting iteration after - * modifying extree. - * arg : Opaque pointer passed to cb(). - * Ret: NULL if iteration completed, or the non-NULL callback return value - * that caused termination of the iteration. - */ -#define rb_gen(a_attr, a_prefix, a_rbt_type, a_type, a_field, a_cmp) \ -a_attr void \ -a_prefix##new(a_rbt_type *rbtree) { \ - rb_new(a_type, a_field, rbtree); \ -} \ -a_attr a_type * \ -a_prefix##first(a_rbt_type *rbtree) { \ - a_type *ret; \ - rbtn_first(a_type, a_field, rbtree, rbtree->rbt_root, ret); \ - if (ret == &rbtree->rbt_nil) { \ - ret = NULL; \ - } \ - return (ret); \ -} \ -a_attr a_type * \ -a_prefix##last(a_rbt_type *rbtree) { \ - a_type *ret; \ - rbtn_last(a_type, a_field, rbtree, rbtree->rbt_root, ret); \ - if (ret == &rbtree->rbt_nil) { \ - ret = NULL; \ - } \ - return (ret); \ -} \ -a_attr a_type * \ -a_prefix##next(a_rbt_type *rbtree, a_type *node) { \ - a_type *ret; \ - if (rbtn_right_get(a_type, a_field, node) != &rbtree->rbt_nil) { \ - rbtn_first(a_type, a_field, rbtree, rbtn_right_get(a_type, \ - a_field, node), ret); \ - } else { \ - a_type *tnode = rbtree->rbt_root; \ - assert(tnode != &rbtree->rbt_nil); \ - ret = &rbtree->rbt_nil; \ - while (true) { \ - int cmp = (a_cmp)(node, tnode); \ - if (cmp < 0) { \ - ret = tnode; \ - tnode = rbtn_left_get(a_type, a_field, tnode); \ - } else if (cmp > 0) { \ - tnode = rbtn_right_get(a_type, a_field, tnode); \ - } else { \ - break; \ - } \ - assert(tnode != &rbtree->rbt_nil); \ - } \ - } \ - if (ret == &rbtree->rbt_nil) { \ - ret = (NULL); \ - } \ - return (ret); \ -} \ -a_attr a_type * \ -a_prefix##prev(a_rbt_type *rbtree, a_type *node) { \ - a_type *ret; \ - if (rbtn_left_get(a_type, a_field, node) != &rbtree->rbt_nil) { \ - rbtn_last(a_type, a_field, rbtree, rbtn_left_get(a_type, \ - a_field, node), ret); \ - } else { \ - a_type *tnode = rbtree->rbt_root; \ - assert(tnode != &rbtree->rbt_nil); \ - ret = &rbtree->rbt_nil; \ - while (true) { \ - int cmp = (a_cmp)(node, tnode); \ - if (cmp < 0) { \ - tnode = rbtn_left_get(a_type, a_field, tnode); \ - } else if (cmp > 0) { \ - ret = tnode; \ - tnode = rbtn_right_get(a_type, a_field, tnode); \ - } else { \ - break; \ - } \ - assert(tnode != &rbtree->rbt_nil); \ - } \ - } \ - if (ret == &rbtree->rbt_nil) { \ - ret = (NULL); \ - } \ - return (ret); \ -} \ -a_attr a_type * \ -a_prefix##search(a_rbt_type *rbtree, a_type *key) { \ - a_type *ret; \ - int cmp; \ - ret = rbtree->rbt_root; \ - while (ret != &rbtree->rbt_nil \ - && (cmp = (a_cmp)(key, ret)) != 0) { \ - if (cmp < 0) { \ - ret = rbtn_left_get(a_type, a_field, ret); \ - } else { \ - ret = rbtn_right_get(a_type, a_field, ret); \ - } \ - } \ - if (ret == &rbtree->rbt_nil) { \ - ret = (NULL); \ - } \ - return (ret); \ -} \ -a_attr a_type * \ -a_prefix##nsearch(a_rbt_type *rbtree, a_type *key) { \ - a_type *ret; \ - a_type *tnode = rbtree->rbt_root; \ - ret = &rbtree->rbt_nil; \ - while (tnode != &rbtree->rbt_nil) { \ - int cmp = (a_cmp)(key, tnode); \ - if (cmp < 0) { \ - ret = tnode; \ - tnode = rbtn_left_get(a_type, a_field, tnode); \ - } else if (cmp > 0) { \ - tnode = rbtn_right_get(a_type, a_field, tnode); \ - } else { \ - ret = tnode; \ - break; \ - } \ - } \ - if (ret == &rbtree->rbt_nil) { \ - ret = (NULL); \ - } \ - return (ret); \ -} \ -a_attr a_type * \ -a_prefix##psearch(a_rbt_type *rbtree, a_type *key) { \ - a_type *ret; \ - a_type *tnode = rbtree->rbt_root; \ - ret = &rbtree->rbt_nil; \ - while (tnode != &rbtree->rbt_nil) { \ - int cmp = (a_cmp)(key, tnode); \ - if (cmp < 0) { \ - tnode = rbtn_left_get(a_type, a_field, tnode); \ - } else if (cmp > 0) { \ - ret = tnode; \ - tnode = rbtn_right_get(a_type, a_field, tnode); \ - } else { \ - ret = tnode; \ - break; \ - } \ - } \ - if (ret == &rbtree->rbt_nil) { \ - ret = (NULL); \ - } \ - return (ret); \ -} \ -a_attr void \ -a_prefix##insert(a_rbt_type *rbtree, a_type *node) { \ - struct { \ - a_type *node; \ - int cmp; \ - } path[sizeof(void *) << 4], *pathp; \ - rbt_node_new(a_type, a_field, rbtree, node); \ - /* Wind. */ \ - path->node = rbtree->rbt_root; \ - for (pathp = path; pathp->node != &rbtree->rbt_nil; pathp++) { \ - int cmp = pathp->cmp = a_cmp(node, pathp->node); \ - assert(cmp != 0); \ - if (cmp < 0) { \ - pathp[1].node = rbtn_left_get(a_type, a_field, \ - pathp->node); \ - } else { \ - pathp[1].node = rbtn_right_get(a_type, a_field, \ - pathp->node); \ - } \ - } \ - pathp->node = node; \ - /* Unwind. */ \ - for (pathp--; (uintptr_t)pathp >= (uintptr_t)path; pathp--) { \ - a_type *cnode = pathp->node; \ - if (pathp->cmp < 0) { \ - a_type *left = pathp[1].node; \ - rbtn_left_set(a_type, a_field, cnode, left); \ - if (rbtn_red_get(a_type, a_field, left)) { \ - a_type *leftleft = rbtn_left_get(a_type, a_field, left);\ - if (rbtn_red_get(a_type, a_field, leftleft)) { \ - /* Fix up 4-node. */ \ - a_type *tnode; \ - rbtn_black_set(a_type, a_field, leftleft); \ - rbtn_rotate_right(a_type, a_field, cnode, tnode); \ - cnode = tnode; \ - } \ - } else { \ - return; \ - } \ - } else { \ - a_type *right = pathp[1].node; \ - rbtn_right_set(a_type, a_field, cnode, right); \ - if (rbtn_red_get(a_type, a_field, right)) { \ - a_type *left = rbtn_left_get(a_type, a_field, cnode); \ - if (rbtn_red_get(a_type, a_field, left)) { \ - /* Split 4-node. */ \ - rbtn_black_set(a_type, a_field, left); \ - rbtn_black_set(a_type, a_field, right); \ - rbtn_red_set(a_type, a_field, cnode); \ - } else { \ - /* Lean left. */ \ - a_type *tnode; \ - bool tred = rbtn_red_get(a_type, a_field, cnode); \ - rbtn_rotate_left(a_type, a_field, cnode, tnode); \ - rbtn_color_set(a_type, a_field, tnode, tred); \ - rbtn_red_set(a_type, a_field, cnode); \ - cnode = tnode; \ - } \ - } else { \ - return; \ - } \ - } \ - pathp->node = cnode; \ - } \ - /* Set root, and make it black. */ \ - rbtree->rbt_root = path->node; \ - rbtn_black_set(a_type, a_field, rbtree->rbt_root); \ -} \ -a_attr void \ -a_prefix##remove(a_rbt_type *rbtree, a_type *node) { \ - struct { \ - a_type *node; \ - int cmp; \ - } *pathp, *nodep, path[sizeof(void *) << 4]; \ - /* Wind. */ \ - nodep = NULL; /* Silence compiler warning. */ \ - path->node = rbtree->rbt_root; \ - for (pathp = path; pathp->node != &rbtree->rbt_nil; pathp++) { \ - int cmp = pathp->cmp = a_cmp(node, pathp->node); \ - if (cmp < 0) { \ - pathp[1].node = rbtn_left_get(a_type, a_field, \ - pathp->node); \ - } else { \ - pathp[1].node = rbtn_right_get(a_type, a_field, \ - pathp->node); \ - if (cmp == 0) { \ - /* Find node's successor, in preparation for swap. */ \ - pathp->cmp = 1; \ - nodep = pathp; \ - for (pathp++; pathp->node != &rbtree->rbt_nil; \ - pathp++) { \ - pathp->cmp = -1; \ - pathp[1].node = rbtn_left_get(a_type, a_field, \ - pathp->node); \ - } \ - break; \ - } \ - } \ - } \ - assert(nodep->node == node); \ - pathp--; \ - if (pathp->node != node) { \ - /* Swap node with its successor. */ \ - bool tred = rbtn_red_get(a_type, a_field, pathp->node); \ - rbtn_color_set(a_type, a_field, pathp->node, \ - rbtn_red_get(a_type, a_field, node)); \ - rbtn_left_set(a_type, a_field, pathp->node, \ - rbtn_left_get(a_type, a_field, node)); \ - /* If node's successor is its right child, the following code */\ - /* will do the wrong thing for the right child pointer. */\ - /* However, it doesn't matter, because the pointer will be */\ - /* properly set when the successor is pruned. */\ - rbtn_right_set(a_type, a_field, pathp->node, \ - rbtn_right_get(a_type, a_field, node)); \ - rbtn_color_set(a_type, a_field, node, tred); \ - /* The pruned leaf node's child pointers are never accessed */\ - /* again, so don't bother setting them to nil. */\ - nodep->node = pathp->node; \ - pathp->node = node; \ - if (nodep == path) { \ - rbtree->rbt_root = nodep->node; \ - } else { \ - if (nodep[-1].cmp < 0) { \ - rbtn_left_set(a_type, a_field, nodep[-1].node, \ - nodep->node); \ - } else { \ - rbtn_right_set(a_type, a_field, nodep[-1].node, \ - nodep->node); \ - } \ - } \ - } else { \ - a_type *left = rbtn_left_get(a_type, a_field, node); \ - if (left != &rbtree->rbt_nil) { \ - /* node has no successor, but it has a left child. */\ - /* Splice node out, without losing the left child. */\ - assert(rbtn_red_get(a_type, a_field, node) == false); \ - assert(rbtn_red_get(a_type, a_field, left)); \ - rbtn_black_set(a_type, a_field, left); \ - if (pathp == path) { \ - rbtree->rbt_root = left; \ - } else { \ - if (pathp[-1].cmp < 0) { \ - rbtn_left_set(a_type, a_field, pathp[-1].node, \ - left); \ - } else { \ - rbtn_right_set(a_type, a_field, pathp[-1].node, \ - left); \ - } \ - } \ - return; \ - } else if (pathp == path) { \ - /* The tree only contained one node. */ \ - rbtree->rbt_root = &rbtree->rbt_nil; \ - return; \ - } \ - } \ - if (rbtn_red_get(a_type, a_field, pathp->node)) { \ - /* Prune red node, which requires no fixup. */ \ - assert(pathp[-1].cmp < 0); \ - rbtn_left_set(a_type, a_field, pathp[-1].node, \ - &rbtree->rbt_nil); \ - return; \ - } \ - /* The node to be pruned is black, so unwind until balance is */\ - /* restored. */\ - pathp->node = &rbtree->rbt_nil; \ - for (pathp--; (uintptr_t)pathp >= (uintptr_t)path; pathp--) { \ - assert(pathp->cmp != 0); \ - if (pathp->cmp < 0) { \ - rbtn_left_set(a_type, a_field, pathp->node, \ - pathp[1].node); \ - assert(rbtn_red_get(a_type, a_field, pathp[1].node) \ - == false); \ - if (rbtn_red_get(a_type, a_field, pathp->node)) { \ - a_type *right = rbtn_right_get(a_type, a_field, \ - pathp->node); \ - a_type *rightleft = rbtn_left_get(a_type, a_field, \ - right); \ - a_type *tnode; \ - if (rbtn_red_get(a_type, a_field, rightleft)) { \ - /* In the following diagrams, ||, //, and \\ */\ - /* indicate the path to the removed node. */\ - /* */\ - /* || */\ - /* pathp(r) */\ - /* // \ */\ - /* (b) (b) */\ - /* / */\ - /* (r) */\ - /* */\ - rbtn_black_set(a_type, a_field, pathp->node); \ - rbtn_rotate_right(a_type, a_field, right, tnode); \ - rbtn_right_set(a_type, a_field, pathp->node, tnode);\ - rbtn_rotate_left(a_type, a_field, pathp->node, \ - tnode); \ - } else { \ - /* || */\ - /* pathp(r) */\ - /* // \ */\ - /* (b) (b) */\ - /* / */\ - /* (b) */\ - /* */\ - rbtn_rotate_left(a_type, a_field, pathp->node, \ - tnode); \ - } \ - /* Balance restored, but rotation modified subtree */\ - /* root. */\ - assert((uintptr_t)pathp > (uintptr_t)path); \ - if (pathp[-1].cmp < 0) { \ - rbtn_left_set(a_type, a_field, pathp[-1].node, \ - tnode); \ - } else { \ - rbtn_right_set(a_type, a_field, pathp[-1].node, \ - tnode); \ - } \ - return; \ - } else { \ - a_type *right = rbtn_right_get(a_type, a_field, \ - pathp->node); \ - a_type *rightleft = rbtn_left_get(a_type, a_field, \ - right); \ - if (rbtn_red_get(a_type, a_field, rightleft)) { \ - /* || */\ - /* pathp(b) */\ - /* // \ */\ - /* (b) (b) */\ - /* / */\ - /* (r) */\ - a_type *tnode; \ - rbtn_black_set(a_type, a_field, rightleft); \ - rbtn_rotate_right(a_type, a_field, right, tnode); \ - rbtn_right_set(a_type, a_field, pathp->node, tnode);\ - rbtn_rotate_left(a_type, a_field, pathp->node, \ - tnode); \ - /* Balance restored, but rotation modified */\ - /* subree root, which may actually be the tree */\ - /* root. */\ - if (pathp == path) { \ - /* Set root. */ \ - rbtree->rbt_root = tnode; \ - } else { \ - if (pathp[-1].cmp < 0) { \ - rbtn_left_set(a_type, a_field, \ - pathp[-1].node, tnode); \ - } else { \ - rbtn_right_set(a_type, a_field, \ - pathp[-1].node, tnode); \ - } \ - } \ - return; \ - } else { \ - /* || */\ - /* pathp(b) */\ - /* // \ */\ - /* (b) (b) */\ - /* / */\ - /* (b) */\ - a_type *tnode; \ - rbtn_red_set(a_type, a_field, pathp->node); \ - rbtn_rotate_left(a_type, a_field, pathp->node, \ - tnode); \ - pathp->node = tnode; \ - } \ - } \ - } else { \ - a_type *left; \ - rbtn_right_set(a_type, a_field, pathp->node, \ - pathp[1].node); \ - left = rbtn_left_get(a_type, a_field, pathp->node); \ - if (rbtn_red_get(a_type, a_field, left)) { \ - a_type *tnode; \ - a_type *leftright = rbtn_right_get(a_type, a_field, \ - left); \ - a_type *leftrightleft = rbtn_left_get(a_type, a_field, \ - leftright); \ - if (rbtn_red_get(a_type, a_field, leftrightleft)) { \ - /* || */\ - /* pathp(b) */\ - /* / \\ */\ - /* (r) (b) */\ - /* \ */\ - /* (b) */\ - /* / */\ - /* (r) */\ - a_type *unode; \ - rbtn_black_set(a_type, a_field, leftrightleft); \ - rbtn_rotate_right(a_type, a_field, pathp->node, \ - unode); \ - rbtn_rotate_right(a_type, a_field, pathp->node, \ - tnode); \ - rbtn_right_set(a_type, a_field, unode, tnode); \ - rbtn_rotate_left(a_type, a_field, unode, tnode); \ - } else { \ - /* || */\ - /* pathp(b) */\ - /* / \\ */\ - /* (r) (b) */\ - /* \ */\ - /* (b) */\ - /* / */\ - /* (b) */\ - assert(leftright != &rbtree->rbt_nil); \ - rbtn_red_set(a_type, a_field, leftright); \ - rbtn_rotate_right(a_type, a_field, pathp->node, \ - tnode); \ - rbtn_black_set(a_type, a_field, tnode); \ - } \ - /* Balance restored, but rotation modified subtree */\ - /* root, which may actually be the tree root. */\ - if (pathp == path) { \ - /* Set root. */ \ - rbtree->rbt_root = tnode; \ - } else { \ - if (pathp[-1].cmp < 0) { \ - rbtn_left_set(a_type, a_field, pathp[-1].node, \ - tnode); \ - } else { \ - rbtn_right_set(a_type, a_field, pathp[-1].node, \ - tnode); \ - } \ - } \ - return; \ - } else if (rbtn_red_get(a_type, a_field, pathp->node)) { \ - a_type *leftleft = rbtn_left_get(a_type, a_field, left);\ - if (rbtn_red_get(a_type, a_field, leftleft)) { \ - /* || */\ - /* pathp(r) */\ - /* / \\ */\ - /* (b) (b) */\ - /* / */\ - /* (r) */\ - a_type *tnode; \ - rbtn_black_set(a_type, a_field, pathp->node); \ - rbtn_red_set(a_type, a_field, left); \ - rbtn_black_set(a_type, a_field, leftleft); \ - rbtn_rotate_right(a_type, a_field, pathp->node, \ - tnode); \ - /* Balance restored, but rotation modified */\ - /* subtree root. */\ - assert((uintptr_t)pathp > (uintptr_t)path); \ - if (pathp[-1].cmp < 0) { \ - rbtn_left_set(a_type, a_field, pathp[-1].node, \ - tnode); \ - } else { \ - rbtn_right_set(a_type, a_field, pathp[-1].node, \ - tnode); \ - } \ - return; \ - } else { \ - /* || */\ - /* pathp(r) */\ - /* / \\ */\ - /* (b) (b) */\ - /* / */\ - /* (b) */\ - rbtn_red_set(a_type, a_field, left); \ - rbtn_black_set(a_type, a_field, pathp->node); \ - /* Balance restored. */ \ - return; \ - } \ - } else { \ - a_type *leftleft = rbtn_left_get(a_type, a_field, left);\ - if (rbtn_red_get(a_type, a_field, leftleft)) { \ - /* || */\ - /* pathp(b) */\ - /* / \\ */\ - /* (b) (b) */\ - /* / */\ - /* (r) */\ - a_type *tnode; \ - rbtn_black_set(a_type, a_field, leftleft); \ - rbtn_rotate_right(a_type, a_field, pathp->node, \ - tnode); \ - /* Balance restored, but rotation modified */\ - /* subtree root, which may actually be the tree */\ - /* root. */\ - if (pathp == path) { \ - /* Set root. */ \ - rbtree->rbt_root = tnode; \ - } else { \ - if (pathp[-1].cmp < 0) { \ - rbtn_left_set(a_type, a_field, \ - pathp[-1].node, tnode); \ - } else { \ - rbtn_right_set(a_type, a_field, \ - pathp[-1].node, tnode); \ - } \ - } \ - return; \ - } else { \ - /* || */\ - /* pathp(b) */\ - /* / \\ */\ - /* (b) (b) */\ - /* / */\ - /* (b) */\ - rbtn_red_set(a_type, a_field, left); \ - } \ - } \ - } \ - } \ - /* Set root. */ \ - rbtree->rbt_root = path->node; \ - assert(rbtn_red_get(a_type, a_field, rbtree->rbt_root) == false); \ -} \ -a_attr a_type * \ -a_prefix##iter_recurse(a_rbt_type *rbtree, a_type *node, \ - a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) { \ - if (node == &rbtree->rbt_nil) { \ - return (&rbtree->rbt_nil); \ - } else { \ - a_type *ret; \ - if ((ret = a_prefix##iter_recurse(rbtree, rbtn_left_get(a_type, \ - a_field, node), cb, arg)) != &rbtree->rbt_nil \ - || (ret = cb(rbtree, node, arg)) != NULL) { \ - return (ret); \ - } \ - return (a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type, \ - a_field, node), cb, arg)); \ - } \ -} \ -a_attr a_type * \ -a_prefix##iter_start(a_rbt_type *rbtree, a_type *start, a_type *node, \ - a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) { \ - int cmp = a_cmp(start, node); \ - if (cmp < 0) { \ - a_type *ret; \ - if ((ret = a_prefix##iter_start(rbtree, start, \ - rbtn_left_get(a_type, a_field, node), cb, arg)) != \ - &rbtree->rbt_nil || (ret = cb(rbtree, node, arg)) != NULL) { \ - return (ret); \ - } \ - return (a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type, \ - a_field, node), cb, arg)); \ - } else if (cmp > 0) { \ - return (a_prefix##iter_start(rbtree, start, \ - rbtn_right_get(a_type, a_field, node), cb, arg)); \ - } else { \ - a_type *ret; \ - if ((ret = cb(rbtree, node, arg)) != NULL) { \ - return (ret); \ - } \ - return (a_prefix##iter_recurse(rbtree, rbtn_right_get(a_type, \ - a_field, node), cb, arg)); \ - } \ -} \ -a_attr a_type * \ -a_prefix##iter(a_rbt_type *rbtree, a_type *start, a_type *(*cb)( \ - a_rbt_type *, a_type *, void *), void *arg) { \ - a_type *ret; \ - if (start != NULL) { \ - ret = a_prefix##iter_start(rbtree, start, rbtree->rbt_root, \ - cb, arg); \ - } else { \ - ret = a_prefix##iter_recurse(rbtree, rbtree->rbt_root, cb, arg);\ - } \ - if (ret == &rbtree->rbt_nil) { \ - ret = NULL; \ - } \ - return (ret); \ -} \ -a_attr a_type * \ -a_prefix##reverse_iter_recurse(a_rbt_type *rbtree, a_type *node, \ - a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) { \ - if (node == &rbtree->rbt_nil) { \ - return (&rbtree->rbt_nil); \ - } else { \ - a_type *ret; \ - if ((ret = a_prefix##reverse_iter_recurse(rbtree, \ - rbtn_right_get(a_type, a_field, node), cb, arg)) != \ - &rbtree->rbt_nil || (ret = cb(rbtree, node, arg)) != NULL) { \ - return (ret); \ - } \ - return (a_prefix##reverse_iter_recurse(rbtree, \ - rbtn_left_get(a_type, a_field, node), cb, arg)); \ - } \ -} \ -a_attr a_type * \ -a_prefix##reverse_iter_start(a_rbt_type *rbtree, a_type *start, \ - a_type *node, a_type *(*cb)(a_rbt_type *, a_type *, void *), \ - void *arg) { \ - int cmp = a_cmp(start, node); \ - if (cmp > 0) { \ - a_type *ret; \ - if ((ret = a_prefix##reverse_iter_start(rbtree, start, \ - rbtn_right_get(a_type, a_field, node), cb, arg)) != \ - &rbtree->rbt_nil || (ret = cb(rbtree, node, arg)) != NULL) { \ - return (ret); \ - } \ - return (a_prefix##reverse_iter_recurse(rbtree, \ - rbtn_left_get(a_type, a_field, node), cb, arg)); \ - } else if (cmp < 0) { \ - return (a_prefix##reverse_iter_start(rbtree, start, \ - rbtn_left_get(a_type, a_field, node), cb, arg)); \ - } else { \ - a_type *ret; \ - if ((ret = cb(rbtree, node, arg)) != NULL) { \ - return (ret); \ - } \ - return (a_prefix##reverse_iter_recurse(rbtree, \ - rbtn_left_get(a_type, a_field, node), cb, arg)); \ - } \ -} \ -a_attr a_type * \ -a_prefix##reverse_iter(a_rbt_type *rbtree, a_type *start, \ - a_type *(*cb)(a_rbt_type *, a_type *, void *), void *arg) { \ - a_type *ret; \ - if (start != NULL) { \ - ret = a_prefix##reverse_iter_start(rbtree, start, \ - rbtree->rbt_root, cb, arg); \ - } else { \ - ret = a_prefix##reverse_iter_recurse(rbtree, rbtree->rbt_root, \ - cb, arg); \ - } \ - if (ret == &rbtree->rbt_nil) { \ - ret = NULL; \ - } \ - return (ret); \ -} - -#endif /* RB_H_ */ diff --git a/lib/libc/stdlib/reallocf.c b/lib/libc/stdlib/reallocf.c deleted file mode 100644 index a85b5a3..0000000 --- a/lib/libc/stdlib/reallocf.c +++ /dev/null @@ -1,48 +0,0 @@ -/*- - * Copyright (c) 1998, M. Warner Losh <imp@freebsd.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stdlib.h> - -void * -reallocf(void *ptr, size_t size) -{ - void *nptr; - - nptr = realloc(ptr, size); - - /* - * When the System V compatibility option (malloc "V" flag) is - * in effect, realloc(ptr, 0) frees the memory and returns NULL. - * So, to avoid double free, call free() only when size != 0. - * realloc(ptr, 0) can't fail when ptr != NULL. - */ - if (!nptr && ptr && size != 0) - free(ptr); - return (nptr); -} diff --git a/lib/libc/stdlib/realpath.3 b/lib/libc/stdlib/realpath.3 deleted file mode 100644 index fec5258..0000000 --- a/lib/libc/stdlib/realpath.3 +++ /dev/null @@ -1,135 +0,0 @@ -.\" Copyright (c) 1994 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" Jan-Simon Pendry. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)realpath.3 8.2 (Berkeley) 2/16/94 -.\" $FreeBSD$ -.\" -.Dd April 19, 2010 -.Dt REALPATH 3 -.Os -.Sh NAME -.Nm realpath -.Nd returns the canonicalized absolute pathname -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In sys/param.h -.In stdlib.h -.Ft "char *" -.Fn realpath "const char *pathname" "char *resolved_path" -.Sh DESCRIPTION -The -.Fn realpath -function resolves all symbolic links, extra -.Dq / -characters and references to -.Pa /./ -and -.Pa /../ -in -.Fa pathname , -and copies the resulting absolute pathname into -the memory pointed to by -.Fa resolved_path . -The -.Fa resolved_path -argument -.Em must -point to a buffer capable of storing at least -.Dv PATH_MAX -characters, or be -.Dv NULL . -.Pp -The -.Fn realpath -function will resolve both absolute and relative paths -and return the absolute pathname corresponding to -.Fa pathname . -All but the last component of -.Fa pathname -must exist when -.Fn realpath -is called. -.Sh "RETURN VALUES" -The -.Fn realpath -function returns -.Fa resolved_path -on success. -If the function was supplied -.Dv NULL -as -.Fa resolved_path , -and operation did not cause errors, the returned value is -a null-terminated string in a buffer allocated by a call to -.Fn malloc 3 . -If an error occurs, -.Fn realpath -returns -.Dv NULL , -and if -.Fa resolved_path -is not -.Dv NULL , -the array that it points to contains the pathname which caused the problem. -.Sh ERRORS -The function -.Fn realpath -may fail and set the external variable -.Va errno -for any of the errors specified for the library functions -.Xr lstat 2 , -.Xr readlink 2 -and -.Xr getcwd 3 . -.Sh SEE ALSO -.Xr getcwd 3 -.\" .Sh STANDARDS -.\" The -.\" .Fn realpath -.\" function conforms to -.\" .St -p1003.1-2001 . -.Sh HISTORY -The -.Fn realpath -function first appeared in -.Bx 4.4 . -.Sh CAVEATS -This implementation of -.Fn realpath -differs slightly from the Solaris implementation. -The -.Bx 4.4 -version always returns absolute pathnames, -whereas the Solaris implementation will, -under certain circumstances, return a relative -.Fa resolved_path -when given a relative -.Fa pathname . diff --git a/lib/libc/stdlib/realpath.c b/lib/libc/stdlib/realpath.c deleted file mode 100644 index e75ee4a..0000000 --- a/lib/libc/stdlib/realpath.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (c) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the authors may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)realpath.c 8.1 (Berkeley) 2/16/94"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include "namespace.h" -#include <sys/param.h> -#include <sys/stat.h> - -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include "un-namespace.h" - -/* - * Find the real name of path, by removing all ".", ".." and symlink - * components. Returns (resolved) on success, or (NULL) on failure, - * in which case the path which caused trouble is left in (resolved). - */ -char * -realpath(const char * __restrict path, char * __restrict resolved) -{ - struct stat sb; - char *p, *q, *s; - size_t left_len, resolved_len; - unsigned symlinks; - int serrno, slen, m; - char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX]; - - if (path == NULL) { - errno = EINVAL; - return (NULL); - } - if (path[0] == '\0') { - errno = ENOENT; - return (NULL); - } - serrno = errno; - if (resolved == NULL) { - resolved = malloc(PATH_MAX); - if (resolved == NULL) - return (NULL); - m = 1; - } else - m = 0; - - symlinks = 0; - if (path[0] == '/') { - resolved[0] = '/'; - resolved[1] = '\0'; - if (path[1] == '\0') - return (resolved); - resolved_len = 1; - left_len = strlcpy(left, path + 1, sizeof(left)); - } else { - if (getcwd(resolved, PATH_MAX) == NULL) { - if (m) - free(resolved); - else - strlcpy(resolved, ".", PATH_MAX); - return (NULL); - } - resolved_len = strlen(resolved); - left_len = strlcpy(left, path, sizeof(left)); - } - if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) { - if (m) - free(resolved); - errno = ENAMETOOLONG; - return (NULL); - } - - /* - * Iterate over path components in `left'. - */ - while (left_len != 0) { - /* - * Extract the next path component and adjust `left' - * and its length. - */ - p = strchr(left, '/'); - s = p ? p : left + left_len; - if (s - left >= sizeof(next_token)) { - if (m) - free(resolved); - errno = ENAMETOOLONG; - return (NULL); - } - memcpy(next_token, left, s - left); - next_token[s - left] = '\0'; - left_len -= s - left; - if (p != NULL) - memmove(left, s + 1, left_len + 1); - if (resolved[resolved_len - 1] != '/') { - if (resolved_len + 1 >= PATH_MAX) { - if (m) - free(resolved); - errno = ENAMETOOLONG; - return (NULL); - } - resolved[resolved_len++] = '/'; - resolved[resolved_len] = '\0'; - } - if (next_token[0] == '\0') - continue; - else if (strcmp(next_token, ".") == 0) - continue; - else if (strcmp(next_token, "..") == 0) { - /* - * Strip the last path component except when we have - * single "/" - */ - if (resolved_len > 1) { - resolved[resolved_len - 1] = '\0'; - q = strrchr(resolved, '/') + 1; - *q = '\0'; - resolved_len = q - resolved; - } - continue; - } - - /* - * Append the next path component and lstat() it. If - * lstat() fails we still can return successfully if - * there are no more path components left. - */ - resolved_len = strlcat(resolved, next_token, PATH_MAX); - if (resolved_len >= PATH_MAX) { - if (m) - free(resolved); - errno = ENAMETOOLONG; - return (NULL); - } - if (lstat(resolved, &sb) != 0) { - if (errno == ENOENT && p == NULL) { - errno = serrno; - return (resolved); - } - if (m) - free(resolved); - return (NULL); - } - if (S_ISLNK(sb.st_mode)) { - if (symlinks++ > MAXSYMLINKS) { - if (m) - free(resolved); - errno = ELOOP; - return (NULL); - } - slen = readlink(resolved, symlink, sizeof(symlink) - 1); - if (slen < 0) { - if (m) - free(resolved); - return (NULL); - } - symlink[slen] = '\0'; - if (symlink[0] == '/') { - resolved[1] = 0; - resolved_len = 1; - } else if (resolved_len > 1) { - /* Strip the last path component. */ - resolved[resolved_len - 1] = '\0'; - q = strrchr(resolved, '/') + 1; - *q = '\0'; - resolved_len = q - resolved; - } - - /* - * If there are any path components left, then - * append them to symlink. The result is placed - * in `left'. - */ - if (p != NULL) { - if (symlink[slen - 1] != '/') { - if (slen + 1 >= sizeof(symlink)) { - if (m) - free(resolved); - errno = ENAMETOOLONG; - return (NULL); - } - symlink[slen] = '/'; - symlink[slen + 1] = 0; - } - left_len = strlcat(symlink, left, sizeof(left)); - if (left_len >= sizeof(left)) { - if (m) - free(resolved); - errno = ENAMETOOLONG; - return (NULL); - } - } - left_len = strlcpy(left, symlink, sizeof(left)); - } - } - - /* - * Remove trailing slash except when the resolved pathname - * is a single "/". - */ - if (resolved_len > 1 && resolved[resolved_len - 1] == '/') - resolved[resolved_len - 1] = '\0'; - return (resolved); -} diff --git a/lib/libc/stdlib/remque.c b/lib/libc/stdlib/remque.c deleted file mode 100644 index 0a2f28f..0000000 --- a/lib/libc/stdlib/remque.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Initial implementation: - * Copyright (c) 2002 Robert Drehmel - * All rights reserved. - * - * As long as the above copyright statement and this notice remain - * unchanged, you can do what ever you want with this file. - */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#define _SEARCH_PRIVATE -#include <search.h> -#include <stdlib.h> /* for NULL */ - -void -remque(void *element) -{ - struct que_elem *prev, *next, *elem; - - elem = (struct que_elem *)element; - - prev = elem->prev; - next = elem->next; - - if (prev != NULL) - prev->next = next; - if (next != NULL) - next->prev = prev; -} diff --git a/lib/libc/stdlib/strfmon.3 b/lib/libc/stdlib/strfmon.3 deleted file mode 100644 index 11b8e21..0000000 --- a/lib/libc/stdlib/strfmon.3 +++ /dev/null @@ -1,167 +0,0 @@ -.\" Copyright (c) 2001 Jeroen Ruigrok van der Werven <asmodai@FreeBSD.org> -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $FreeBSD$ -.\" -.Dd October 12, 2002 -.Dt STRFMON 3 -.Os -.Sh NAME -.Nm strfmon -.Nd convert monetary value to string -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In monetary.h -.Ft ssize_t -.Fn strfmon "char * restrict s" "size_t maxsize" "const char * restrict format" "..." -.Sh DESCRIPTION -The -.Fn strfmon -function places characters into the array pointed to by -.Fa s -as controlled by the string pointed to by -.Fa format . -No more than -.Fa maxsize -bytes are placed into the array. -.Pp -The format string is composed of zero or more directives: -ordinary characters (not -.Cm % ) , -which are copied unchanged to the output stream; and conversion -specifications, each of which results in fetching zero or more subsequent -arguments. -Each conversion specification is introduced by the -.Cm % -character. -After the -.Cm % , -the following appear in sequence: -.Bl -bullet -.It -Zero or more of the following flags: -.Bl -tag -width "XXX" -.It Cm = Ns Ar f -A -.Sq Cm = -character followed by another character -.Ar f -which is used as the numeric fill character. -.It Cm ^ -Do not use grouping characters, regardless of the current locale default. -.It Cm + -Represent positive values by prefixing them with a positive sign, -and negative values by prefixing them with a negative sign. -This is the default. -.It Cm \&( -Enclose negative values in parentheses. -.It Cm \&! -Do not include a currency symbol in the output. -.It Cm \- -Left justify the result. -Only valid when a field width is specified. -.El -.It -An optional minimum field width as a decimal number. -By default, there is no minimum width. -.It -A -.Sq Cm # -sign followed by a decimal number specifying the maximum -expected number of digits after the radix character. -.It -A -.Sq Cm \&. -character followed by a decimal number specifying the number -the number of digits after the radix character. -.It -One of the following conversion specifiers: -.Bl -tag -width "XXX" -.It Cm i -The -.Vt double -argument is formatted as an international monetary amount. -.It Cm n -The -.Vt double -argument is formatted as a national monetary amount. -.It Cm % -A -.Sq Li % -character is written. -.El -.El -.Sh RETURN VALUES -If the total number of resulting bytes including the terminating -.Dv NULL -byte is not more than -.Fa maxsize , -.Fn strfmon -returns the number of bytes placed into the array pointed to by -.Fa s , -not including the terminating -.Dv NULL -byte. -Otherwise, \-1 is returned, -the contents of the array are indeterminate, -and -.Va errno -is set to indicate the error. -.Sh ERRORS -The -.Fn strfmon -function will fail if: -.Bl -tag -width Er -.It Bq Er E2BIG -Conversion stopped due to lack of space in the buffer. -.It Bq Er EINVAL -The format string is invalid. -.It Bq Er ENOMEM -Not enough memory for temporary buffers. -.El -.Sh SEE ALSO -.Xr localeconv 3 -.Sh STANDARDS -The -.Fn strfmon -function -conforms to -.St -p1003.1-2001 . -.Sh AUTHORS -.An -nosplit -The -.Fn strfmon -function was implemented by -.An Alexey Zelkin Aq phantom@FreeBSD.org . -.Pp -This manual page was written by -.An Jeroen Ruigrok van der Werven Aq asmodai@FreeBSD.org -based on the standards' text. -.Sh BUGS -The -.Fn strfmon -function does not correctly handle multibyte characters in the -.Fa format -argument. diff --git a/lib/libc/stdlib/strfmon.c b/lib/libc/stdlib/strfmon.c deleted file mode 100644 index 6c28254..0000000 --- a/lib/libc/stdlib/strfmon.c +++ /dev/null @@ -1,616 +0,0 @@ -/*- - * Copyright (c) 2001 Alexey Zelkin <phantom@FreeBSD.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/types.h> -#include <ctype.h> -#include <errno.h> -#include <limits.h> -#include <locale.h> -#include <monetary.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -/* internal flags */ -#define NEED_GROUPING 0x01 /* print digits grouped (default) */ -#define SIGN_POSN_USED 0x02 /* '+' or '(' usage flag */ -#define LOCALE_POSN 0x04 /* use locale defined +/- (default) */ -#define PARENTH_POSN 0x08 /* enclose negative amount in () */ -#define SUPRESS_CURR_SYMBOL 0x10 /* supress the currency from output */ -#define LEFT_JUSTIFY 0x20 /* left justify */ -#define USE_INTL_CURRENCY 0x40 /* use international currency symbol */ -#define IS_NEGATIVE 0x80 /* is argument value negative ? */ - -/* internal macros */ -#define PRINT(CH) do { \ - if (dst >= s + maxsize) \ - goto e2big_error; \ - *dst++ = CH; \ -} while (0) - -#define PRINTS(STR) do { \ - char *tmps = STR; \ - while (*tmps != '\0') \ - PRINT(*tmps++); \ -} while (0) - -#define GET_NUMBER(VAR) do { \ - VAR = 0; \ - while (isdigit((unsigned char)*fmt)) { \ - if (VAR > INT_MAX / 10) \ - goto e2big_error; \ - VAR *= 10; \ - VAR += *fmt - '0'; \ - if (VAR < 0) \ - goto e2big_error; \ - fmt++; \ - } \ -} while (0) - -#define GRPCPY(howmany) do { \ - int i = howmany; \ - while (i-- > 0) { \ - avalue_size--; \ - *--bufend = *(avalue+avalue_size+padded); \ - } \ -} while (0) - -#define GRPSEP do { \ - *--bufend = thousands_sep; \ - groups++; \ -} while (0) - -static void __setup_vars(int, char *, char *, char *, char **); -static int __calc_left_pad(int, char *); -static char *__format_grouped_double(double, int *, int, int, int); - -ssize_t -strfmon(char * __restrict s, size_t maxsize, const char * __restrict format, - ...) -{ - va_list ap; - char *dst; /* output destination pointer */ - const char *fmt; /* current format poistion pointer */ - struct lconv *lc; /* pointer to lconv structure */ - char *asciivalue; /* formatted double pointer */ - - int flags; /* formatting options */ - int pad_char; /* padding character */ - int pad_size; /* pad size */ - int width; /* field width */ - int left_prec; /* left precision */ - int right_prec; /* right precision */ - double value; /* just value */ - char space_char = ' '; /* space after currency */ - - char cs_precedes, /* values gathered from struct lconv */ - sep_by_space, - sign_posn, - *signstr, - *currency_symbol; - - char *tmpptr; /* temporary vars */ - int sverrno; - - va_start(ap, format); - - lc = localeconv(); - dst = s; - fmt = format; - asciivalue = NULL; - currency_symbol = NULL; - pad_size = 0; - - while (*fmt) { - /* pass nonformating characters AS IS */ - if (*fmt != '%') - goto literal; - - /* '%' found ! */ - - /* "%%" mean just '%' */ - if (*(fmt+1) == '%') { - fmt++; - literal: - PRINT(*fmt++); - continue; - } - - /* set up initial values */ - flags = (NEED_GROUPING|LOCALE_POSN); - pad_char = ' '; /* padding character is "space" */ - left_prec = -1; /* no left precision specified */ - right_prec = -1; /* no right precision specified */ - width = -1; /* no width specified */ - value = 0; /* we have no value to print now */ - - /* Flags */ - while (1) { - switch (*++fmt) { - case '=': /* fill character */ - pad_char = *++fmt; - if (pad_char == '\0') - goto format_error; - continue; - case '^': /* not group currency */ - flags &= ~(NEED_GROUPING); - continue; - case '+': /* use locale defined signs */ - if (flags & SIGN_POSN_USED) - goto format_error; - flags |= (SIGN_POSN_USED|LOCALE_POSN); - continue; - case '(': /* enclose negatives with () */ - if (flags & SIGN_POSN_USED) - goto format_error; - flags |= (SIGN_POSN_USED|PARENTH_POSN); - continue; - case '!': /* suppress currency symbol */ - flags |= SUPRESS_CURR_SYMBOL; - continue; - case '-': /* alignment (left) */ - flags |= LEFT_JUSTIFY; - continue; - default: - break; - } - break; - } - - /* field Width */ - if (isdigit((unsigned char)*fmt)) { - GET_NUMBER(width); - /* Do we have enough space to put number with - * required width ? - */ - if ((unsigned int)width >= maxsize - (dst - s)) - goto e2big_error; - } - - /* Left precision */ - if (*fmt == '#') { - if (!isdigit((unsigned char)*++fmt)) - goto format_error; - GET_NUMBER(left_prec); - if ((unsigned int)left_prec >= maxsize - (dst - s)) - goto e2big_error; - } - - /* Right precision */ - if (*fmt == '.') { - if (!isdigit((unsigned char)*++fmt)) - goto format_error; - GET_NUMBER(right_prec); - if ((unsigned int)right_prec >= maxsize - (dst - s) - - left_prec) - goto e2big_error; - } - - /* Conversion Characters */ - switch (*fmt++) { - case 'i': /* use internaltion currency format */ - flags |= USE_INTL_CURRENCY; - break; - case 'n': /* use national currency format */ - flags &= ~(USE_INTL_CURRENCY); - break; - default: /* required character is missing or - premature EOS */ - goto format_error; - } - - if (currency_symbol != NULL) - free(currency_symbol); - if (flags & USE_INTL_CURRENCY) { - currency_symbol = strdup(lc->int_curr_symbol); - if (currency_symbol != NULL) - space_char = *(currency_symbol+3); - } else - currency_symbol = strdup(lc->currency_symbol); - - if (currency_symbol == NULL) - goto end_error; /* ENOMEM. */ - - /* value itself */ - value = va_arg(ap, double); - - /* detect sign */ - if (value < 0) { - flags |= IS_NEGATIVE; - value = -value; - } - - /* fill left_prec with amount of padding chars */ - if (left_prec >= 0) { - pad_size = __calc_left_pad((flags ^ IS_NEGATIVE), - currency_symbol) - - __calc_left_pad(flags, currency_symbol); - if (pad_size < 0) - pad_size = 0; - } - - if (asciivalue != NULL) - free(asciivalue); - asciivalue = __format_grouped_double(value, &flags, - left_prec, right_prec, pad_char); - if (asciivalue == NULL) - goto end_error; /* errno already set */ - /* to ENOMEM by malloc() */ - - /* set some variables for later use */ - __setup_vars(flags, &cs_precedes, &sep_by_space, - &sign_posn, &signstr); - - /* - * Description of some LC_MONETARY's values: - * - * p_cs_precedes & n_cs_precedes - * - * = 1 - $currency_symbol precedes the value - * for a monetary quantity with a non-negative value - * = 0 - symbol succeeds the value - * - * p_sep_by_space & n_sep_by_space - * - * = 0 - no space separates $currency_symbol - * from the value for a monetary quantity with a - * non-negative value - * = 1 - space separates the symbol from the value - * = 2 - space separates the symbol and the sign string, - * if adjacent. - * - * p_sign_posn & n_sign_posn - * - * = 0 - parentheses enclose the quantity and the - * $currency_symbol - * = 1 - the sign string precedes the quantity and the - * $currency_symbol - * = 2 - the sign string succeeds the quantity and the - * $currency_symbol - * = 3 - the sign string precedes the $currency_symbol - * = 4 - the sign string succeeds the $currency_symbol - * - */ - - tmpptr = dst; - - while (pad_size-- > 0) - PRINT(' '); - - if (sign_posn == 0 && (flags & IS_NEGATIVE)) - PRINT('('); - - if (cs_precedes == 1) { - if (sign_posn == 1 || sign_posn == 3) { - PRINTS(signstr); - if (sep_by_space == 2) /* XXX: ? */ - PRINT(' '); - } - - if (!(flags & SUPRESS_CURR_SYMBOL)) { - PRINTS(currency_symbol); - - if (sign_posn == 4) { - if (sep_by_space == 2) - PRINT(space_char); - PRINTS(signstr); - if (sep_by_space == 1) - PRINT(' '); - } else if (sep_by_space == 1) - PRINT(space_char); - } - } else if (sign_posn == 1) - PRINTS(signstr); - - PRINTS(asciivalue); - - if (cs_precedes == 0) { - if (sign_posn == 3) { - if (sep_by_space == 1) - PRINT(' '); - PRINTS(signstr); - } - - if (!(flags & SUPRESS_CURR_SYMBOL)) { - if ((sign_posn == 3 && sep_by_space == 2) - || (sep_by_space == 1 - && (sign_posn == 0 - || sign_posn == 1 - || sign_posn == 2 - || sign_posn == 4))) - PRINT(space_char); - PRINTS(currency_symbol); /* XXX: len */ - if (sign_posn == 4) { - if (sep_by_space == 2) - PRINT(' '); - PRINTS(signstr); - } - } - } - - if (sign_posn == 2) { - if (sep_by_space == 2) - PRINT(' '); - PRINTS(signstr); - } - - if (sign_posn == 0 && (flags & IS_NEGATIVE)) - PRINT(')'); - - if (dst - tmpptr < width) { - if (flags & LEFT_JUSTIFY) { - while (dst - tmpptr < width) - PRINT(' '); - } else { - pad_size = dst-tmpptr; - memmove(tmpptr + width-pad_size, tmpptr, - pad_size); - memset(tmpptr, ' ', width-pad_size); - dst += width-pad_size; - } - } - } - - PRINT('\0'); - va_end(ap); - free(asciivalue); - free(currency_symbol); - return (dst - s - 1); /* return size of put data except trailing '\0' */ - -e2big_error: - errno = E2BIG; - goto end_error; - -format_error: - errno = EINVAL; - -end_error: - sverrno = errno; - if (asciivalue != NULL) - free(asciivalue); - if (currency_symbol != NULL) - free(currency_symbol); - errno = sverrno; - va_end(ap); - return (-1); -} - -static void -__setup_vars(int flags, char *cs_precedes, char *sep_by_space, - char *sign_posn, char **signstr) { - - struct lconv *lc = localeconv(); - - if ((flags & IS_NEGATIVE) && (flags & USE_INTL_CURRENCY)) { - *cs_precedes = lc->int_n_cs_precedes; - *sep_by_space = lc->int_n_sep_by_space; - *sign_posn = (flags & PARENTH_POSN) ? 0 : lc->int_n_sign_posn; - *signstr = (lc->negative_sign[0] == '\0') ? "-" - : lc->negative_sign; - } else if (flags & USE_INTL_CURRENCY) { - *cs_precedes = lc->int_p_cs_precedes; - *sep_by_space = lc->int_p_sep_by_space; - *sign_posn = (flags & PARENTH_POSN) ? 0 : lc->int_p_sign_posn; - *signstr = lc->positive_sign; - } else if (flags & IS_NEGATIVE) { - *cs_precedes = lc->n_cs_precedes; - *sep_by_space = lc->n_sep_by_space; - *sign_posn = (flags & PARENTH_POSN) ? 0 : lc->n_sign_posn; - *signstr = (lc->negative_sign[0] == '\0') ? "-" - : lc->negative_sign; - } else { - *cs_precedes = lc->p_cs_precedes; - *sep_by_space = lc->p_sep_by_space; - *sign_posn = (flags & PARENTH_POSN) ? 0 : lc->p_sign_posn; - *signstr = lc->positive_sign; - } - - /* Set defult values for unspecified information. */ - if (*cs_precedes != 0) - *cs_precedes = 1; - if (*sep_by_space == CHAR_MAX) - *sep_by_space = 0; - if (*sign_posn == CHAR_MAX) - *sign_posn = 0; -} - -static int -__calc_left_pad(int flags, char *cur_symb) { - - char cs_precedes, sep_by_space, sign_posn, *signstr; - int left_chars = 0; - - __setup_vars(flags, &cs_precedes, &sep_by_space, &sign_posn, &signstr); - - if (cs_precedes != 0) { - left_chars += strlen(cur_symb); - if (sep_by_space != 0) - left_chars++; - } - - switch (sign_posn) { - case 1: - left_chars += strlen(signstr); - break; - case 3: - case 4: - if (cs_precedes != 0) - left_chars += strlen(signstr); - } - return (left_chars); -} - -static int -get_groups(int size, char *grouping) { - - int chars = 0; - - if (*grouping == CHAR_MAX || *grouping <= 0) /* no grouping ? */ - return (0); - - while (size > (int)*grouping) { - chars++; - size -= (int)*grouping++; - /* no more grouping ? */ - if (*grouping == CHAR_MAX) - break; - /* rest grouping with same value ? */ - if (*grouping == 0) { - chars += (size - 1) / *(grouping - 1); - break; - } - } - return (chars); -} - -/* convert double to ASCII */ -static char * -__format_grouped_double(double value, int *flags, - int left_prec, int right_prec, int pad_char) { - - char *rslt; - char *avalue; - int avalue_size; - char fmt[32]; - - size_t bufsize; - char *bufend; - - int padded; - - struct lconv *lc = localeconv(); - char *grouping; - char decimal_point; - char thousands_sep; - - int groups = 0; - - grouping = lc->mon_grouping; - decimal_point = *lc->mon_decimal_point; - if (decimal_point == '\0') - decimal_point = *lc->decimal_point; - thousands_sep = *lc->mon_thousands_sep; - if (thousands_sep == '\0') - thousands_sep = *lc->thousands_sep; - - /* fill left_prec with default value */ - if (left_prec == -1) - left_prec = 0; - - /* fill right_prec with default value */ - if (right_prec == -1) { - if (*flags & USE_INTL_CURRENCY) - right_prec = lc->int_frac_digits; - else - right_prec = lc->frac_digits; - - if (right_prec == CHAR_MAX) /* POSIX locale ? */ - right_prec = 2; - } - - if (*flags & NEED_GROUPING) - left_prec += get_groups(left_prec, grouping); - - /* convert to string */ - snprintf(fmt, sizeof(fmt), "%%%d.%df", left_prec + right_prec + 1, - right_prec); - avalue_size = asprintf(&avalue, fmt, value); - if (avalue_size < 0) - return (NULL); - - /* make sure that we've enough space for result string */ - bufsize = strlen(avalue)*2+1; - rslt = calloc(1, bufsize); - if (rslt == NULL) { - free(avalue); - return (NULL); - } - bufend = rslt + bufsize - 1; /* reserve space for trailing '\0' */ - - /* skip spaces at beggining */ - padded = 0; - while (avalue[padded] == ' ') { - padded++; - avalue_size--; - } - - if (right_prec > 0) { - bufend -= right_prec; - memcpy(bufend, avalue + avalue_size+padded-right_prec, - right_prec); - *--bufend = decimal_point; - avalue_size -= (right_prec + 1); - } - - if ((*flags & NEED_GROUPING) && - thousands_sep != '\0' && /* XXX: need investigation */ - *grouping != CHAR_MAX && - *grouping > 0) { - while (avalue_size > (int)*grouping) { - GRPCPY(*grouping); - GRPSEP; - grouping++; - - /* no more grouping ? */ - if (*grouping == CHAR_MAX) - break; - - /* rest grouping with same value ? */ - if (*grouping == 0) { - grouping--; - while (avalue_size > *grouping) { - GRPCPY(*grouping); - GRPSEP; - } - } - } - if (avalue_size != 0) - GRPCPY(avalue_size); - padded -= groups; - - } else { - bufend -= avalue_size; - memcpy(bufend, avalue+padded, avalue_size); - if (right_prec == 0) - padded--; /* decrease assumed $decimal_point */ - } - - /* do padding with pad_char */ - if (padded > 0) { - bufend -= padded; - memset(bufend, pad_char, padded); - } - - bufsize = bufsize - (bufend - rslt) + 1; - memmove(rslt, bufend, bufsize); - free(avalue); - return (rslt); -} diff --git a/lib/libc/stdlib/strtod.3 b/lib/libc/stdlib/strtod.3 deleted file mode 100644 index e19e5fe..0000000 --- a/lib/libc/stdlib/strtod.3 +++ /dev/null @@ -1,198 +0,0 @@ -.\" Copyright (c) 1990, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the American National Standards Committee X3, on Information -.\" Processing Systems. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)strtod.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD$ -.\" -.Dd May 11, 2010 -.Dt STRTOD 3 -.Os -.Sh NAME -.Nm strtod , strtof , strtold -.Nd convert -.Tn ASCII -string to floating point -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In stdlib.h -.Ft double -.Fn strtod "const char * restrict nptr" "char ** restrict endptr" -.Ft float -.Fn strtof "const char * restrict nptr" "char ** restrict endptr" -.Ft "long double" -.Fn strtold "const char * restrict nptr" "char ** restrict endptr" -.Sh DESCRIPTION -These conversion -functions convert the initial portion of the string -pointed to by -.Fa nptr -to -.Vt double , -.Vt float , -and -.Vt "long double" -representation, respectively. -.Pp -The expected form of the string is an optional plus (``+'') or minus -sign (``\-'') followed by either: -.Bl -bullet -.It -a decimal significand consisting of a sequence of decimal digits -optionally containing a decimal-point character, or -.It -a hexadecimal significand consisting of a ``0X'' or ``0x'' followed -by a sequence of hexadecimal digits optionally containing a -decimal-point character. -.El -.Pp -In both cases, the significand may be optionally followed by an -exponent. -An exponent consists of an ``E'' or ``e'' (for decimal -constants) or a ``P'' or ``p'' (for hexadecimal constants), -followed by an optional plus or minus sign, followed by a -sequence of decimal digits. -For decimal constants, the exponent indicates the power of 10 by -which the significand should be scaled. -For hexadecimal constants, the scaling is instead done by powers -of 2. -.Pp -Alternatively, if the portion of the string following the optional -plus or minus sign begins with -.Dq INFINITY -or -.Dq NAN , -ignoring case, it is interpreted as an infinity or a quiet \*(Na, -respectively. -The syntax -.Dq Xo Pf NAN( Ar "s" ) Xc , -where -.Ar s -is an alphanumeric string, produces the same value as the call -.Fo nan -.Qq Ar s Ns -.Fc -(respectively, -.Fo nanf -.Qq Ar s Ns -.Fc -and -.Fo nanl -.Qq Ar s Ns -.Fc . ) -.Pp -In any of the above cases, leading white-space characters in the -string (as defined by the -.Xr isspace 3 -function) are skipped. -The decimal point -character is defined in the program's locale (category -.Dv LC_NUMERIC ) . -.Sh RETURN VALUES -The -.Fn strtod , -.Fn strtof , -and -.Fn strtold -functions return the converted value, if any. -.Pp -If -.Fa endptr -is not -.Dv NULL , -a pointer to the character after the last character used -in the conversion is stored in the location referenced by -.Fa endptr . -.Pp -If no conversion is performed, zero is returned and the value of -.Fa nptr -is stored in the location referenced by -.Fa endptr . -.Pp -If the correct value would cause overflow, plus or minus -.Dv HUGE_VAL , -.Dv HUGE_VALF , -or -.Dv HUGE_VALL -is returned (according to the sign and type of the return value), and -.Er ERANGE -is stored in -.Va errno . -If the correct value would cause underflow, zero is -returned and -.Er ERANGE -is stored in -.Va errno . -.Sh ERRORS -.Bl -tag -width Er -.It Bq Er ERANGE -Overflow or underflow occurred. -.El -.Sh SEE ALSO -.Xr atof 3 , -.Xr atoi 3 , -.Xr atol 3 , -.Xr nan 3 , -.Xr strtol 3 , -.Xr strtoul 3 , -.Xr wcstod 3 -.Sh STANDARDS -The -.Fn strtod -function -conforms to -.St -isoC-99 . -.Sh AUTHORS -The author of this software is -.An David M. Gay . -.Bd -literal -Copyright (c) 1998 by Lucent Technologies -All Rights Reserved - -Permission to use, copy, modify, and distribute this software and -its documentation for any purpose and without fee is hereby -granted, provided that the above copyright notice appear in all -copies and that both that the copyright notice and this -permission notice and warranty disclaimer appear in supporting -documentation, and that the name of Lucent or any of its entities -not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, -INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. -IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY -SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER -IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. -.Ed diff --git a/lib/libc/stdlib/strtoimax.c b/lib/libc/stdlib/strtoimax.c deleted file mode 100644 index 4f0063c..0000000 --- a/lib/libc/stdlib/strtoimax.c +++ /dev/null @@ -1,140 +0,0 @@ -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "from @(#)strtol.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <ctype.h> -#include <errno.h> -#include <stdlib.h> -#include <inttypes.h> - -/* - * Convert a string to an intmax_t integer. - * - * Assumes that the upper and lower case - * alphabets and digits are each contiguous. - */ -intmax_t -strtoimax(const char * __restrict nptr, char ** __restrict endptr, int base) -{ - const char *s; - uintmax_t acc; - char c; - uintmax_t cutoff; - int neg, any, cutlim; - - /* - * Skip white space and pick up leading +/- sign if any. - * If base is 0, allow 0x for hex and 0 for octal, else - * assume decimal; if base is already 16, allow 0x. - */ - s = nptr; - do { - c = *s++; - } while (isspace((unsigned char)c)); - if (c == '-') { - neg = 1; - c = *s++; - } else { - neg = 0; - if (c == '+') - c = *s++; - } - if ((base == 0 || base == 16) && - c == '0' && (*s == 'x' || *s == 'X') && - ((s[1] >= '0' && s[1] <= '9') || - (s[1] >= 'A' && s[1] <= 'F') || - (s[1] >= 'a' && s[1] <= 'f'))) { - c = s[1]; - s += 2; - base = 16; - } - if (base == 0) - base = c == '0' ? 8 : 10; - acc = any = 0; - if (base < 2 || base > 36) - goto noconv; - - /* - * Compute the cutoff value between legal numbers and illegal - * numbers. That is the largest legal value, divided by the - * base. An input number that is greater than this value, if - * followed by a legal input character, is too big. One that - * is equal to this value may be valid or not; the limit - * between valid and invalid numbers is then based on the last - * digit. For instance, if the range for intmax_t is - * [-9223372036854775808..9223372036854775807] and the input base - * is 10, cutoff will be set to 922337203685477580 and cutlim to - * either 7 (neg==0) or 8 (neg==1), meaning that if we have - * accumulated a value > 922337203685477580, or equal but the - * next digit is > 7 (or 8), the number is too big, and we will - * return a range error. - * - * Set 'any' if any `digits' consumed; make it negative to indicate - * overflow. - */ - cutoff = neg ? (uintmax_t)-(INTMAX_MIN + INTMAX_MAX) + INTMAX_MAX - : INTMAX_MAX; - cutlim = cutoff % base; - cutoff /= base; - for ( ; ; c = *s++) { - if (c >= '0' && c <= '9') - c -= '0'; - else if (c >= 'A' && c <= 'Z') - c -= 'A' - 10; - else if (c >= 'a' && c <= 'z') - c -= 'a' - 10; - else - break; - if (c >= base) - break; - if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) - any = -1; - else { - any = 1; - acc *= base; - acc += c; - } - } - if (any < 0) { - acc = neg ? INTMAX_MIN : INTMAX_MAX; - errno = ERANGE; - } else if (!any) { -noconv: - errno = EINVAL; - } else if (neg) - acc = -acc; - if (endptr != NULL) - *endptr = (char *)(any ? s - 1 : nptr); - return (acc); -} diff --git a/lib/libc/stdlib/strtol.3 b/lib/libc/stdlib/strtol.3 deleted file mode 100644 index 02316f5..0000000 --- a/lib/libc/stdlib/strtol.3 +++ /dev/null @@ -1,222 +0,0 @@ -.\" Copyright (c) 1990, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" Chris Torek and the American National Standards Committee X3, -.\" on Information Processing Systems. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)strtol.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD$ -.\" -.Dd November 28, 2001 -.Dt STRTOL 3 -.Os -.Sh NAME -.Nm strtol , strtoll , strtoimax , strtoq -.Nd "convert a string value to a" -.Vt long , "long long" , intmax_t -or -.Vt quad_t -integer -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In stdlib.h -.In limits.h -.Ft long -.Fn strtol "const char * restrict nptr" "char ** restrict endptr" "int base" -.Ft long long -.Fn strtoll "const char * restrict nptr" "char ** restrict endptr" "int base" -.In inttypes.h -.Ft intmax_t -.Fn strtoimax "const char * restrict nptr" "char ** restrict endptr" "int base" -.In sys/types.h -.In stdlib.h -.In limits.h -.Ft quad_t -.Fn strtoq "const char *nptr" "char **endptr" "int base" -.Sh DESCRIPTION -The -.Fn strtol -function -converts the string in -.Fa nptr -to a -.Vt long -value. -The -.Fn strtoll -function -converts the string in -.Fa nptr -to a -.Vt "long long" -value. -The -.Fn strtoimax -function -converts the string in -.Fa nptr -to an -.Vt intmax_t -value. -The -.Fn strtoq -function -converts the string in -.Fa nptr -to a -.Vt quad_t -value. -The conversion is done according to the given -.Fa base , -which must be between 2 and 36 inclusive, -or be the special value 0. -.Pp -The string may begin with an arbitrary amount of white space -(as determined by -.Xr isspace 3 ) -followed by a single optional -.Ql + -or -.Ql - -sign. -If -.Fa base -is zero or 16, -the string may then include a -.Dq Li 0x -prefix, -and the number will be read in base 16; otherwise, a zero -.Fa base -is taken as 10 (decimal) unless the next character is -.Ql 0 , -in which case it is taken as 8 (octal). -.Pp -The remainder of the string is converted to a -.Vt long , "long long" , intmax_t -or -.Vt quad_t -value in the obvious manner, -stopping at the first character which is not a valid digit -in the given base. -(In bases above 10, the letter -.Ql A -in either upper or lower case -represents 10, -.Ql B -represents 11, and so forth, with -.Ql Z -representing 35.) -.Pp -If -.Fa endptr -is not -.Dv NULL , -.Fn strtol -stores the address of the first invalid character in -.Fa *endptr . -If there were no digits at all, however, -.Fn strtol -stores the original value of -.Fa nptr -in -.Fa *endptr . -(Thus, if -.Fa *nptr -is not -.Ql \e0 -but -.Fa **endptr -is -.Ql \e0 -on return, the entire string was valid.) -.Sh RETURN VALUES -The -.Fn strtol , -.Fn strtoll , -.Fn strtoimax -and -.Fn strtoq -functions -return the result of the conversion, -unless the value would underflow or overflow. -If no conversion could be performed, 0 is returned and -the global variable -.Va errno -is set to -.Er EINVAL -(the last feature is not portable across all platforms). -If an overflow or underflow occurs, -.Va errno -is set to -.Er ERANGE -and the function return value is clamped according -to the following table. -.Bl -column -offset indent ".Fn strtoimax" ".Sy underflow" ".Sy overflow" -.It Sy Function Ta Sy underflow Ta Sy overflow -.It Fn strtol Ta Dv LONG_MIN Ta Dv LONG_MAX -.It Fn strtoll Ta Dv LLONG_MIN Ta Dv LLONG_MAX -.It Fn strtoimax Ta Dv INTMAX_MIN Ta Dv INTMAX_MAX -.It Fn strtoq Ta Dv LLONG_MIN Ta Dv LLONG_MAX -.El -.Sh ERRORS -.Bl -tag -width Er -.It Bq Er EINVAL -The value of -.Fa base -is not supported or -no conversion could be performed -(the last feature is not portable across all platforms). -.It Bq Er ERANGE -The given string was out of range; the value converted has been clamped. -.El -.Sh SEE ALSO -.Xr atof 3 , -.Xr atoi 3 , -.Xr atol 3 , -.Xr strtod 3 , -.Xr strtonum 3 , -.Xr strtoul 3 , -.Xr wcstol 3 -.Sh STANDARDS -The -.Fn strtol -function -conforms to -.St -isoC . -The -.Fn strtoll -and -.Fn strtoimax -functions -conform to -.St -isoC-99 . -The -.Bx -.Fn strtoq -function is deprecated. diff --git a/lib/libc/stdlib/strtol.c b/lib/libc/stdlib/strtol.c deleted file mode 100644 index 0d6f736..0000000 --- a/lib/libc/stdlib/strtol.c +++ /dev/null @@ -1,140 +0,0 @@ -/*- - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)strtol.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <limits.h> -#include <ctype.h> -#include <errno.h> -#include <stdlib.h> - - -/* - * Convert a string to a long integer. - * - * Assumes that the upper and lower case - * alphabets and digits are each contiguous. - */ -long -strtol(const char * __restrict nptr, char ** __restrict endptr, int base) -{ - const char *s; - unsigned long acc; - char c; - unsigned long cutoff; - int neg, any, cutlim; - - /* - * Skip white space and pick up leading +/- sign if any. - * If base is 0, allow 0x for hex and 0 for octal, else - * assume decimal; if base is already 16, allow 0x. - */ - s = nptr; - do { - c = *s++; - } while (isspace((unsigned char)c)); - if (c == '-') { - neg = 1; - c = *s++; - } else { - neg = 0; - if (c == '+') - c = *s++; - } - if ((base == 0 || base == 16) && - c == '0' && (*s == 'x' || *s == 'X') && - ((s[1] >= '0' && s[1] <= '9') || - (s[1] >= 'A' && s[1] <= 'F') || - (s[1] >= 'a' && s[1] <= 'f'))) { - c = s[1]; - s += 2; - base = 16; - } - if (base == 0) - base = c == '0' ? 8 : 10; - acc = any = 0; - if (base < 2 || base > 36) - goto noconv; - - /* - * Compute the cutoff value between legal numbers and illegal - * numbers. That is the largest legal value, divided by the - * base. An input number that is greater than this value, if - * followed by a legal input character, is too big. One that - * is equal to this value may be valid or not; the limit - * between valid and invalid numbers is then based on the last - * digit. For instance, if the range for longs is - * [-2147483648..2147483647] and the input base is 10, - * cutoff will be set to 214748364 and cutlim to either - * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated - * a value > 214748364, or equal but the next digit is > 7 (or 8), - * the number is too big, and we will return a range error. - * - * Set 'any' if any `digits' consumed; make it negative to indicate - * overflow. - */ - cutoff = neg ? (unsigned long)-(LONG_MIN + LONG_MAX) + LONG_MAX - : LONG_MAX; - cutlim = cutoff % base; - cutoff /= base; - for ( ; ; c = *s++) { - if (c >= '0' && c <= '9') - c -= '0'; - else if (c >= 'A' && c <= 'Z') - c -= 'A' - 10; - else if (c >= 'a' && c <= 'z') - c -= 'a' - 10; - else - break; - if (c >= base) - break; - if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) - any = -1; - else { - any = 1; - acc *= base; - acc += c; - } - } - if (any < 0) { - acc = neg ? LONG_MIN : LONG_MAX; - errno = ERANGE; - } else if (!any) { -noconv: - errno = EINVAL; - } else if (neg) - acc = -acc; - if (endptr != NULL) - *endptr = (char *)(any ? s - 1 : nptr); - return (acc); -} diff --git a/lib/libc/stdlib/strtoll.c b/lib/libc/stdlib/strtoll.c deleted file mode 100644 index 2e5547d..0000000 --- a/lib/libc/stdlib/strtoll.c +++ /dev/null @@ -1,140 +0,0 @@ -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)strtoq.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <limits.h> -#include <errno.h> -#include <ctype.h> -#include <stdlib.h> - -/* - * Convert a string to a long long integer. - * - * Assumes that the upper and lower case - * alphabets and digits are each contiguous. - */ -long long -strtoll(const char * __restrict nptr, char ** __restrict endptr, int base) -{ - const char *s; - unsigned long long acc; - char c; - unsigned long long cutoff; - int neg, any, cutlim; - - /* - * Skip white space and pick up leading +/- sign if any. - * If base is 0, allow 0x for hex and 0 for octal, else - * assume decimal; if base is already 16, allow 0x. - */ - s = nptr; - do { - c = *s++; - } while (isspace((unsigned char)c)); - if (c == '-') { - neg = 1; - c = *s++; - } else { - neg = 0; - if (c == '+') - c = *s++; - } - if ((base == 0 || base == 16) && - c == '0' && (*s == 'x' || *s == 'X') && - ((s[1] >= '0' && s[1] <= '9') || - (s[1] >= 'A' && s[1] <= 'F') || - (s[1] >= 'a' && s[1] <= 'f'))) { - c = s[1]; - s += 2; - base = 16; - } - if (base == 0) - base = c == '0' ? 8 : 10; - acc = any = 0; - if (base < 2 || base > 36) - goto noconv; - - /* - * Compute the cutoff value between legal numbers and illegal - * numbers. That is the largest legal value, divided by the - * base. An input number that is greater than this value, if - * followed by a legal input character, is too big. One that - * is equal to this value may be valid or not; the limit - * between valid and invalid numbers is then based on the last - * digit. For instance, if the range for quads is - * [-9223372036854775808..9223372036854775807] and the input base - * is 10, cutoff will be set to 922337203685477580 and cutlim to - * either 7 (neg==0) or 8 (neg==1), meaning that if we have - * accumulated a value > 922337203685477580, or equal but the - * next digit is > 7 (or 8), the number is too big, and we will - * return a range error. - * - * Set 'any' if any `digits' consumed; make it negative to indicate - * overflow. - */ - cutoff = neg ? (unsigned long long)-(LLONG_MIN + LLONG_MAX) + LLONG_MAX - : LLONG_MAX; - cutlim = cutoff % base; - cutoff /= base; - for ( ; ; c = *s++) { - if (c >= '0' && c <= '9') - c -= '0'; - else if (c >= 'A' && c <= 'Z') - c -= 'A' - 10; - else if (c >= 'a' && c <= 'z') - c -= 'a' - 10; - else - break; - if (c >= base) - break; - if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) - any = -1; - else { - any = 1; - acc *= base; - acc += c; - } - } - if (any < 0) { - acc = neg ? LLONG_MIN : LLONG_MAX; - errno = ERANGE; - } else if (!any) { -noconv: - errno = EINVAL; - } else if (neg) - acc = -acc; - if (endptr != NULL) - *endptr = (char *)(any ? s - 1 : nptr); - return (acc); -} diff --git a/lib/libc/stdlib/strtonum.3 b/lib/libc/stdlib/strtonum.3 deleted file mode 100644 index 90f0b57..0000000 --- a/lib/libc/stdlib/strtonum.3 +++ /dev/null @@ -1,156 +0,0 @@ -.\" Copyright (c) 2004 Ted Unangst -.\" -.\" Permission to use, copy, modify, and distribute this software for any -.\" purpose with or without fee is hereby granted, provided that the above -.\" copyright notice and this permission notice appear in all copies. -.\" -.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -.\" -.\" $OpenBSD: strtonum.3,v 1.12 2005/10/26 11:37:58 jmc Exp $ -.\" $FreeBSD$ -.\" -.Dd April 29, 2004 -.Dt STRTONUM 3 -.Os -.Sh NAME -.Nm strtonum -.Nd "reliably convert string value to an integer" -.Sh SYNOPSIS -.In stdlib.h -.In limits.h -.Ft long long -.Fo strtonum -.Fa "const char *nptr" -.Fa "long long minval" -.Fa "long long maxval" -.Fa "const char **errstr" -.Fc -.Sh DESCRIPTION -The -.Fn strtonum -function converts the string in -.Fa nptr -to a -.Vt "long long" -value. -The -.Fn strtonum -function was designed to facilitate safe, robust programming -and overcome the shortcomings of the -.Xr atoi 3 -and -.Xr strtol 3 -family of interfaces. -.Pp -The string may begin with an arbitrary amount of whitespace -(as determined by -.Xr isspace 3 ) -followed by a single optional -.Ql + -or -.Ql - -sign. -.Pp -The remainder of the string is converted to a -.Vt "long long" -value according to base 10. -.Pp -The value obtained is then checked against the provided -.Fa minval -and -.Fa maxval -bounds. -If -.Fa errstr -is non-null, -.Fn strtonum -stores an error string in -.Fa *errstr -indicating the failure. -.Sh RETURN VALUES -The -.Fn strtonum -function returns the result of the conversion, -unless the value would exceed the provided bounds or is invalid. -On error, 0 is returned, -.Va errno -is set, and -.Fa errstr -will point to an error message. -On success, -.Fa *errstr -will be set to -.Dv NULL ; -this fact can be used to differentiate -a successful return of 0 from an error. -.Sh EXAMPLES -Using -.Fn strtonum -correctly is meant to be simpler than the alternative functions. -.Bd -literal -offset indent -int iterations; -const char *errstr; - -iterations = strtonum(optarg, 1, 64, &errstr); -if (errstr) - errx(1, "number of iterations is %s: %s", errstr, optarg); -.Ed -.Pp -The above example will guarantee that the value of iterations is between -1 and 64 (inclusive). -.Sh ERRORS -.Bl -tag -width Er -.It Bq Er ERANGE -The given string was out of range. -.It Bq Er EINVAL -The given string did not consist solely of digit characters. -.It Bq Er EINVAL -The supplied -.Fa minval -was larger than -.Fa maxval . -.El -.Pp -If an error occurs, -.Fa errstr -will be set to one of the following strings: -.Pp -.Bl -tag -width ".Li too large" -compact -.It Li "too large" -The result was larger than the provided maximum value. -.It Li "too small" -The result was smaller than the provided minimum value. -.It Li invalid -The string did not consist solely of digit characters. -.El -.Sh SEE ALSO -.Xr atof 3 , -.Xr atoi 3 , -.Xr atol 3 , -.Xr atoll 3 , -.Xr sscanf 3 , -.Xr strtod 3 , -.Xr strtol 3 , -.Xr strtoul 3 -.Sh STANDARDS -The -.Fn strtonum -function is a -.Bx -extension. -The existing alternatives, such as -.Xr atoi 3 -and -.Xr strtol 3 , -are either impossible or difficult to use safely. -.Sh HISTORY -The -.Fn strtonum -function first appeared in -.Ox 3.6 . diff --git a/lib/libc/stdlib/strtonum.c b/lib/libc/stdlib/strtonum.c deleted file mode 100644 index 6dccd97..0000000 --- a/lib/libc/stdlib/strtonum.c +++ /dev/null @@ -1,68 +0,0 @@ -/*- - * Copyright (c) 2004 Ted Unangst and Todd Miller - * All rights reserved. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $OpenBSD: strtonum.c,v 1.6 2004/08/03 19:38:01 millert Exp $ - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <errno.h> -#include <limits.h> -#include <stdlib.h> - -#define INVALID 1 -#define TOOSMALL 2 -#define TOOLARGE 3 - -long long -strtonum(const char *numstr, long long minval, long long maxval, - const char **errstrp) -{ - long long ll = 0; - char *ep; - int error = 0; - struct errval { - const char *errstr; - int err; - } ev[4] = { - { NULL, 0 }, - { "invalid", EINVAL }, - { "too small", ERANGE }, - { "too large", ERANGE }, - }; - - ev[0].err = errno; - errno = 0; - if (minval > maxval) - error = INVALID; - else { - ll = strtoll(numstr, &ep, 10); - if (errno == EINVAL || numstr == ep || *ep != '\0') - error = INVALID; - else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval) - error = TOOSMALL; - else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval) - error = TOOLARGE; - } - if (errstrp != NULL) - *errstrp = ev[error].errstr; - errno = ev[error].err; - if (error) - ll = 0; - - return (ll); -} diff --git a/lib/libc/stdlib/strtoq.c b/lib/libc/stdlib/strtoq.c deleted file mode 100644 index afad51f..0000000 --- a/lib/libc/stdlib/strtoq.c +++ /dev/null @@ -1,48 +0,0 @@ -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)strtoq.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/types.h> - -#include <stdlib.h> - -/* - * Convert a string to a quad integer. - */ -quad_t -strtoq(const char *nptr, char **endptr, int base) -{ - - return strtoll(nptr, endptr, base); -} diff --git a/lib/libc/stdlib/strtoul.3 b/lib/libc/stdlib/strtoul.3 deleted file mode 100644 index 2c0f348..0000000 --- a/lib/libc/stdlib/strtoul.3 +++ /dev/null @@ -1,224 +0,0 @@ -.\" Copyright (c) 1990, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" Chris Torek and the American National Standards Committee X3, -.\" on Information Processing Systems. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)strtoul.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD$ -.\" -.Dd November 28, 2001 -.Dt STRTOUL 3 -.Os -.Sh NAME -.Nm strtoul , strtoull , strtoumax , strtouq -.Nd "convert a string to an" -.Vt "unsigned long" , "unsigned long long" , uintmax_t , -or -.Vt u_quad_t -integer -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In stdlib.h -.In limits.h -.Ft "unsigned long" -.Fn strtoul "const char * restrict nptr" "char ** restrict endptr" "int base" -.Ft "unsigned long long" -.Fn strtoull "const char * restrict nptr" "char ** restrict endptr" "int base" -.In inttypes.h -.Ft uintmax_t -.Fn strtoumax "const char * restrict nptr" "char ** restrict endptr" "int base" -.In sys/types.h -.In stdlib.h -.In limits.h -.Ft u_quad_t -.Fn strtouq "const char *nptr" "char **endptr" "int base" -.Sh DESCRIPTION -The -.Fn strtoul -function -converts the string in -.Fa nptr -to an -.Vt "unsigned long" -value. -The -.Fn strtoull -function -converts the string in -.Fa nptr -to an -.Vt "unsigned long long" -value. -The -.Fn strtoumax -function -converts the string in -.Fa nptr -to an -.Vt uintmax_t -value. -The -.Fn strtouq -function -converts the string in -.Fa nptr -to a -.Vt u_quad_t -value. -The conversion is done according to the given -.Fa base , -which must be between 2 and 36 inclusive, -or be the special value 0. -.Pp -The string may begin with an arbitrary amount of white space -(as determined by -.Xr isspace 3 ) -followed by a single optional -.Ql + -or -.Ql - -sign. -If -.Fa base -is zero or 16, -the string may then include a -.Dq Li 0x -prefix, -and the number will be read in base 16; otherwise, a zero -.Fa base -is taken as 10 (decimal) unless the next character is -.Ql 0 , -in which case it is taken as 8 (octal). -.Pp -The remainder of the string is converted to an -.Vt "unsigned long" -value in the obvious manner, -stopping at the end of the string -or at the first character that does not produce a valid digit -in the given base. -(In bases above 10, the letter -.Ql A -in either upper or lower case -represents 10, -.Ql B -represents 11, and so forth, with -.Ql Z -representing 35.) -.Pp -If -.Fa endptr -is not -.Dv NULL , -.Fn strtoul -stores the address of the first invalid character in -.Fa *endptr . -If there were no digits at all, however, -.Fn strtoul -stores the original value of -.Fa nptr -in -.Fa *endptr . -(Thus, if -.Fa *nptr -is not -.Ql \e0 -but -.Fa **endptr -is -.Ql \e0 -on return, the entire string was valid.) -.Sh RETURN VALUES -The -.Fn strtoul , -.Fn strtoull , -.Fn strtoumax -and -.Fn strtouq -functions -return either the result of the conversion -or, if there was a leading minus sign, -the negation of the result of the conversion, -unless the original (non-negated) value would overflow; -in the latter case, -.Fn strtoul -returns -.Dv ULONG_MAX , -.Fn strtoull -returns -.Dv ULLONG_MAX , -.Fn strtoumax -returns -.Dv UINTMAX_MAX , -and -.Fn strtouq -returns -.Dv ULLONG_MAX . -In all cases, -.Va errno -is set to -.Er ERANGE . -If no conversion could be performed, 0 is returned and -the global variable -.Va errno -is set to -.Er EINVAL -(the last feature is not portable across all platforms). -.Sh ERRORS -.Bl -tag -width Er -.It Bq Er EINVAL -The value of -.Fa base -is not supported or -no conversion could be performed -(the last feature is not portable across all platforms). -.It Bq Er ERANGE -The given string was out of range; the value converted has been clamped. -.El -.Sh SEE ALSO -.Xr strtol 3 , -.Xr strtonum 3 , -.Xr wcstoul 3 -.Sh STANDARDS -The -.Fn strtoul -function -conforms to -.St -isoC . -The -.Fn strtoull -and -.Fn strtoumax -functions -conform to -.St -isoC-99 . -The -.Bx -.Fn strtouq -function is deprecated. diff --git a/lib/libc/stdlib/strtoul.c b/lib/libc/stdlib/strtoul.c deleted file mode 100644 index e8d1e11..0000000 --- a/lib/libc/stdlib/strtoul.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)strtoul.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <limits.h> -#include <ctype.h> -#include <errno.h> -#include <stdlib.h> - -/* - * Convert a string to an unsigned long integer. - * - * Assumes that the upper and lower case - * alphabets and digits are each contiguous. - */ -unsigned long -strtoul(const char * __restrict nptr, char ** __restrict endptr, int base) -{ - const char *s; - unsigned long acc; - char c; - unsigned long cutoff; - int neg, any, cutlim; - - /* - * See strtol for comments as to the logic used. - */ - s = nptr; - do { - c = *s++; - } while (isspace((unsigned char)c)); - if (c == '-') { - neg = 1; - c = *s++; - } else { - neg = 0; - if (c == '+') - c = *s++; - } - if ((base == 0 || base == 16) && - c == '0' && (*s == 'x' || *s == 'X') && - ((s[1] >= '0' && s[1] <= '9') || - (s[1] >= 'A' && s[1] <= 'F') || - (s[1] >= 'a' && s[1] <= 'f'))) { - c = s[1]; - s += 2; - base = 16; - } - if (base == 0) - base = c == '0' ? 8 : 10; - acc = any = 0; - if (base < 2 || base > 36) - goto noconv; - - cutoff = ULONG_MAX / base; - cutlim = ULONG_MAX % base; - for ( ; ; c = *s++) { - if (c >= '0' && c <= '9') - c -= '0'; - else if (c >= 'A' && c <= 'Z') - c -= 'A' - 10; - else if (c >= 'a' && c <= 'z') - c -= 'a' - 10; - else - break; - if (c >= base) - break; - if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) - any = -1; - else { - any = 1; - acc *= base; - acc += c; - } - } - if (any < 0) { - acc = ULONG_MAX; - errno = ERANGE; - } else if (!any) { -noconv: - errno = EINVAL; - } else if (neg) - acc = -acc; - if (endptr != NULL) - *endptr = (char *)(any ? s - 1 : nptr); - return (acc); -} diff --git a/lib/libc/stdlib/strtoull.c b/lib/libc/stdlib/strtoull.c deleted file mode 100644 index f11910c..0000000 --- a/lib/libc/stdlib/strtoull.c +++ /dev/null @@ -1,118 +0,0 @@ -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)strtouq.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <limits.h> -#include <errno.h> -#include <ctype.h> -#include <stdlib.h> - -/* - * Convert a string to an unsigned long long integer. - * - * Assumes that the upper and lower case - * alphabets and digits are each contiguous. - */ -unsigned long long -strtoull(const char * __restrict nptr, char ** __restrict endptr, int base) -{ - const char *s; - unsigned long long acc; - char c; - unsigned long long cutoff; - int neg, any, cutlim; - - /* - * See strtoq for comments as to the logic used. - */ - s = nptr; - do { - c = *s++; - } while (isspace((unsigned char)c)); - if (c == '-') { - neg = 1; - c = *s++; - } else { - neg = 0; - if (c == '+') - c = *s++; - } - if ((base == 0 || base == 16) && - c == '0' && (*s == 'x' || *s == 'X') && - ((s[1] >= '0' && s[1] <= '9') || - (s[1] >= 'A' && s[1] <= 'F') || - (s[1] >= 'a' && s[1] <= 'f'))) { - c = s[1]; - s += 2; - base = 16; - } - if (base == 0) - base = c == '0' ? 8 : 10; - acc = any = 0; - if (base < 2 || base > 36) - goto noconv; - - cutoff = ULLONG_MAX / base; - cutlim = ULLONG_MAX % base; - for ( ; ; c = *s++) { - if (c >= '0' && c <= '9') - c -= '0'; - else if (c >= 'A' && c <= 'Z') - c -= 'A' - 10; - else if (c >= 'a' && c <= 'z') - c -= 'a' - 10; - else - break; - if (c >= base) - break; - if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) - any = -1; - else { - any = 1; - acc *= base; - acc += c; - } - } - if (any < 0) { - acc = ULLONG_MAX; - errno = ERANGE; - } else if (!any) { -noconv: - errno = EINVAL; - } else if (neg) - acc = -acc; - if (endptr != NULL) - *endptr = (char *)(any ? s - 1 : nptr); - return (acc); -} diff --git a/lib/libc/stdlib/strtoumax.c b/lib/libc/stdlib/strtoumax.c deleted file mode 100644 index 23050c2..0000000 --- a/lib/libc/stdlib/strtoumax.c +++ /dev/null @@ -1,118 +0,0 @@ -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "from @(#)strtoul.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <ctype.h> -#include <errno.h> -#include <stdlib.h> -#include <inttypes.h> - -/* - * Convert a string to a uintmax_t integer. - * - * Assumes that the upper and lower case - * alphabets and digits are each contiguous. - */ -uintmax_t -strtoumax(const char * __restrict nptr, char ** __restrict endptr, int base) -{ - const char *s; - uintmax_t acc; - char c; - uintmax_t cutoff; - int neg, any, cutlim; - - /* - * See strtoimax for comments as to the logic used. - */ - s = nptr; - do { - c = *s++; - } while (isspace((unsigned char)c)); - if (c == '-') { - neg = 1; - c = *s++; - } else { - neg = 0; - if (c == '+') - c = *s++; - } - if ((base == 0 || base == 16) && - c == '0' && (*s == 'x' || *s == 'X') && - ((s[1] >= '0' && s[1] <= '9') || - (s[1] >= 'A' && s[1] <= 'F') || - (s[1] >= 'a' && s[1] <= 'f'))) { - c = s[1]; - s += 2; - base = 16; - } - if (base == 0) - base = c == '0' ? 8 : 10; - acc = any = 0; - if (base < 2 || base > 36) - goto noconv; - - cutoff = UINTMAX_MAX / base; - cutlim = UINTMAX_MAX % base; - for ( ; ; c = *s++) { - if (c >= '0' && c <= '9') - c -= '0'; - else if (c >= 'A' && c <= 'Z') - c -= 'A' - 10; - else if (c >= 'a' && c <= 'z') - c -= 'a' - 10; - else - break; - if (c >= base) - break; - if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) - any = -1; - else { - any = 1; - acc *= base; - acc += c; - } - } - if (any < 0) { - acc = UINTMAX_MAX; - errno = ERANGE; - } else if (!any) { -noconv: - errno = EINVAL; - } else if (neg) - acc = -acc; - if (endptr != NULL) - *endptr = (char *)(any ? s - 1 : nptr); - return (acc); -} diff --git a/lib/libc/stdlib/strtouq.c b/lib/libc/stdlib/strtouq.c deleted file mode 100644 index 9638c11..0000000 --- a/lib/libc/stdlib/strtouq.c +++ /dev/null @@ -1,48 +0,0 @@ -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)strtouq.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/types.h> - -#include <stdlib.h> - -/* - * Convert a string to an unsigned quad integer. - */ -u_quad_t -strtouq(const char *nptr, char **endptr, int base) -{ - - return strtoull(nptr, endptr, base); -} diff --git a/lib/libc/stdlib/system.3 b/lib/libc/stdlib/system.3 deleted file mode 100644 index 3d13489..0000000 --- a/lib/libc/stdlib/system.3 +++ /dev/null @@ -1,99 +0,0 @@ -.\" Copyright (c) 1990, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the American National Standards Committee X3, on Information -.\" Processing Systems. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)system.3 8.1 (Berkeley) 6/4/93 -.\" $FreeBSD$ -.\" -.Dd June 4, 1993 -.Dt SYSTEM 3 -.Os -.Sh NAME -.Nm system -.Nd pass a command to the shell -.Sh LIBRARY -.Lb libc -.Sh SYNOPSIS -.In stdlib.h -.Ft int -.Fn system "const char *string" -.Sh DESCRIPTION -The -.Fn system -function -hands the argument -.Fa string -to the command interpreter -.Xr sh 1 . -The calling process waits for the shell -to finish executing the command, -ignoring -.Dv SIGINT -and -.Dv SIGQUIT , -and blocking -.Dv SIGCHLD . -.Pp -If -.Fa string -is a -.Dv NULL -pointer, -.Fn system -will return non-zero if the command interpreter -.Xr sh 1 -is available, and zero if it is not. -.Sh RETURN VALUES -The -.Fn system -function -returns the exit status of the shell as returned by -.Xr waitpid 2 , -or \-1 if an error occurred when invoking -.Xr fork 2 -or -.Xr waitpid 2 . -A return value of 127 means the execution of the shell -failed. -.Sh SEE ALSO -.Xr sh 1 , -.Xr execve 2 , -.Xr fork 2 , -.Xr waitpid 2 , -.Xr popen 3 -.Sh STANDARDS -The -.Fn system -function -conforms to -.St -isoC -and is expected to be -.St -p1003.2 -compatible. diff --git a/lib/libc/stdlib/system.c b/lib/libc/stdlib/system.c deleted file mode 100644 index 4f47edf..0000000 --- a/lib/libc/stdlib/system.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)system.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include "namespace.h" -#include <sys/types.h> -#include <sys/wait.h> -#include <signal.h> -#include <stdlib.h> -#include <stddef.h> -#include <unistd.h> -#include <paths.h> -#include <errno.h> -#include "un-namespace.h" -#include "libc_private.h" - -int -__system(const char *command) -{ - pid_t pid, savedpid; - int pstat; - struct sigaction ign, intact, quitact; - sigset_t newsigblock, oldsigblock; - - if (!command) /* just checking... */ - return(1); - - /* - * Ignore SIGINT and SIGQUIT, block SIGCHLD. Remember to save - * existing signal dispositions. - */ - ign.sa_handler = SIG_IGN; - (void)sigemptyset(&ign.sa_mask); - ign.sa_flags = 0; - (void)_sigaction(SIGINT, &ign, &intact); - (void)_sigaction(SIGQUIT, &ign, &quitact); - (void)sigemptyset(&newsigblock); - (void)sigaddset(&newsigblock, SIGCHLD); - (void)_sigprocmask(SIG_BLOCK, &newsigblock, &oldsigblock); - switch(pid = fork()) { - case -1: /* error */ - break; - case 0: /* child */ - /* - * Restore original signal dispositions and exec the command. - */ - (void)_sigaction(SIGINT, &intact, NULL); - (void)_sigaction(SIGQUIT, &quitact, NULL); - (void)_sigprocmask(SIG_SETMASK, &oldsigblock, NULL); - execl(_PATH_BSHELL, "sh", "-c", command, (char *)NULL); - _exit(127); - default: /* parent */ - savedpid = pid; - do { - pid = _wait4(savedpid, &pstat, 0, (struct rusage *)0); - } while (pid == -1 && errno == EINTR); - break; - } - (void)_sigaction(SIGINT, &intact, NULL); - (void)_sigaction(SIGQUIT, &quitact, NULL); - (void)_sigprocmask(SIG_SETMASK, &oldsigblock, NULL); - return(pid == -1 ? -1 : pstat); -} - -__weak_reference(__system, system); -__weak_reference(__system, _system); diff --git a/lib/libc/stdlib/tdelete.c b/lib/libc/stdlib/tdelete.c deleted file mode 100644 index c83afb8..0000000 --- a/lib/libc/stdlib/tdelete.c +++ /dev/null @@ -1,71 +0,0 @@ -/* $NetBSD: tdelete.c,v 1.2 1999/09/16 11:45:37 lukem Exp $ */ - -/* - * Tree search generalized from Knuth (6.2.2) Algorithm T just like - * the AT&T man page says. - * - * The node_t structure is for internal use only, lint doesn't grok it. - * - * Written by reading the System V Interface Definition, not the code. - * - * Totally public domain. - */ - -#include <sys/cdefs.h> -#if 0 -#if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: tdelete.c,v 1.2 1999/09/16 11:45:37 lukem Exp $"); -#endif /* LIBC_SCCS and not lint */ -#endif -__FBSDID("$FreeBSD$"); - -#define _SEARCH_PRIVATE -#include <search.h> -#include <stdlib.h> - - -/* - * delete node with given key - * - * vkey: key to be deleted - * vrootp: address of the root of the tree - * compar: function to carry out node comparisons - */ -void * -tdelete(const void * __restrict vkey, void ** __restrict vrootp, - int (*compar)(const void *, const void *)) -{ - node_t **rootp = (node_t **)vrootp; - node_t *p, *q, *r; - int cmp; - - if (rootp == NULL || (p = *rootp) == NULL) - return NULL; - - while ((cmp = (*compar)(vkey, (*rootp)->key)) != 0) { - p = *rootp; - rootp = (cmp < 0) ? - &(*rootp)->llink : /* follow llink branch */ - &(*rootp)->rlink; /* follow rlink branch */ - if (*rootp == NULL) - return NULL; /* key not found */ - } - r = (*rootp)->rlink; /* D1: */ - if ((q = (*rootp)->llink) == NULL) /* Left NULL? */ - q = r; - else if (r != NULL) { /* Right link is NULL? */ - if (r->llink == NULL) { /* D2: Find successor */ - r->llink = q; - q = r; - } else { /* D3: Find NULL link */ - for (q = r->llink; q->llink != NULL; q = r->llink) - r = q; - r->llink = q->rlink; - q->llink = (*rootp)->llink; - q->rlink = (*rootp)->rlink; - } - } - free(*rootp); /* D4: Free node */ - *rootp = q; /* link parent to new node */ - return p; -} diff --git a/lib/libc/stdlib/tfind.c b/lib/libc/stdlib/tfind.c deleted file mode 100644 index c5d66cf..0000000 --- a/lib/libc/stdlib/tfind.c +++ /dev/null @@ -1,48 +0,0 @@ -/* $NetBSD: tfind.c,v 1.2 1999/09/16 11:45:37 lukem Exp $ */ - -/* - * Tree search generalized from Knuth (6.2.2) Algorithm T just like - * the AT&T man page says. - * - * The node_t structure is for internal use only, lint doesn't grok it. - * - * Written by reading the System V Interface Definition, not the code. - * - * Totally public domain. - */ - -#include <sys/cdefs.h> -#if 0 -#if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: tfind.c,v 1.2 1999/09/16 11:45:37 lukem Exp $"); -#endif /* LIBC_SCCS and not lint */ -#endif -__FBSDID("$FreeBSD$"); - -#define _SEARCH_PRIVATE -#include <stdlib.h> -#include <search.h> - -/* find a node, or return 0 */ -void * -tfind(vkey, vrootp, compar) - const void *vkey; /* key to be found */ - void * const *vrootp; /* address of the tree root */ - int (*compar)(const void *, const void *); -{ - node_t **rootp = (node_t **)vrootp; - - if (rootp == NULL) - return NULL; - - while (*rootp != NULL) { /* T1: */ - int r; - - if ((r = (*compar)(vkey, (*rootp)->key)) == 0) /* T2: */ - return *rootp; /* key found */ - rootp = (r < 0) ? - &(*rootp)->llink : /* T3: follow left branch */ - &(*rootp)->rlink; /* T4: follow right branch */ - } - return NULL; -} diff --git a/lib/libc/stdlib/tsearch.3 b/lib/libc/stdlib/tsearch.3 deleted file mode 100644 index 7a204d0..0000000 --- a/lib/libc/stdlib/tsearch.3 +++ /dev/null @@ -1,132 +0,0 @@ -.\" $NetBSD$ -.\" Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com> -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. The name of the author may not be used to endorse or promote products -.\" derived from this software without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, -.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY -.\" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -.\" THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -.\" EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -.\" PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -.\" OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -.\" -.\" OpenBSD: tsearch.3,v 1.2 1998/06/21 22:13:49 millert Exp -.\" $FreeBSD$ -.\" -.Dd June 15, 1997 -.Dt TSEARCH 3 -.Os -.Sh NAME -.Nm tsearch , tfind , tdelete , twalk -.Nd manipulate binary search trees -.Sh SYNOPSIS -.In search.h -.Ft void * -.Fn tdelete "const void * restrict key" "void ** restrict rootp" "int (*compar) (const void *, const void *)" -.Ft void * -.Fn tfind "const void *key" "void * const *rootp" "int (*compar) (const void *, const void *)" -.Ft void * -.Fn tsearch "const void *key" "void **rootp" "int (*compar) (const void *, const void *)" -.Ft void -.Fn twalk "const void *root" "void (*action) (const void *, VISIT, int)" -.Sh DESCRIPTION -The -.Fn tdelete , -.Fn tfind , -.Fn tsearch , -and -.Fn twalk -functions manage binary search trees based on algorithms T and D -from Knuth (6.2.2). -The comparison function passed in by -the user has the same style of return values as -.Xr strcmp 3 . -.Pp -The -.Fn tfind -function -searches for the datum matched by the argument -.Fa key -in the binary tree rooted at -.Fa rootp , -returning a pointer to the datum if it is found and NULL -if it is not. -.Pp -The -.Fn tsearch -function -is identical to -.Fn tfind -except that if no match is found, -.Fa key -is inserted into the tree and a pointer to it is returned. -If -.Fa rootp -points to a NULL value a new binary search tree is created. -.Pp -The -.Fn tdelete -function -deletes a node from the specified binary search tree and returns -a pointer to the parent of the node to be deleted. -It takes the same arguments as -.Fn tfind -and -.Fn tsearch . -If the node to be deleted is the root of the binary search tree, -.Fa rootp -will be adjusted. -.Pp -The -.Fn twalk -function -walks the binary search tree rooted in -.Fa root -and calls the function -.Fa action -on each node. -The -.Fa action -function -is called with three arguments: a pointer to the current node, -a value from the enum -.Sy "typedef enum { preorder, postorder, endorder, leaf } VISIT;" -specifying the traversal type, and a node level (where level -zero is the root of the tree). -.Sh RETURN VALUES -The -.Fn tsearch -function returns NULL if allocation of a new node fails (usually -due to a lack of free memory). -.Pp -The -.Fn tfind , -.Fn tsearch , -and -.Fn tdelete -functions -return NULL if -.Fa rootp -is NULL or the datum cannot be found. -.Pp -The -.Fn twalk -function returns no value. -.Sh SEE ALSO -.Xr bsearch 3 , -.Xr hsearch 3 , -.Xr lsearch 3 diff --git a/lib/libc/stdlib/tsearch.c b/lib/libc/stdlib/tsearch.c deleted file mode 100644 index 149c2bb..0000000 --- a/lib/libc/stdlib/tsearch.c +++ /dev/null @@ -1,58 +0,0 @@ -/* $NetBSD: tsearch.c,v 1.3 1999/09/16 11:45:37 lukem Exp $ */ - -/* - * Tree search generalized from Knuth (6.2.2) Algorithm T just like - * the AT&T man page says. - * - * The node_t structure is for internal use only, lint doesn't grok it. - * - * Written by reading the System V Interface Definition, not the code. - * - * Totally public domain. - */ - -#include <sys/cdefs.h> -#if 0 -#if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: tsearch.c,v 1.3 1999/09/16 11:45:37 lukem Exp $"); -#endif /* LIBC_SCCS and not lint */ -#endif -__FBSDID("$FreeBSD$"); - -#define _SEARCH_PRIVATE -#include <search.h> -#include <stdlib.h> - -/* find or insert datum into search tree */ -void * -tsearch(vkey, vrootp, compar) - const void *vkey; /* key to be located */ - void **vrootp; /* address of tree root */ - int (*compar)(const void *, const void *); -{ - node_t *q; - node_t **rootp = (node_t **)vrootp; - - if (rootp == NULL) - return NULL; - - while (*rootp != NULL) { /* Knuth's T1: */ - int r; - - if ((r = (*compar)(vkey, (*rootp)->key)) == 0) /* T2: */ - return *rootp; /* we found it! */ - - rootp = (r < 0) ? - &(*rootp)->llink : /* T3: follow left branch */ - &(*rootp)->rlink; /* T4: follow right branch */ - } - - q = malloc(sizeof(node_t)); /* T5: key not found */ - if (q != 0) { /* make new node */ - *rootp = q; /* link new node to old */ - /* LINTED const castaway ok */ - q->key = (void *)vkey; /* initialize new node */ - q->llink = q->rlink = NULL; - } - return q; -} diff --git a/lib/libc/stdlib/twalk.c b/lib/libc/stdlib/twalk.c deleted file mode 100644 index 55f220f3..0000000 --- a/lib/libc/stdlib/twalk.c +++ /dev/null @@ -1,58 +0,0 @@ -/* $NetBSD: twalk.c,v 1.1 1999/02/22 10:33:16 christos Exp $ */ - -/* - * Tree search generalized from Knuth (6.2.2) Algorithm T just like - * the AT&T man page says. - * - * The node_t structure is for internal use only, lint doesn't grok it. - * - * Written by reading the System V Interface Definition, not the code. - * - * Totally public domain. - */ - -#include <sys/cdefs.h> -#if 0 -#if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: twalk.c,v 1.1 1999/02/22 10:33:16 christos Exp $"); -#endif /* LIBC_SCCS and not lint */ -#endif -__FBSDID("$FreeBSD$"); - -#define _SEARCH_PRIVATE -#include <search.h> -#include <stdlib.h> - -static void trecurse(const node_t *, - void (*action)(const void *, VISIT, int), int level); - -/* Walk the nodes of a tree */ -static void -trecurse(root, action, level) - const node_t *root; /* Root of the tree to be walked */ - void (*action)(const void *, VISIT, int); - int level; -{ - - if (root->llink == NULL && root->rlink == NULL) - (*action)(root, leaf, level); - else { - (*action)(root, preorder, level); - if (root->llink != NULL) - trecurse(root->llink, action, level + 1); - (*action)(root, postorder, level); - if (root->rlink != NULL) - trecurse(root->rlink, action, level + 1); - (*action)(root, endorder, level); - } -} - -/* Walk the nodes of a tree */ -void -twalk(vroot, action) - const void *vroot; /* Root of the tree to be walked */ - void (*action)(const void *, VISIT, int); -{ - if (vroot != NULL && action != NULL) - trecurse(vroot, action, 0); -} |