summaryrefslogtreecommitdiff
path: root/src/lib/libc/stdlib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libc/stdlib')
-rw-r--r--src/lib/libc/stdlib/Makefile.inc71
-rw-r--r--src/lib/libc/stdlib/_Exit.c26
-rw-r--r--src/lib/libc/stdlib/_rand48.c50
-rw-r--r--src/lib/libc/stdlib/a64l.3133
-rw-r--r--src/lib/libc/stdlib/a64l.c45
-rw-r--r--src/lib/libc/stdlib/abort.363
-rw-r--r--src/lib/libc/stdlib/abort.c78
-rw-r--r--src/lib/libc/stdlib/abs.365
-rw-r--r--src/lib/libc/stdlib/abs.c40
-rw-r--r--src/lib/libc/stdlib/alloca.380
-rw-r--r--src/lib/libc/stdlib/atexit.371
-rw-r--r--src/lib/libc/stdlib/atexit.c133
-rw-r--r--src/lib/libc/stdlib/atexit.h41
-rw-r--r--src/lib/libc/stdlib/atof.369
-rw-r--r--src/lib/libc/stdlib/atof.c40
-rw-r--r--src/lib/libc/stdlib/atoi.386
-rw-r--r--src/lib/libc/stdlib/atoi.c40
-rw-r--r--src/lib/libc/stdlib/atol.370
-rw-r--r--src/lib/libc/stdlib/atol.c40
-rw-r--r--src/lib/libc/stdlib/atoll.370
-rw-r--r--src/lib/libc/stdlib/atoll.c41
-rw-r--r--src/lib/libc/stdlib/bsearch.384
-rw-r--r--src/lib/libc/stdlib/bsearch.c71
-rw-r--r--src/lib/libc/stdlib/calloc.c53
-rw-r--r--src/lib/libc/stdlib/cfree.c44
-rw-r--r--src/lib/libc/stdlib/div.363
-rw-r--r--src/lib/libc/stdlib/div.c74
-rw-r--r--src/lib/libc/stdlib/drand48.c26
-rw-r--r--src/lib/libc/stdlib/ecvt.3165
-rw-r--r--src/lib/libc/stdlib/ecvt.c103
-rw-r--r--src/lib/libc/stdlib/erand48.c27
-rw-r--r--src/lib/libc/stdlib/exit.3114
-rw-r--r--src/lib/libc/stdlib/exit.c72
-rw-r--r--src/lib/libc/stdlib/gcvt.c99
-rw-r--r--src/lib/libc/stdlib/getenv.3142
-rw-r--r--src/lib/libc/stdlib/getenv.c83
-rw-r--r--src/lib/libc/stdlib/getopt.3372
-rw-r--r--src/lib/libc/stdlib/getopt_long.3377
-rw-r--r--src/lib/libc/stdlib/getopt_long.c537
-rw-r--r--src/lib/libc/stdlib/getsubopt.3143
-rw-r--r--src/lib/libc/stdlib/getsubopt.c100
-rw-r--r--src/lib/libc/stdlib/hcreate.3195
-rw-r--r--src/lib/libc/stdlib/hcreate.c200
-rw-r--r--src/lib/libc/stdlib/heapsort.c177
-rw-r--r--src/lib/libc/stdlib/insque.3100
-rw-r--r--src/lib/libc/stdlib/insque.c52
-rw-r--r--src/lib/libc/stdlib/jrand48.c25
-rw-r--r--src/lib/libc/stdlib/l64a.c45
-rw-r--r--src/lib/libc/stdlib/labs.368
-rw-r--r--src/lib/libc/stdlib/labs.c40
-rw-r--r--src/lib/libc/stdlib/lcong48.c34
-rw-r--r--src/lib/libc/stdlib/ldiv.365
-rw-r--r--src/lib/libc/stdlib/ldiv.c53
-rw-r--r--src/lib/libc/stdlib/llabs.c45
-rw-r--r--src/lib/libc/stdlib/lrand48.c27
-rw-r--r--src/lib/libc/stdlib/lsearch.3105
-rw-r--r--src/lib/libc/stdlib/lsearch.c88
-rw-r--r--src/lib/libc/stdlib/malloc.3431
-rw-r--r--src/lib/libc/stdlib/malloc.c1698
-rw-r--r--src/lib/libc/stdlib/merge.c336
-rw-r--r--src/lib/libc/stdlib/mrand48.c27
-rw-r--r--src/lib/libc/stdlib/multibyte.c120
-rw-r--r--src/lib/libc/stdlib/nrand48.c25
-rw-r--r--src/lib/libc/stdlib/putenv.c53
-rw-r--r--src/lib/libc/stdlib/qabs.356
-rw-r--r--src/lib/libc/stdlib/qabs.c40
-rw-r--r--src/lib/libc/stdlib/qdiv.360
-rw-r--r--src/lib/libc/stdlib/qdiv.c53
-rw-r--r--src/lib/libc/stdlib/qsort.3233
-rw-r--r--src/lib/libc/stdlib/qsort.c164
-rw-r--r--src/lib/libc/stdlib/radixsort.3155
-rw-r--r--src/lib/libc/stdlib/radixsort.c297
-rw-r--r--src/lib/libc/stdlib/rand.398
-rw-r--r--src/lib/libc/stdlib/rand.c56
-rw-r--r--src/lib/libc/stdlib/rand48.3165
-rw-r--r--src/lib/libc/stdlib/rand48.h32
-rw-r--r--src/lib/libc/stdlib/random.3186
-rw-r--r--src/lib/libc/stdlib/random.c425
-rw-r--r--src/lib/libc/stdlib/realpath.3117
-rw-r--r--src/lib/libc/stdlib/realpath.c198
-rw-r--r--src/lib/libc/stdlib/remque.c48
-rw-r--r--src/lib/libc/stdlib/seed48.c40
-rw-r--r--src/lib/libc/stdlib/setenv.c106
-rw-r--r--src/lib/libc/stdlib/srand48.c34
-rw-r--r--src/lib/libc/stdlib/strtod.3113
-rw-r--r--src/lib/libc/stdlib/strtod.c2411
-rw-r--r--src/lib/libc/stdlib/strtol.3247
-rw-r--r--src/lib/libc/stdlib/strtol.c143
-rw-r--r--src/lib/libc/stdlib/strtoll.c156
-rw-r--r--src/lib/libc/stdlib/strtonum.3151
-rw-r--r--src/lib/libc/stdlib/strtonum.c65
-rw-r--r--src/lib/libc/stdlib/strtoul.3231
-rw-r--r--src/lib/libc/stdlib/strtoul.c105
-rw-r--r--src/lib/libc/stdlib/strtoull.c118
-rw-r--r--src/lib/libc/stdlib/system.399
-rw-r--r--src/lib/libc/stdlib/system.c77
-rw-r--r--src/lib/libc/stdlib/tfind.c41
-rw-r--r--src/lib/libc/stdlib/tsearch.3116
-rw-r--r--src/lib/libc/stdlib/tsearch.c119
99 files changed, 14865 insertions, 0 deletions
diff --git a/src/lib/libc/stdlib/Makefile.inc b/src/lib/libc/stdlib/Makefile.inc
new file mode 100644
index 0000000000..1d5ba5c9bd
--- /dev/null
+++ b/src/lib/libc/stdlib/Makefile.inc
@@ -0,0 +1,71 @@
1# $OpenBDS: Makefile.inc,v 1.6 1996/08/21 03:47:21 tholo Exp $
2
3# stdlib sources
4.PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/stdlib ${LIBCSRCDIR}/stdlib
5
6SRCS+= a64l.c abort.c atexit.c atoi.c atof.c atol.c atoll.c bsearch.c \
7 calloc.c cfree.c exit.c ecvt.c gcvt.c getenv.c getopt_long.c \
8 getsubopt.c hcreate.c heapsort.c l64a.c llabs.c lsearch.c malloc.c \
9 merge.c multibyte.c putenv.c qsort.c radixsort.c rand.c random.c \
10 realpath.c setenv.c strtod.c strtol.c strtoll.c strtonum.c strtoul.c \
11 strtoull.c system.c \
12 tfind.c tsearch.c _rand48.c drand48.c erand48.c jrand48.c lcong48.c \
13 lrand48.c mrand48.c nrand48.c seed48.c srand48.c qabs.c qdiv.c _Exit.c
14
15.if (${MACHINE_ARCH} == "m68k")
16SRCS+= abs.S div.c labs.c ldiv.c
17LSRCS+= abs.c
18.elif (${MACHINE_ARCH} == "i386")
19SRCS+= abs.S div.S labs.S ldiv.S
20LSRCS+= abs.c div.c labs.c ldiv.c
21.elif (${MACHINE_ARCH} == "ns32k")
22SRCS+= abs.S div.c labs.c ldiv.c
23LSRCS+= abs.c
24.elif (${MACHINE_ARCH} == "tahoe")
25SRCS+= abs.S div.c labs.c ldiv.c
26LSRCS+= abs.c
27.elif (${MACHINE_ARCH} == "vax")
28SRCS+= abs.c div.c labs.c ldiv.c
29.elif (${MACHINE_ARCH} == "alpha")
30# XXX should be .S's
31SRCS+= abs.c div.c labs.c ldiv.c
32.else
33SRCS+= abs.c div.c labs.c ldiv.c
34.endif
35
36.if (${MACHINE_ARCH} == "vax") || (${MACHINE_ARCH} == "m68k")
37SRCS+= insque.S remque.S
38.else
39SRCS+= insque.c remque.c
40.endif
41
42MAN+= a64l.3 abort.3 abs.3 alloca.3 atexit.3 atof.3 atoi.3 atol.3 atoll.3 \
43 bsearch.3 div.3 ecvt.3 exit.3 getenv.3 getopt.3 getopt_long.3 \
44 getsubopt.3 hcreate.3 insque.3 labs.3 ldiv.3 lsearch.3 malloc.3 qabs.3 \
45 qdiv.3 qsort.3 radixsort.3 rand48.3 rand.3 random.3 realpath.3 \
46 strtod.3 strtonum.3 strtol.3 strtoul.3 system.3 tsearch.3
47
48MLINKS+=exit.3 _Exit.3
49MLINKS+=ecvt.3 fcvt.3 ecvt.3 gcvt.3
50MLINKS+=getenv.3 setenv.3 getenv.3 unsetenv.3 getenv.3 putenv.3
51MLINKS+=getopt_long.3 getopt_long_only.3
52MLINKS+=hcreate.3 hdestroy.3 hcreate.3 hsearch.3
53MLINKS+=insque.3 remque.3
54MLINKS+=labs.3 llabs.3
55MLINKS+=lsearch.3 lfind.3
56MLINKS+=malloc.3 free.3 malloc.3 realloc.3 malloc.3 calloc.3
57MLINKS+=malloc.3 cfree.3 malloc.3 malloc.conf.5
58MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3
59MLINKS+=radixsort.3 sradixsort.3
60MLINKS+=rand.3 srand.3 rand.3 rand_r.3
61MLINKS+=random.3 initstate.3 random.3 setstate.3
62MLINKS+=random.3 srandom.3 random.3 srandomdev.3
63MLINKS+=rand48.3 drand48.3 rand48.3 erand48.3 rand48.3 lrand48.3
64MLINKS+=rand48.3 mrand48.3 rand48.3 nrand48.3 rand48.3 jrand48.3
65MLINKS+=rand48.3 srand48.3 rand48.3 seed48.3 rand48.3 lcong48.3
66MLINKS+=strtol.3 strtoll.3 strtol.3 strtoq.3
67MLINKS+=strtoul.3 strtoull.3 strtoul.3 strtouq.3
68MLINKS+=tsearch.3 tfind.3
69MLINKS+=tsearch.3 tdelete.3
70MLINKS+=tsearch.3 twalk.3
71MLINKS+=a64l.3 l64a.3
diff --git a/src/lib/libc/stdlib/_Exit.c b/src/lib/libc/stdlib/_Exit.c
new file mode 100644
index 0000000000..784015a21d
--- /dev/null
+++ b/src/lib/libc/stdlib/_Exit.c
@@ -0,0 +1,26 @@
1/* $OpenBSD: _Exit.c,v 1.1 2004/05/03 17:21:13 millert Exp $ */
2
3/*
4 * Placed in the public domain by Todd C. Miller on January 21, 2004.
5 */
6
7#if defined(LIBC_SCCS) && !defined(lint)
8static char *rcsid = "$OpenBSD: _Exit.c,v 1.1 2004/05/03 17:21:13 millert Exp $";
9#endif /* LIBC_SCCS and not lint */
10
11#include <stdlib.h>
12#include <unistd.h>
13
14/*
15 * _Exit() is the ISO/ANSI C99 equivalent of the POSIX _exit() function.
16 * No atexit() handlers are called and no signal handlers are run.
17 * Whether or not stdio buffers are flushed or temporary files are removed
18 * is implementation-dependent. As such it is safest to *not* flush
19 * stdio buffers or remove temporary files. This is also consistent
20 * with most other implementations.
21 */
22void
23_Exit(int status)
24{
25 _exit(status);
26}
diff --git a/src/lib/libc/stdlib/_rand48.c b/src/lib/libc/stdlib/_rand48.c
new file mode 100644
index 0000000000..fed7372f68
--- /dev/null
+++ b/src/lib/libc/stdlib/_rand48.c
@@ -0,0 +1,50 @@
1/*
2 * Copyright (c) 1993 Martin Birgmeier
3 * All rights reserved.
4 *
5 * You may redistribute unmodified or modified versions of this source
6 * code provided that the above copyright notice and this and the
7 * following conditions are retained.
8 *
9 * This software is provided ``as is'', and comes with no warranties
10 * of any kind. I shall in no event be liable for anything that happens
11 * to anyone/anything when using this software.
12 */
13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: _rand48.c,v 1.2 1996/08/19 08:33:19 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
18#include "rand48.h"
19
20unsigned short __rand48_seed[3] = {
21 RAND48_SEED_0,
22 RAND48_SEED_1,
23 RAND48_SEED_2
24};
25unsigned short __rand48_mult[3] = {
26 RAND48_MULT_0,
27 RAND48_MULT_1,
28 RAND48_MULT_2
29};
30unsigned short __rand48_add = RAND48_ADD;
31
32void
33__dorand48(unsigned short xseed[3])
34{
35 unsigned long accu;
36 unsigned short temp[2];
37
38 accu = (unsigned long) __rand48_mult[0] * (unsigned long) xseed[0] +
39 (unsigned long) __rand48_add;
40 temp[0] = (unsigned short) accu; /* lower 16 bits */
41 accu >>= sizeof(unsigned short) * 8;
42 accu += (unsigned long) __rand48_mult[0] * (unsigned long) xseed[1] +
43 (unsigned long) __rand48_mult[1] * (unsigned long) xseed[0];
44 temp[1] = (unsigned short) accu; /* middle 16 bits */
45 accu >>= sizeof(unsigned short) * 8;
46 accu += __rand48_mult[0] * xseed[2] + __rand48_mult[1] * xseed[1] + __rand48_mult[2] * xseed[0];
47 xseed[0] = temp[0];
48 xseed[1] = temp[1];
49 xseed[2] = (unsigned short) accu;
50}
diff --git a/src/lib/libc/stdlib/a64l.3 b/src/lib/libc/stdlib/a64l.3
new file mode 100644
index 0000000000..f2957a7ad4
--- /dev/null
+++ b/src/lib/libc/stdlib/a64l.3
@@ -0,0 +1,133 @@
1.\" $OpenBSD: a64l.3,v 1.9 2005/02/25 03:12:44 cloder Exp $
2.\"
3.\" Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
4.\"
5.\" Permission to use, copy, modify, and distribute this software for any
6.\" purpose with or without fee is hereby granted, provided that the above
7.\" copyright notice and this permission notice appear in all copies.
8.\"
9.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16.\"
17.Dd August 17, 1997
18.Dt A64L 3
19.Os
20.Sh NAME
21.Nm a64l ,
22.Nm l64a
23.Nd convert between 32-bit integer and radix-64 ASCII string
24.Sh SYNOPSIS
25.Fd #include <stdlib.h>
26.Ft long
27.Fn a64l "const char *s"
28.Ft char *
29.Fn l64a "long l"
30.Sh DESCRIPTION
31The
32.Fn a64l
33and
34.Fn l64a
35functions are used to maintain numbers stored in radix-64
36.Tn ASCII
37characters.
38This is a notation by which 32-bit integers
39can be represented by up to six characters; each character represents a
40.Dq digit
41in a radix-64 notation.
42.Pp
43The characters used to represent digits are
44.Ql \&.
45for 0,
46.Ql /
47for 1,
48.Ql 0
49through
50.Ql 9
51for 2-11,
52.Ql A
53through
54.Ql Z
55for 12-37, and
56.Ql a
57through
58.Ql z
59for 38-63.
60.Pp
61The
62.Fn a64l
63function takes a pointer to a NUL-terminated radix-64 representation
64and returns a corresponding 32-bit value.
65If the string pointed to by
66.Fa s
67contains more than six characters,
68.Fn a64l
69will use the first six.
70.Fn a64l
71scans the character string from left to right, decoding
72each character as a 6-bit radix-64 number.
73If a long integer is
74larger than 32 bits, the return value will be sign-extended.
75.Pp
76.Fn l64a
77takes a long integer argument
78.Fa l
79and returns a pointer to the corresponding radix-64 representation.
80.Sh RETURN VALUES
81On success,
82.Fn a64l
83returns a 32-bit representation of
84.Fa s .
85If
86.Fa s
87is a null pointer or if it contains digits other than those described above,
88.Fn a64l
89returns \-1 and sets the global variable
90.Va errno
91to
92.Er EINVAL .
93.Pp
94On success,
95.Fn l64a
96returns a pointer to a string containing the radix-64 representation of
97.Fa l .
98If
99.Fa l
100is 0,
101.Fn l64a
102returns a pointer to the empty string.
103If
104.Fa l
105is negative,
106.Fn l64a
107returns a null pointer and sets the global variable
108.Va errno
109to
110.Er EINVAL .
111.Sh WARNINGS
112The value returned by
113.Fn l64a
114is a pointer into a static buffer, the contents of which
115will be overwritten by subsequent calls.
116.Pp
117The value returned by
118.Fn a64l
119may be incorrect if the value is too large; for that reason, only strings
120that resulted from a call to
121.Fn l64a
122should be used to call
123.Fn a64l .
124.Pp
125If a long integer is larger than 32 bits, only the low-order
12632 bits are used.
127.Sh STANDARDS
128The
129.Fn a64l
130and
131.Fn l64a
132functions conform to
133.St -xpg4.2 .
diff --git a/src/lib/libc/stdlib/a64l.c b/src/lib/libc/stdlib/a64l.c
new file mode 100644
index 0000000000..518bdb64f9
--- /dev/null
+++ b/src/lib/libc/stdlib/a64l.c
@@ -0,0 +1,45 @@
1/*
2 * Written by J.T. Conklin <jtc@netbsd.org>.
3 * Public domain.
4 */
5
6#if defined(LIBC_SCCS) && !defined(lint)
7static char *rcsid = "$OpenBSD: a64l.c,v 1.4 2005/03/30 18:51:49 pat Exp $";
8#endif /* LIBC_SCCS and not lint */
9
10#include <errno.h>
11#include <stdlib.h>
12
13long
14a64l(const char *s)
15{
16 long value, digit, shift;
17 int i;
18
19 if (s == NULL) {
20 errno = EINVAL;
21 return(-1L);
22 }
23
24 value = 0;
25 shift = 0;
26 for (i = 0; *s && i < 6; i++, s++) {
27 if (*s >= '.' && *s <= '/')
28 digit = *s - '.';
29 else if (*s >= '0' && *s <= '9')
30 digit = *s - '0' + 2;
31 else if (*s >= 'A' && *s <= 'Z')
32 digit = *s - 'A' + 12;
33 else if (*s >= 'a' && *s <= 'z')
34 digit = *s - 'a' + 38;
35 else {
36 errno = EINVAL;
37 return(-1L);
38 }
39
40 value |= digit << shift;
41 shift += 6;
42 }
43
44 return(value);
45}
diff --git a/src/lib/libc/stdlib/abort.3 b/src/lib/libc/stdlib/abort.3
new file mode 100644
index 0000000000..d411b859eb
--- /dev/null
+++ b/src/lib/libc/stdlib/abort.3
@@ -0,0 +1,63 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information
6.\" Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: abort.3,v 1.7 2003/06/02 20:18:37 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt ABORT 3
36.Os
37.Sh NAME
38.Nm abort
39.Nd cause abnormal program termination
40.Sh SYNOPSIS
41.Fd #include <stdlib.h>
42.Ft void
43.Fn abort void
44.Sh DESCRIPTION
45The
46.Fn abort
47function causes abnormal program termination to occur, unless the signal
48.Dv SIGABRT
49is being caught and the signal handler does not return.
50.Pp
51Any open streams are flushed and closed.
52.Sh RETURN VALUES
53The
54.Fn abort
55function never returns.
56.Sh SEE ALSO
57.Xr sigaction 2 ,
58.Xr exit 3
59.Sh STANDARDS
60The
61.Fn abort
62function conforms to
63.St -p1003.1-90 .
diff --git a/src/lib/libc/stdlib/abort.c b/src/lib/libc/stdlib/abort.c
new file mode 100644
index 0000000000..2430c124f9
--- /dev/null
+++ b/src/lib/libc/stdlib/abort.c
@@ -0,0 +1,78 @@
1/*
2 * Copyright (c) 1985 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: abort.c,v 1.13 2004/01/20 19:35:17 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <signal.h>
35#include <stdlib.h>
36#include <unistd.h>
37#include "thread_private.h"
38#include "atexit.h"
39
40void
41abort(void)
42{
43 struct atexit *p = __atexit;
44 static int cleanup_called = 0;
45 sigset_t mask;
46
47
48 sigfillset(&mask);
49 /*
50 * don't block SIGABRT to give any handler a chance; we ignore
51 * any errors -- X311J doesn't allow abort to return anyway.
52 */
53 sigdelset(&mask, SIGABRT);
54 (void)_thread_sys_sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
55
56 /*
57 * POSIX requires we flush stdio buffers on abort
58 */
59 if (cleanup_called == 0) {
60 while (p != NULL && p->next != NULL)
61 p = p->next;
62 if (p != NULL && p->fns[0] != NULL) {
63 cleanup_called = 1;
64 (*p->fns[0])();
65 }
66 }
67
68 (void)kill(getpid(), SIGABRT);
69
70 /*
71 * if SIGABRT ignored, or caught and the handler returns, do
72 * it again, only harder.
73 */
74 (void)signal(SIGABRT, SIG_DFL);
75 (void)_thread_sys_sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
76 (void)kill(getpid(), SIGABRT);
77 _exit(1);
78}
diff --git a/src/lib/libc/stdlib/abs.3 b/src/lib/libc/stdlib/abs.3
new file mode 100644
index 0000000000..f0a6b8a23a
--- /dev/null
+++ b/src/lib/libc/stdlib/abs.3
@@ -0,0 +1,65 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information
6.\" Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: abs.3,v 1.6 2003/06/02 20:18:37 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt ABS 3
36.Os
37.Sh NAME
38.Nm abs
39.Nd integer absolute value function
40.Sh SYNOPSIS
41.Fd #include <stdlib.h>
42.Ft int
43.Fn abs "int j"
44.Sh DESCRIPTION
45The
46.Fn abs
47function computes the absolute value of the integer
48.Fa j .
49.Sh RETURN VALUES
50The
51.Fn abs
52function returns the absolute value.
53.Sh SEE ALSO
54.Xr cabs 3 ,
55.Xr floor 3 ,
56.Xr hypot 3 ,
57.Xr labs 3 ,
58.Xr math 3
59.Sh STANDARDS
60The
61.Fn abs
62function conforms to
63.St -ansiC .
64.Sh BUGS
65The absolute value of the most negative integer remains negative.
diff --git a/src/lib/libc/stdlib/abs.c b/src/lib/libc/stdlib/abs.c
new file mode 100644
index 0000000000..a471ab3a1e
--- /dev/null
+++ b/src/lib/libc/stdlib/abs.c
@@ -0,0 +1,40 @@
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: abs.c,v 1.4 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35
36int
37abs(int j)
38{
39 return(j < 0 ? -j : j);
40}
diff --git a/src/lib/libc/stdlib/alloca.3 b/src/lib/libc/stdlib/alloca.3
new file mode 100644
index 0000000000..4136dc405c
--- /dev/null
+++ b/src/lib/libc/stdlib/alloca.3
@@ -0,0 +1,80 @@
1.\" Copyright (c) 1980, 1991 Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" Redistribution and use in source and binary forms, with or without
5.\" modification, are permitted provided that the following conditions
6.\" are met:
7.\" 1. Redistributions of source code must retain the above copyright
8.\" notice, this list of conditions and the following disclaimer.
9.\" 2. Redistributions in binary form must reproduce the above copyright
10.\" notice, this list of conditions and the following disclaimer in the
11.\" documentation and/or other materials provided with the distribution.
12.\" 3. Neither the name of the University nor the names of its contributors
13.\" may be used to endorse or promote products derived from this software
14.\" without specific prior written permission.
15.\"
16.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
17.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26.\" SUCH DAMAGE.
27.\"
28.\" $OpenBSD: alloca.3,v 1.10 2003/06/02 20:18:37 millert Exp $
29.\"
30.Dd May 2, 1991
31.Dt ALLOCA 3
32.Os
33.Sh NAME
34.Nm alloca
35.Nd memory allocator
36.Sh SYNOPSIS
37.Fd #include <stdlib.h>
38.Ft void *
39.Fn alloca "size_t size"
40.Sh DESCRIPTION
41The
42.Fn alloca
43function allocates
44.Fa size
45bytes of space in the stack frame of the caller.
46This temporary space is automatically freed on return.
47.Sh RETURN VALUES
48The
49.Fn alloca
50function returns a pointer to the beginning of the allocated space.
51.Sh SEE ALSO
52.Xr pagesize 1 ,
53.Xr brk 2 ,
54.Xr calloc 3 ,
55.Xr malloc 3 ,
56.Xr realloc 3
57.Sh BUGS
58The
59.Fn alloca
60function is machine dependent; its use is discouraged.
61.\" .Sh HISTORY
62.\" The
63.\" .Fn alloca
64.\" function appeared in
65.\" .Bx ?? .
66.\" The function appeared in 32v, pwb and pwb.2 and in 3bsd 4bsd
67.\" The first man page (or link to a man page that I can find at the
68.\" moment is 4.3...
69.Pp
70The
71.Fn alloca
72function is slightly unsafe because it cannot ensure that the pointer
73returned points to a valid and usable block of memory.
74The allocation made may exceed the bounds of the stack, or even go
75further into other objects in memory, and
76.Fn alloca
77cannot determine such an error.
78Avoid
79.Fn alloca
80with large unbounded allocations.
diff --git a/src/lib/libc/stdlib/atexit.3 b/src/lib/libc/stdlib/atexit.3
new file mode 100644
index 0000000000..c8d4ce63d5
--- /dev/null
+++ b/src/lib/libc/stdlib/atexit.3
@@ -0,0 +1,71 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" Chris Torek and the American National Standards Committee X3,
6.\" on Information Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: atexit.3,v 1.5 2003/06/02 20:18:37 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt ATEXIT 3
36.Os
37.Sh NAME
38.Nm atexit
39.Nd register a function to be called on exit
40.Sh SYNOPSIS
41.Fd #include <stdlib.h>
42.Ft int
43.Fn atexit "void (*function)(void)"
44.Sh DESCRIPTION
45The
46.Fn atexit
47function registers the given
48.Fa function
49to be called at program exit, whether via
50.Xr exit 3
51or via return from the program's
52.Fn main .
53Functions so registered are called in reverse order;
54no arguments are passed.
55At least 32 functions can always be registered,
56and more are allowed as long as sufficient memory can be allocated.
57.Sh RETURN VALUES
58.Rv -std atexit
59.Sh ERRORS
60.Bl -tag -width Er
61.It Bq Er ENOMEM
62No memory was available to add the function to the list.
63The existing list of functions is unmodified.
64.El
65.Sh SEE ALSO
66.Xr exit 3
67.Sh STANDARDS
68The
69.Fn atexit
70function conforms to
71.St -ansiC .
diff --git a/src/lib/libc/stdlib/atexit.c b/src/lib/libc/stdlib/atexit.c
new file mode 100644
index 0000000000..4fd2c57318
--- /dev/null
+++ b/src/lib/libc/stdlib/atexit.c
@@ -0,0 +1,133 @@
1/*
2 * Copyright (c) 2002 Daniel Hartmeier
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following
13 * disclaimer in the documentation and/or other materials provided
14 * with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
29 */
30
31#if defined(LIBC_SCCS) && !defined(lint)
32static char *rcsid = "$OpenBSD: atexit.c,v 1.8 2005/03/30 18:51:49 pat Exp $";
33#endif /* LIBC_SCCS and not lint */
34
35#include <sys/types.h>
36#include <sys/mman.h>
37#include <stdlib.h>
38#include <unistd.h>
39#include "atexit.h"
40
41int __atexit_invalid = 1;
42struct atexit *__atexit;
43
44/*
45 * Function pointers are stored in a linked list of pages. The list
46 * is initially empty, and pages are allocated on demand. The first
47 * function pointer in the first allocated page (the last one in
48 * the linked list) is reserved for the cleanup function.
49 *
50 * Outside the following two functions, all pages are mprotect()'ed
51 * to prevent unintentional/malicious corruption.
52 *
53 * The free(malloc(1)) is a workaround causing malloc_init() to
54 * ensure that malloc.c gets the first mmap() call for its sbrk()
55 * games.
56 */
57
58/*
59 * Register a function to be performed at exit.
60 */
61int
62atexit(void (*fn)(void))
63{
64 struct atexit *p = __atexit;
65 int pgsize = getpagesize();
66
67 if (pgsize < sizeof(*p))
68 return (-1);
69 if (p != NULL) {
70 if (p->ind + 1 >= p->max)
71 p = NULL;
72 else if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
73 return (-1);
74 }
75 if (p == NULL) {
76 if (__atexit_invalid) {
77 free(malloc(1));
78 __atexit_invalid = 0;
79 }
80 p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
81 MAP_ANON | MAP_PRIVATE, -1, 0);
82 if (p == MAP_FAILED)
83 return (-1);
84 if (__atexit == NULL) {
85 p->fns[0] = NULL;
86 p->ind = 1;
87 } else
88 p->ind = 0;
89 p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
90 sizeof(p->fns[0]);
91 p->next = __atexit;
92 __atexit = p;
93 }
94 p->fns[p->ind++] = fn;
95 if (mprotect(p, pgsize, PROT_READ))
96 return (-1);
97 return (0);
98}
99
100/*
101 * Register the cleanup function
102 */
103void
104__atexit_register_cleanup(void (*fn)(void))
105{
106 struct atexit *p = __atexit;
107 int pgsize = getpagesize();
108
109 if (pgsize < sizeof(*p))
110 return;
111 while (p != NULL && p->next != NULL)
112 p = p->next;
113 if (p == NULL) {
114 if (__atexit_invalid) {
115 free(malloc(1));
116 __atexit_invalid = 0;
117 }
118 p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
119 MAP_ANON | MAP_PRIVATE, -1, 0);
120 if (p == MAP_FAILED)
121 return;
122 p->ind = 1;
123 p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
124 sizeof(p->fns[0]);
125 p->next = NULL;
126 __atexit = p;
127 } else {
128 if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
129 return;
130 }
131 p->fns[0] = fn;
132 mprotect(p, pgsize, PROT_READ);
133}
diff --git a/src/lib/libc/stdlib/atexit.h b/src/lib/libc/stdlib/atexit.h
new file mode 100644
index 0000000000..21b0c2e532
--- /dev/null
+++ b/src/lib/libc/stdlib/atexit.h
@@ -0,0 +1,41 @@
1/* $OpenBSD: atexit.h,v 1.6 2003/07/31 07:08:42 deraadt Exp $ */
2
3/*
4 * Copyright (c) 2002 Daniel Hartmeier
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * - Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 */
32
33struct atexit {
34 struct atexit *next; /* next in list */
35 int ind; /* next index in this table */
36 int max; /* max entries >= ATEXIT_SIZE */
37 void (*fns[1])(void); /* the table itself */
38};
39
40extern int __atexit_invalid;
41extern struct atexit *__atexit; /* points to head of LIFO stack */
diff --git a/src/lib/libc/stdlib/atof.3 b/src/lib/libc/stdlib/atof.3
new file mode 100644
index 0000000000..c60b9e9fd7
--- /dev/null
+++ b/src/lib/libc/stdlib/atof.3
@@ -0,0 +1,69 @@
1.\" Copyright (c) 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information
6.\" Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: atof.3,v 1.4 2003/06/02 20:18:37 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt ATOF 3
36.Os
37.Sh NAME
38.Nm atof
39.Nd convert
40.Tn ASCII
41string to double
42.Sh SYNOPSIS
43.Fd #include <stdlib.h>
44.Ft double
45.Fn atof "const char *nptr"
46.Sh DESCRIPTION
47The
48.Fn atof
49function converts the initial portion of the string pointed to by
50.Fa nptr
51to
52.Li double
53representation.
54.Pp
55It is equivalent to:
56.Bd -literal -offset indent
57strtod(nptr, (char **)NULL);
58.Ed
59.Sh SEE ALSO
60.Xr atoi 3 ,
61.Xr atol 3 ,
62.Xr strtod 3 ,
63.Xr strtol 3 ,
64.Xr strtoul 3
65.Sh STANDARDS
66The
67.Fn atof
68function conforms to
69.St -ansiC .
diff --git a/src/lib/libc/stdlib/atof.c b/src/lib/libc/stdlib/atof.c
new file mode 100644
index 0000000000..2724530231
--- /dev/null
+++ b/src/lib/libc/stdlib/atof.c
@@ -0,0 +1,40 @@
1/*
2 * Copyright (c) 1988 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: atof.c,v 1.4 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35
36double
37atof(const char *ascii)
38{
39 return(strtod(ascii, (char **)NULL));
40}
diff --git a/src/lib/libc/stdlib/atoi.3 b/src/lib/libc/stdlib/atoi.3
new file mode 100644
index 0000000000..dee8b637a3
--- /dev/null
+++ b/src/lib/libc/stdlib/atoi.3
@@ -0,0 +1,86 @@
1.\" Copyright (c) 1990, 1991, 1993
2.\" The Regents of the University of California. All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information
6.\" Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: atoi.3,v 1.8 2004/08/22 21:47:41 jaredy Exp $
33.\"
34.Dd June 4, 1993
35.Dt ATOI 3
36.Os
37.Sh NAME
38.Nm atoi
39.Nd convert
40.Tn ASCII
41string to integer
42.Sh SYNOPSIS
43.Fd #include <stdlib.h>
44.Ft int
45.Fn atoi "const char *nptr"
46.Sh DESCRIPTION
47The
48.Fn atoi
49function converts the initial portion of the string pointed to by
50.Fa nptr
51to
52.Li integer
53representation.
54.Pp
55It is equivalent to:
56.Bd -literal -offset indent
57(int)strtol(nptr, (char **)NULL, 10);
58.Ed
59.Sh SEE ALSO
60.Xr atof 3 ,
61.Xr atol 3 ,
62.Xr strtod 3 ,
63.Xr strtol 3 ,
64.Xr strtonum 3 ,
65.Xr strtoul 3
66.Sh STANDARDS
67The
68.Fn atoi
69function conforms to
70.St -ansiC .
71.Sh CAVEATS
72.Nm
73does no overflow checking, handles unsigned numbers poorly,
74and handles strings containing trailing extra characters
75(like
76.Dq "123abc" )
77poorly.
78Careful use of
79.Xr strtol 3
80and
81.Xr strtoul 3
82can alleviate these problems,
83but
84.Xr strtonum 3
85can be used to convert numbers from strings much more safely
86and easily.
diff --git a/src/lib/libc/stdlib/atoi.c b/src/lib/libc/stdlib/atoi.c
new file mode 100644
index 0000000000..ea821ced3d
--- /dev/null
+++ b/src/lib/libc/stdlib/atoi.c
@@ -0,0 +1,40 @@
1/*
2 * Copyright (c) 1988 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: atoi.c,v 1.4 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35
36int
37atoi(const char *str)
38{
39 return((int)strtol(str, (char **)NULL, 10));
40}
diff --git a/src/lib/libc/stdlib/atol.3 b/src/lib/libc/stdlib/atol.3
new file mode 100644
index 0000000000..80e54c892d
--- /dev/null
+++ b/src/lib/libc/stdlib/atol.3
@@ -0,0 +1,70 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information
6.\" Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: atol.3,v 1.6 2003/06/02 20:18:37 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt ATOL 3
36.Os
37.Sh NAME
38.Nm atol
39.Nd convert
40.Tn ASCII
41string to long integer
42.Sh SYNOPSIS
43.Fd #include <stdlib.h>
44.Ft long
45.Fn atol "const char *nptr"
46.Sh DESCRIPTION
47The
48.Fn atol
49function converts the initial portion of the string pointed to by
50.Fa nptr
51to
52.Li long integer
53representation.
54.Pp
55It is equivalent to:
56.Bd -literal -offset indent
57strtol(nptr, (char **)NULL, 10);
58.Ed
59.Sh SEE ALSO
60.Xr atof 3 ,
61.Xr atoi 3 ,
62.Xr atoll 3 ,
63.Xr strtod 3 ,
64.Xr strtol 3 ,
65.Xr strtoul 3
66.Sh STANDARDS
67The
68.Fn atol
69function conforms to
70.St -ansiC-99 .
diff --git a/src/lib/libc/stdlib/atol.c b/src/lib/libc/stdlib/atol.c
new file mode 100644
index 0000000000..38236b556c
--- /dev/null
+++ b/src/lib/libc/stdlib/atol.c
@@ -0,0 +1,40 @@
1/*
2 * Copyright (c) 1988 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: atol.c,v 1.4 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35
36long
37atol(const char *str)
38{
39 return(strtol(str, (char **)NULL, 10));
40}
diff --git a/src/lib/libc/stdlib/atoll.3 b/src/lib/libc/stdlib/atoll.3
new file mode 100644
index 0000000000..40584e9d47
--- /dev/null
+++ b/src/lib/libc/stdlib/atoll.3
@@ -0,0 +1,70 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information
6.\" Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: atoll.3,v 1.3 2003/06/02 20:18:37 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt ATOLL 3
36.Os
37.Sh NAME
38.Nm atoll
39.Nd convert
40.Tn ASCII
41string to long long integer
42.Sh SYNOPSIS
43.Fd #include <stdlib.h>
44.Ft long long
45.Fn atoll "const char *nptr"
46.Sh DESCRIPTION
47The
48.Fn atoll
49function converts the initial portion of the string pointed to by
50.Fa nptr
51to
52.Li long integer
53representation.
54.Pp
55It is equivalent to:
56.Bd -literal -offset indent
57strtoll(nptr, (char **)NULL, 10);
58.Ed
59.Sh SEE ALSO
60.Xr atof 3 ,
61.Xr atoi 3 ,
62.Xr atol 3 ,
63.Xr strtod 3 ,
64.Xr strtol 3 ,
65.Xr strtoul 3
66.Sh STANDARDS
67The
68.Fn atoll
69function conforms to
70.St -ansiC-99 .
diff --git a/src/lib/libc/stdlib/atoll.c b/src/lib/libc/stdlib/atoll.c
new file mode 100644
index 0000000000..6786b62e1a
--- /dev/null
+++ b/src/lib/libc/stdlib/atoll.c
@@ -0,0 +1,41 @@
1/*
2 * Copyright (c) 1988 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: atoll.c,v 1.2 2003/06/02 20:18:37 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35
36long long
37atoll(str)
38 const char *str;
39{
40 return(strtoll(str, (char **)NULL, 10));
41}
diff --git a/src/lib/libc/stdlib/bsearch.3 b/src/lib/libc/stdlib/bsearch.3
new file mode 100644
index 0000000000..d1dd9173db
--- /dev/null
+++ b/src/lib/libc/stdlib/bsearch.3
@@ -0,0 +1,84 @@
1.\" Copyright (c) 1990, 1991, 1993, 1994
2.\" The Regents of the University of California. All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information
6.\" Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: bsearch.3,v 1.6 2003/06/02 20:18:37 millert Exp $
33.\"
34.Dd April 19, 1994
35.Dt BSEARCH 3
36.Os
37.Sh NAME
38.Nm bsearch
39.Nd binary search of a sorted table
40.Sh SYNOPSIS
41.Fd #include <stdlib.h>
42.Ft void *
43.Fn bsearch "const void *key" "const void *base" "size_t nmemb" "size_t size" "int (*compar) (const void *, const void *)"
44.Sh DESCRIPTION
45The
46.Fn bsearch
47function searches an array of
48.Fa nmemb
49objects, the initial member of which is
50pointed to by
51.Fa base ,
52for a member that matches the object pointed to by
53.Fa key .
54The size of each member of the array is specified by
55.Fa size .
56.Pp
57The contents of the array should be in ascending sorted order according
58to the comparison function referenced by
59.Fa compar .
60The
61.Fa compar
62routine is expected to have two arguments which point to the
63.Fa key
64object and to an array member, in that order, and should return an integer
65less than, equal to, or greater than zero if the
66.Fa key
67object is found, respectively, to be less than, to match, or be
68greater than the array member.
69.Sh RETURN VALUES
70The
71.Fn bsearch
72function returns a pointer to a matching member of the array, or a null
73pointer if no match is found.
74If two members compare as equal, which member is matched is unspecified.
75.Sh SEE ALSO
76.Xr db 3 ,
77.Xr lsearch 3 ,
78.Xr qsort 3 ,
79.Xr tsearch 3
80.Sh STANDARDS
81The
82.Fn bsearch
83function conforms to
84.St -ansiC .
diff --git a/src/lib/libc/stdlib/bsearch.c b/src/lib/libc/stdlib/bsearch.c
new file mode 100644
index 0000000000..109211da92
--- /dev/null
+++ b/src/lib/libc/stdlib/bsearch.c
@@ -0,0 +1,71 @@
1/*
2 * Copyright (c) 1990 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: bsearch.c,v 1.5 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35
36/*
37 * Perform a binary search.
38 *
39 * The code below is a bit sneaky. After a comparison fails, we
40 * divide the work in half by moving either left or right. If lim
41 * is odd, moving left simply involves halving lim: e.g., when lim
42 * is 5 we look at item 2, so we change lim to 2 so that we will
43 * look at items 0 & 1. If lim is even, the same applies. If lim
44 * is odd, moving right again involes halving lim, this time moving
45 * the base up one item past p: e.g., when lim is 5 we change base
46 * to item 3 and make lim 2 so that we will look at items 3 and 4.
47 * If lim is even, however, we have to shrink it by one before
48 * halving: e.g., when lim is 4, we still looked at item 2, so we
49 * have to make lim 3, then halve, obtaining 1, so that we will only
50 * look at item 3.
51 */
52void *
53bsearch(const void *key, const void *base0, size_t nmemb, size_t size,
54 int (*compar)(const void *, const void *))
55{
56 const char *base = base0;
57 int lim, cmp;
58 const void *p;
59
60 for (lim = nmemb; lim != 0; lim >>= 1) {
61 p = base + (lim >> 1) * size;
62 cmp = (*compar)(key, p);
63 if (cmp == 0)
64 return ((void *)p);
65 if (cmp > 0) { /* key > p: move right */
66 base = (char *)p + size;
67 lim--;
68 } /* else move left */
69 }
70 return (NULL);
71}
diff --git a/src/lib/libc/stdlib/calloc.c b/src/lib/libc/stdlib/calloc.c
new file mode 100644
index 0000000000..7aabed235f
--- /dev/null
+++ b/src/lib/libc/stdlib/calloc.c
@@ -0,0 +1,53 @@
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: calloc.c,v 1.9 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35#include <string.h>
36#include <limits.h>
37#include <errno.h>
38
39void *
40calloc(size_t num, size_t size)
41{
42 void *p;
43
44 if (num && size && SIZE_T_MAX / num < size) {
45 errno = ENOMEM;
46 return NULL;
47 }
48 size *= num;
49 p = malloc(size);
50 if (p)
51 memset(p, 0, size);
52 return(p);
53}
diff --git a/src/lib/libc/stdlib/cfree.c b/src/lib/libc/stdlib/cfree.c
new file mode 100644
index 0000000000..db1fa56039
--- /dev/null
+++ b/src/lib/libc/stdlib/cfree.c
@@ -0,0 +1,44 @@
1/* $OpenBSD: cfree.c,v 1.4 2005/03/30 18:51:49 pat Exp $ */
2
3/*
4 * Copyright (c) 1996 SigmaSoft, Th. Lockert <tholo@sigmasoft.com>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
17 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
18 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
19 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#if defined(LIBC_SCCS) && !defined(lint)
29static char rcsid[] = "$OpenBSD: cfree.c,v 1.4 2005/03/30 18:51:49 pat Exp $";
30#endif /* LIBC_SCCS and not lint */
31
32#include <sys/cdefs.h>
33#include <stdlib.h>
34
35#ifdef __indr_reference
36__indr_reference(free, cfree);
37#else
38
39void
40cfree(void *p)
41{
42 free(p);
43}
44#endif
diff --git a/src/lib/libc/stdlib/div.3 b/src/lib/libc/stdlib/div.3
new file mode 100644
index 0000000000..a75614310e
--- /dev/null
+++ b/src/lib/libc/stdlib/div.3
@@ -0,0 +1,63 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" Chris Torek.
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. Neither the name of the University nor the names of its contributors
15.\" may be used to endorse or promote products derived from this software
16.\" without specific prior written permission.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28.\" SUCH DAMAGE.
29.\"
30.\" $OpenBSD: div.3,v 1.7 2004/01/23 23:08:46 jmc Exp $
31.\"
32.Dd April 19, 1991
33.Dt DIV 3
34.Os
35.Sh NAME
36.Nm div
37.Nd return quotient and remainder from division
38.Sh SYNOPSIS
39.Fd #include <stdlib.h>
40.Ft div_t
41.Fn div "int num" "int denom"
42.Sh DESCRIPTION
43The
44.Fn div
45function computes the value
46.Fa num Ns / Ns Fa denom
47and returns the quotient and remainder in a structure named
48.Fa div_t
49that contains two
50.Li int
51members named
52.Fa quot
53and
54.Fa rem .
55.Sh SEE ALSO
56.Xr ldiv 3 ,
57.Xr math 3 ,
58.Xr qdiv 3
59.Sh STANDARDS
60The
61.Fn div
62function conforms to
63.St -ansiC .
diff --git a/src/lib/libc/stdlib/div.c b/src/lib/libc/stdlib/div.c
new file mode 100644
index 0000000000..32c53dff03
--- /dev/null
+++ b/src/lib/libc/stdlib/div.c
@@ -0,0 +1,74 @@
1/*
2 * Copyright (c) 1990 Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Chris Torek.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char *rcsid = "$OpenBSD: div.c,v 1.4 2005/03/30 18:51:49 pat Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37#include <stdlib.h> /* div_t */
38
39div_t
40div(int num, int denom)
41{
42 div_t r;
43
44 r.quot = num / denom;
45 r.rem = num % denom;
46 /*
47 * The ANSI standard says that |r.quot| <= |n/d|, where
48 * n/d is to be computed in infinite precision. In other
49 * words, we should always truncate the quotient towards
50 * 0, never -infinity.
51 *
52 * Machine division and remainer may work either way when
53 * one or both of n or d is negative. If only one is
54 * negative and r.quot has been truncated towards -inf,
55 * r.rem will have the same sign as denom and the opposite
56 * sign of num; if both are negative and r.quot has been
57 * truncated towards -inf, r.rem will be positive (will
58 * have the opposite sign of num). These are considered
59 * `wrong'.
60 *
61 * If both are num and denom are positive, r will always
62 * be positive.
63 *
64 * This all boils down to:
65 * if num >= 0, but r.rem < 0, we got the wrong answer.
66 * In that case, to get the right answer, add 1 to r.quot and
67 * subtract denom from r.rem.
68 */
69 if (num >= 0 && r.rem < 0) {
70 r.quot++;
71 r.rem -= denom;
72 }
73 return (r);
74}
diff --git a/src/lib/libc/stdlib/drand48.c b/src/lib/libc/stdlib/drand48.c
new file mode 100644
index 0000000000..02886d5b62
--- /dev/null
+++ b/src/lib/libc/stdlib/drand48.c
@@ -0,0 +1,26 @@
1/*
2 * Copyright (c) 1993 Martin Birgmeier
3 * All rights reserved.
4 *
5 * You may redistribute unmodified or modified versions of this source
6 * code provided that the above copyright notice and this and the
7 * following conditions are retained.
8 *
9 * This software is provided ``as is'', and comes with no warranties
10 * of any kind. I shall in no event be liable for anything that happens
11 * to anyone/anything when using this software.
12 */
13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: drand48.c,v 1.2 1996/08/19 08:33:29 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
18#include "rand48.h"
19
20extern unsigned short __rand48_seed[3];
21
22double
23drand48(void)
24{
25 return erand48(__rand48_seed);
26}
diff --git a/src/lib/libc/stdlib/ecvt.3 b/src/lib/libc/stdlib/ecvt.3
new file mode 100644
index 0000000000..689cb1c6f9
--- /dev/null
+++ b/src/lib/libc/stdlib/ecvt.3
@@ -0,0 +1,165 @@
1.\" $OpenBSD: ecvt.3,v 1.7 2004/01/25 14:48:32 jmc Exp $
2.\"
3.\" Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
4.\"
5.\" Permission to use, copy, modify, and distribute this software for any
6.\" purpose with or without fee is hereby granted, provided that the above
7.\" copyright notice and this permission notice appear in all copies.
8.\"
9.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16.\"
17.\" Sponsored in part by the Defense Advanced Research Projects
18.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
19.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
20.\"
21.Dd December 1, 2002
22.Dt ECVT 3
23.Os
24.Sh NAME
25.Nm ecvt ,
26.Nm fcvt ,
27.Nm gcvt
28.Nd convert double to
29.Tn ASCII
30string
31.Sh SYNOPSIS
32.Fd #include <stdlib.h>
33.Ft char *
34.Fn ecvt "double value" "int ndigit" "int *decpt" "int *sign"
35.Ft char *
36.Fn fcvt "double value" "int ndigit" "int *decpt" "int *sign"
37.Ft char *
38.Fn gcvt "double value" "int ndigit" "char *buf"
39.Sh DESCRIPTION
40.Bf -symbolic
41These functions are provided for compatibility with legacy code.
42New code should use the
43.Xr snprintf 3
44function for improved safety and portability.
45.Ef
46.Pp
47The
48.Fn ecvt ,
49.Fn fcvt
50and
51.Fn gcvt
52functions convert the double precision floating-point number
53.Fa value
54to a NUL-terminated
55.Tn ASCII
56string.
57.Pp
58The
59.Fn ecvt
60function converts
61.Fa value
62to a NUL-terminated string of exactly
63.Fa ndigit
64digits and returns a pointer to that string.
65The result is padded with zeroes from left to right as needed.
66There are no leading zeroes unless
67.Fa value
68itself is 0.
69The least significant digit is rounded in an implementation-dependent manner.
70The position of the decimal point relative to the beginning of the string
71is stored in
72.Fa decpt .
73A negative value indicates that the decimal point is located
74to the left of the returned digits (this occurs when there is no
75whole number component to
76.Fa value ) .
77If
78.Fa value
79is zero, it is unspecified whether the integer pointed to by
80.Fa decpt
81will be 0 or 1.
82The decimal point itself is not included in the returned string.
83If the sign of the result is negative, the integer pointed to by
84.Fa sign
85is non-zero; otherwise, it is 0.
86.Pp
87If the converted value is out of range or is not representable,
88the contents of the returned string are unspecified.
89.Pp
90The
91.Fn fcvt
92function is identical to
93.Fn ecvt
94with the exception that
95.Fa ndigit
96specifies the number of digits after the decimal point (zero-padded as
97needed).
98.Pp
99The
100.Fn gcvt
101function converts
102.Fa value
103to a NUL-terminated string similar to the %g
104.Xr printf 3
105format specifier and stores the result in
106.Fa buf .
107It produces
108.Fa ndigit
109significant digits similar to the %f
110.Xr printf 3
111format specifier where possible.
112If
113.Fa ndigit
114does allow sufficient precision, the result is stored in
115exponential notation similar to the %e
116.Xr printf 3
117format specifier.
118If
119.Fa value
120is less than zero,
121.Fa buf
122will be prefixed with a minus sign.
123A decimal point is included in the returned string if
124.Fa value
125is not a whole number.
126Unlike the
127.Fn ecvt
128and
129.Fn fcvt
130functions,
131.Fa buf
132is not zero-padded.
133.Sh RETURN VALUES
134The
135.Fn ecvt ,
136.Fn fcvt
137and
138.Fn gcvt
139functions return a NUL-terminated string representation of
140.Fa value .
141.Sh WARNINGS
142The
143.Fn ecvt
144and
145.Fn fcvt
146functions return a pointer to internal storage space that will be
147overwritten by subsequent calls to either function.
148.Pp
149The maximum possible precision of the return value is limited by the
150precision of a double and may not be the same on all architectures.
151.Pp
152The
153.Xr snprintf 3
154function is preferred over these functions for new code.
155.Sh SEE ALSO
156.Xr printf 3 ,
157.Xr strtod 3
158.Sh STANDARDS
159The
160.Fn ecvt ,
161.Fn fcvt
162and
163.Fn gcvt
164functions conform to
165.St -p1003.1-2001 .
diff --git a/src/lib/libc/stdlib/ecvt.c b/src/lib/libc/stdlib/ecvt.c
new file mode 100644
index 0000000000..657c531808
--- /dev/null
+++ b/src/lib/libc/stdlib/ecvt.c
@@ -0,0 +1,103 @@
1/* $OpenBSD: ecvt.c,v 1.3 2003/06/17 21:56:24 millert Exp $ */
2
3/*
4 * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * Sponsored in part by the Defense Advanced Research Projects
19 * Agency (DARPA) and Air Force Research Laboratory, Air Force
20 * Materiel Command, USAF, under agreement number F39502-99-1-0512.
21 */
22
23#if defined(LIBC_SCCS) && !defined(lint)
24static char rcsid[] = "$OpenBSD: ecvt.c,v 1.3 2003/06/17 21:56:24 millert Exp $";
25#endif /* LIBC_SCCS and not lint */
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30
31extern char *__dtoa(double, int, int, int *, int *, char **);
32static char *__cvt(double, int, int *, int *, int, int);
33
34static char *
35__cvt(double value, int ndigit, int *decpt, int *sign, int fmode, int pad)
36{
37 static char *s;
38 char *p, *rve;
39 size_t siz;
40
41 if (ndigit == 0) {
42 *sign = value < 0.0;
43 *decpt = 0;
44 return ("");
45 }
46
47 if (s) {
48 free(s);
49 s = NULL;
50 }
51
52 if (ndigit < 0)
53 siz = -ndigit + 1;
54 else
55 siz = ndigit + 1;
56
57
58 /* __dtoa() doesn't allocate space for 0 so we do it by hand */
59 if (value == 0.0) {
60 *decpt = 1 - fmode; /* 1 for 'e', 0 for 'f' */
61 *sign = 0;
62 if ((rve = s = (char *)malloc(siz)) == NULL)
63 return(NULL);
64 *rve++ = '0';
65 *rve = '\0';
66 } else {
67 p = __dtoa(value, fmode + 2, ndigit, decpt, sign, &rve);
68 if (*decpt == 9999) {
69 /* Nan or Infinity */
70 *decpt = 0;
71 return(p);
72 }
73 /* make a local copy and adjust rve to be in terms of s */
74 if (pad && fmode)
75 siz += *decpt;
76 if ((s = (char *)malloc(siz)) == NULL)
77 return(NULL);
78 (void) strlcpy(s, p, siz);
79 rve = s + (rve - p);
80 }
81
82 /* Add trailing zeros (unless we got NaN or Inf) */
83 if (pad && *decpt != 9999) {
84 siz -= rve - s;
85 while (--siz)
86 *rve++ = '0';
87 *rve = '\0';
88 }
89
90 return(s);
91}
92
93char *
94ecvt(double value, int ndigit, int *decpt, int *sign)
95{
96 return(__cvt(value, ndigit, decpt, sign, 0, 1));
97}
98
99char *
100fcvt(double value, int ndigit, int *decpt, int *sign)
101{
102 return(__cvt(value, ndigit, decpt, sign, 1, 1));
103}
diff --git a/src/lib/libc/stdlib/erand48.c b/src/lib/libc/stdlib/erand48.c
new file mode 100644
index 0000000000..b92dacffcc
--- /dev/null
+++ b/src/lib/libc/stdlib/erand48.c
@@ -0,0 +1,27 @@
1/*
2 * Copyright (c) 1993 Martin Birgmeier
3 * All rights reserved.
4 *
5 * You may redistribute unmodified or modified versions of this source
6 * code provided that the above copyright notice and this and the
7 * following conditions are retained.
8 *
9 * This software is provided ``as is'', and comes with no warranties
10 * of any kind. I shall in no event be liable for anything that happens
11 * to anyone/anything when using this software.
12 */
13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: erand48.c,v 1.2 1996/08/19 08:33:29 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
18#include "rand48.h"
19
20double
21erand48(unsigned short xseed[3])
22{
23 __dorand48(xseed);
24 return ldexp((double) xseed[0], -48) +
25 ldexp((double) xseed[1], -32) +
26 ldexp((double) xseed[2], -16);
27}
diff --git a/src/lib/libc/stdlib/exit.3 b/src/lib/libc/stdlib/exit.3
new file mode 100644
index 0000000000..fa233ac75f
--- /dev/null
+++ b/src/lib/libc/stdlib/exit.3
@@ -0,0 +1,114 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information
6.\" Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: exit.3,v 1.10 2004/05/03 17:21:13 millert Exp $
33.\"
34.Dd January 21, 2004
35.Dt EXIT 3
36.Os
37.Sh NAME
38.Nm exit, _Exit
39.Nd perform normal program termination
40.Sh SYNOPSIS
41.Fd #include <stdlib.h>
42.Ft void
43.Fn exit "int status"
44.Ft void
45.Fn _Exit "int status"
46.Sh DESCRIPTION
47The
48.Fn exit
49and
50.Fn _Exit
51functions terminate a process.
52.Pp
53Before termination,
54.Fn exit
55performs the following operations in the order listed:
56.Bl -enum -offset indent
57.It
58Call the functions registered with the
59.Xr atexit 3
60function, in the reverse order of their registration.
61.It
62Flush all open output streams.
63.It
64Close all open streams.
65.It
66Unlink all files created with the
67.Xr tmpfile 3
68function.
69.El
70.Pp
71The
72.Fn _Exit
73function terminates without calling the functions registered with the
74.Xr atexit 3
75function.
76The
77.Ox
78implementation of
79.Fn _Exit
80does not flush open output streams or unlink files created with the
81.Xr tmpfile 3
82function.
83However, this behavior is implementation-specific.
84.Pp
85Lastly,
86.Fn exit
87and
88.Fn _Exit
89call
90.Xr _exit 2 .
91Note that typically
92.Xr _exit 2
93only passes the lower 8 bits of
94.Fa status
95on to the parent, thus negative values have less meaning.
96.Sh RETURN VALUES
97The
98.Fn exit
99and
100.Fn _Exit
101functions never return.
102.Sh SEE ALSO
103.Xr _exit 2 ,
104.Xr atexit 3 ,
105.Xr intro 3 ,
106.Xr sysexits 3 ,
107.Xr tmpfile 3
108.Sh STANDARDS
109The
110.Fn exit
111and
112.Fn _Exit
113functions conform to
114.St -ansiC-99 .
diff --git a/src/lib/libc/stdlib/exit.c b/src/lib/libc/stdlib/exit.c
new file mode 100644
index 0000000000..a0960e83c4
--- /dev/null
+++ b/src/lib/libc/stdlib/exit.c
@@ -0,0 +1,72 @@
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: exit.c,v 1.10 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35#include <sys/mman.h>
36#include <stdlib.h>
37#include <unistd.h>
38#include "atexit.h"
39#include "thread_private.h"
40
41/*
42 * This variable is zero until a process has created a thread.
43 * It is used to avoid calling locking functions in libc when they
44 * are not required. By default, libc is intended to be(come)
45 * thread-safe, but without a (significant) penalty to non-threaded
46 * processes.
47 */
48int __isthreaded = 0;
49
50/*
51 * Exit, flushing stdio buffers if necessary.
52 */
53void
54exit(int status)
55{
56 struct atexit *p, *q;
57 int n, pgsize = getpagesize();
58
59 if (!__atexit_invalid) {
60 p = __atexit;
61 while (p != NULL) {
62 for (n = p->ind; --n >= 0;)
63 if (p->fns[n] != NULL)
64 (*p->fns[n])();
65 q = p;
66 p = p->next;
67 munmap(q, pgsize);
68 }
69 }
70 /* cleanup, if registered, was called through fns[0] in the last page */
71 _exit(status);
72}
diff --git a/src/lib/libc/stdlib/gcvt.c b/src/lib/libc/stdlib/gcvt.c
new file mode 100644
index 0000000000..9fd664b346
--- /dev/null
+++ b/src/lib/libc/stdlib/gcvt.c
@@ -0,0 +1,99 @@
1/* $OpenBSD: gcvt.c,v 1.5 2003/06/17 21:56:24 millert Exp $ */
2
3/*
4 * Copyright (c) 2002, 2003 Todd C. Miller <Todd.Miller@courtesan.com>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * Sponsored in part by the Defense Advanced Research Projects
19 * Agency (DARPA) and Air Force Research Laboratory, Air Force
20 * Materiel Command, USAF, under agreement number F39502-99-1-0512.
21 */
22
23#if defined(LIBC_SCCS) && !defined(lint)
24static char rcsid[] = "$OpenBSD: gcvt.c,v 1.5 2003/06/17 21:56:24 millert Exp $";
25#endif /* LIBC_SCCS and not lint */
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30
31extern char *__dtoa(double, int, int, int *, int *, char **);
32
33char *
34gcvt(double value, int ndigit, char *buf)
35{
36 char *digits, *dst, *src;
37 int i, decpt, sign;
38
39 if (ndigit == 0) {
40 buf[0] = '\0';
41 return (buf);
42 }
43
44 digits = __dtoa(value, 2, ndigit, &decpt, &sign, NULL);
45 if (decpt == 9999) {
46 /* Infinity or NaN, assume buffer is at least ndigit long. */
47 strlcpy(buf, digits, ndigit + 1);
48 return (buf);
49 }
50
51 dst = buf;
52 if (sign)
53 *dst++ = '-';
54
55 if (decpt < 0 || decpt > ndigit) {
56 /* exponential format */
57 if (--decpt < 0) {
58 sign = 1;
59 decpt = -decpt;
60 } else
61 sign = 0;
62 for (src = digits; *src != '\0'; )
63 *dst++ = *src++;
64 *dst++ = 'e';
65 if (sign)
66 *dst++ = '-';
67 else
68 *dst++ = '+';
69 if (decpt < 10) {
70 *dst++ = '0';
71 *dst++ = '0' + decpt;
72 *dst = '\0';
73 } else {
74 /* XXX - optimize */
75 for (sign = decpt, i = 0; (sign /= 10) != 0; i++)
76 sign /= 10;
77 while (decpt != 0) {
78 dst[i--] = '0' + decpt % 10;
79 decpt /= 10;
80 }
81 }
82 } else {
83 /* standard format */
84 for (i = 0, src = digits; i < decpt; i++) {
85 if (*src != '\0')
86 *dst++ = *src++;
87 else
88 *dst++ = '0';
89 }
90 if (*src != '\0') {
91 *dst++ = '.'; /* XXX - locale-specific (LC_NUMERIC) */
92 for (i = decpt; digits[i] != '\0'; i++) {
93 *dst++ = digits[i];
94 }
95 }
96 *dst = '\0';
97 }
98 return (buf);
99}
diff --git a/src/lib/libc/stdlib/getenv.3 b/src/lib/libc/stdlib/getenv.3
new file mode 100644
index 0000000000..054004e1d8
--- /dev/null
+++ b/src/lib/libc/stdlib/getenv.3
@@ -0,0 +1,142 @@
1.\" Copyright (c) 1988, 1991, 1993
2.\" The Regents of the University of California. All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information
6.\" Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: getenv.3,v 1.9 2004/01/23 23:08:46 jmc Exp $
33.\"
34.Dd December 11, 1993
35.Dt GETENV 3
36.Os
37.Sh NAME
38.Nm getenv ,
39.Nm putenv ,
40.Nm setenv ,
41.Nm unsetenv
42.Nd environment variable functions
43.Sh SYNOPSIS
44.Fd #include <stdlib.h>
45.Ft char *
46.Fn getenv "const char *name"
47.Ft int
48.Fn setenv "const char *name" "const char *value" "int overwrite"
49.Ft int
50.Fn putenv "const char *string"
51.Ft void
52.Fn unsetenv "const char *name"
53.Sh DESCRIPTION
54These functions set, unset, and fetch environment variables from the host
55.Em environment list .
56For compatibility with differing environment conventions, the given arguments
57.Fa name
58and
59.Fa value
60may be appended and prepended, respectively, with an equal sign
61.Dq Li \&= .
62.Pp
63The
64.Fn getenv
65function obtains the current value of the environment variable,
66.Fa name .
67If the variable
68.Fa name
69is not in the current environment, a null pointer is returned.
70.Pp
71The
72.Fn setenv
73function inserts or resets the environment variable
74.Fa name
75in the current environment list.
76If the variable
77.Fa name
78does not exist in the list, it is inserted with the given
79.Fa value .
80If the variable does exist, the argument
81.Fa overwrite
82is tested; if
83.Fa overwrite
84is zero, the variable is not reset, otherwise it is reset to the given
85.Fa value .
86.Pp
87The
88.Fn putenv
89function takes an argument of the form
90.Ar name Ns = Ns Ar value
91and is equivalent to:
92.Bd -literal -offset indent
93setenv(name, value, 1);
94.Ed
95.Pp
96The
97.Fn unsetenv
98function deletes all instances of the variable name pointed to by
99.Fa name
100from the list.
101.Sh RETURN VALUES
102The functions
103.Fn setenv
104and
105.Fn putenv
106return zero if successful; otherwise the global variable
107.Va errno
108is set to indicate the error and \-1 is returned.
109.Pp
110If
111.Fn getenv
112is successful, the string returned should be considered read-only.
113.Sh ERRORS
114.Bl -tag -width [ENOMEM]
115.It Bq Er ENOMEM
116The function
117.Fn setenv
118or
119.Fn putenv
120failed because they were unable to allocate memory for the environment.
121.El
122.Sh SEE ALSO
123.Xr csh 1 ,
124.Xr sh 1 ,
125.Xr execve 2 ,
126.Xr environ 7
127.Sh STANDARDS
128The
129.Fn getenv
130function conforms to
131.St -ansiC .
132.Sh HISTORY
133The functions
134.Fn setenv
135and
136.Fn unsetenv
137appeared in
138.At v7 .
139The
140.Fn putenv
141function appeared in
142.Bx 4.3 Reno .
diff --git a/src/lib/libc/stdlib/getenv.c b/src/lib/libc/stdlib/getenv.c
new file mode 100644
index 0000000000..7e4d6b91a9
--- /dev/null
+++ b/src/lib/libc/stdlib/getenv.c
@@ -0,0 +1,83 @@
1/*
2 * Copyright (c) 1987, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: getenv.c,v 1.7 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35#include <string.h>
36
37char *__findenv(const char *name, int *offset);
38
39/*
40 * __findenv --
41 * Returns pointer to value associated with name, if any, else NULL.
42 * Sets offset to be the offset of the name/value combination in the
43 * environmental array, for use by setenv(3) and unsetenv(3).
44 * Explicitly removes '=' in argument name.
45 *
46 * This routine *should* be a static; don't use it.
47 */
48char *
49__findenv(const char *name, int *offset)
50{
51 extern char **environ;
52 int len, i;
53 const char *np;
54 char **p, *cp;
55
56 if (name == NULL || environ == NULL)
57 return (NULL);
58 for (np = name; *np && *np != '='; ++np)
59 ;
60 len = np - name;
61 for (p = environ; (cp = *p) != NULL; ++p) {
62 for (np = name, i = len; i && *cp; i--)
63 if (*cp++ != *np++)
64 break;
65 if (i == 0 && *cp++ == '=') {
66 *offset = p - environ;
67 return (cp);
68 }
69 }
70 return (NULL);
71}
72
73/*
74 * getenv --
75 * Returns ptr to value associated with name, if any, else NULL.
76 */
77char *
78getenv(const char *name)
79{
80 int offset;
81
82 return (__findenv(name, &offset));
83}
diff --git a/src/lib/libc/stdlib/getopt.3 b/src/lib/libc/stdlib/getopt.3
new file mode 100644
index 0000000000..e0dc3701f9
--- /dev/null
+++ b/src/lib/libc/stdlib/getopt.3
@@ -0,0 +1,372 @@
1.\" Copyright (c) 1988, 1991, 1993
2.\" The Regents of the University of California. All rights reserved.
3.\"
4.\" Redistribution and use in source and binary forms, with or without
5.\" modification, are permitted provided that the following conditions
6.\" are met:
7.\" 1. Redistributions of source code must retain the above copyright
8.\" notice, this list of conditions and the following disclaimer.
9.\" 2. Redistributions in binary form must reproduce the above copyright
10.\" notice, this list of conditions and the following disclaimer in the
11.\" documentation and/or other materials provided with the distribution.
12.\" 3. Neither the name of the University nor the names of its contributors
13.\" may be used to endorse or promote products derived from this software
14.\" without specific prior written permission.
15.\"
16.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
17.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26.\" SUCH DAMAGE.
27.\"
28.\" $OpenBSD: getopt.3,v 1.31 2005/03/26 22:02:15 millert Exp $
29.\"
30.Dd December 17, 2002
31.Dt GETOPT 3
32.Os
33.Sh NAME
34.Nm getopt
35.Nd get option character from command line argument list
36.Sh SYNOPSIS
37.Fd #include <unistd.h>
38.Vt extern char *optarg;
39.Vt extern int opterr;
40.Vt extern int optind;
41.Vt extern int optopt;
42.Vt extern int optreset;
43.Ft int
44.Fn getopt "int argc" "char * const *argv" "const char *optstring"
45.Sh DESCRIPTION
46The
47.Fn getopt
48function incrementally parses a command line argument list
49.Fa argv
50and returns the next
51.Em known
52option character.
53An option character is
54.Em known
55if it has been specified in the string of accepted option characters,
56.Fa optstring .
57.Pp
58The option string
59.Fa optstring
60may contain the following elements: individual characters,
61characters followed by a colon, and characters followed by two colons.
62A character followed by a single colon indicates that an argument
63is to follow the option on the command line.
64Two colons indicates that the argument is optional \- this is an
65extension not covered by POSIX.
66For example, an option string
67.Qq x
68recognizes an option
69.Fl x ,
70and an option string
71.Qq Li x:
72recognizes an option and argument
73.Fl x Ar argument .
74It does not matter to
75.Fn getopt
76if a following argument has leading whitespace.
77.Pp
78On return from
79.Fn getopt ,
80.Va optarg
81points to an option argument, if it is anticipated,
82and the variable
83.Va optind
84contains the index to the next
85.Fa argv
86argument for a subsequent call
87to
88.Fn getopt .
89.Pp
90The variables
91.Va opterr
92and
93.Va optind
94are both initialized to 1.
95The
96.Va optind
97variable may be set to another value larger than 0 before a set of calls to
98.Fn getopt
99in order to skip over more or less
100.Fa argv
101entries.
102An
103.Va optind
104value of 0 is reserved for compatibility with GNU
105.Fn getopt .
106.Pp
107In order to use
108.Fn getopt
109to evaluate multiple sets of arguments, or to evaluate a single set of
110arguments multiple times,
111the variable
112.Va optreset
113must be set to 1 before the second and each additional set of calls to
114.Fn getopt ,
115and the variable
116.Va optind
117must be reinitialized.
118.Pp
119The
120.Fn getopt
121function returns \-1 when the argument list is exhausted.
122The interpretation of options in the argument list may be cancelled
123by the option
124.Ql --
125(double dash) which causes
126.Fn getopt
127to signal the end of argument processing and return \-1.
128When all options have been processed (i.e., up to the first non-option
129argument),
130.Fn getopt
131returns \-1.
132.Sh RETURN VALUES
133The
134.Fn getopt
135function returns the next known option character in
136.Fa optstring .
137If
138.Fn getopt
139encounters a character not found in
140.Fa optstring
141or if it detects a missing option argument,
142it returns
143.Sq \&?
144(question mark).
145If
146.Fa optstring
147has a leading
148.Sq \&:
149then a missing option argument causes
150.Sq \&:
151to be returned instead of
152.Sq \&? .
153In either case, the variable
154.Va optopt
155is set to the character that caused the error.
156The
157.Fn getopt
158function returns \-1 when the argument list is exhausted.
159.Sh ENVIRONMENT
160.Bl -tag -width POSIXLY_CORRECTXX
161.It Ev POSIXLY_CORRECT
162If set, a leading
163.Sq -
164in
165.Ar optstring
166is ignored.
167.El
168.Sh EXAMPLES
169.Bd -literal -compact
170extern char *optarg;
171extern int optind;
172int bflag, ch, fd;
173
174bflag = 0;
175while ((ch = getopt(argc, argv, "bf:")) != -1) {
176 switch (ch) {
177 case 'b':
178 bflag = 1;
179 break;
180 case 'f':
181 if ((fd = open(optarg, O_RDONLY, 0)) < 0) {
182 (void)fprintf(stderr,
183 "myname: %s: %s\en", optarg, strerror(errno));
184 exit(1);
185 }
186 break;
187 case '?':
188 default:
189 usage();
190 }
191}
192argc -= optind;
193argv += optind;
194.Ed
195.Sh DIAGNOSTICS
196If the
197.Fn getopt
198function encounters a character not found in the string
199.Fa optstring
200or detects
201a missing option argument it writes an error message to
202.Em stderr
203and returns
204.Ql \&? .
205Setting
206.Va opterr
207to a zero will disable these error messages.
208If
209.Fa optstring
210has a leading
211.Ql \&:
212then a missing option argument causes a
213.Ql \&:
214to be returned in addition to suppressing any error messages.
215.Pp
216Option arguments are allowed to begin with
217.Ql - ;
218this is reasonable but reduces the amount of error checking possible.
219.Sh SEE ALSO
220.Xr getopt 1 ,
221.Xr getopt_long 3 ,
222.Xr getsubopt 3
223.Sh STANDARDS
224The
225.Fn getopt
226function implements a superset of the functionality specified by
227.St -p1003.1 .
228.Pp
229The following extensions are supported:
230.Bl -tag -width "xxx"
231.It Li o
232The
233.Va optreset
234variable was added to make it possible to call the
235.Fn getopt
236function multiple times.
237.It Li o
238If the
239.Va optind
240variable is set to 0,
241.Fn getopt
242will behave as if the
243.Va optreset
244variable has been set.
245This is for compatibility with
246.Tn GNU
247.Fn getopt .
248New code should use
249.Va optreset
250instead.
251.It Li o
252If the first character of
253.Fa optstring
254is a plus sign
255.Pq Ql + ,
256it will be ignored.
257This is for compatibility with
258.Tn GNU
259.Fn getopt .
260.It Li o
261If the first character of
262.Fa optstring
263is a dash
264.Pq Ql - ,
265non-options will be returned as arguments to the option character
266.Ql \e1 .
267This is for compatibility with
268.Tn GNU
269.Fn getopt .
270.It Li o
271A single dash
272.Pq Ql -
273may be specified as a character in
274.Fa optstring ,
275however it should
276.Em never
277have an argument associated with it.
278This allows
279.Fn getopt
280to be used with programs that expect
281.Ql -
282as an option flag.
283This practice is wrong, and should not be used in any current development.
284It is provided for backward compatibility
285.Em only .
286Care should be taken not to use
287.Ql -
288as the first character in
289.Fa optstring
290to avoid a semantic conflict with
291.Tn GNU
292.Fn getopt
293semantics (see above).
294By default, a single dash causes
295.Fn getopt
296to return \-1.
297.El
298.Pp
299Unlike
300.Tn GNU
301.Fn getopt ,
302.Ox
303does not permute the argument vector to allow non-options to be
304interspersed with options on the command line.
305Programs requiring this behavior should use
306.Xr getopt_long 3
307instead.
308Because of this (and unlike
309.Tn GNU ) ,
310the
311.Ox
312.Fn getopt
313supports optional arguments separated by whitespace.
314.Pp
315Historic
316.Bx
317versions of
318.Fn getopt
319set
320.Fa optopt
321to the last option character processed.
322However, this conflicts with
323.St -p1003.1
324which stipulates that
325.Fa optopt
326be set to the last character that caused an error.
327.Sh HISTORY
328The
329.Fn getopt
330function appeared in
331.Bx 4.3 .
332.Sh BUGS
333The
334.Fn getopt
335function was once specified to return
336.Dv EOF
337instead of \-1.
338This was changed by
339.St -p1003.2-92
340to decouple
341.Fn getopt
342from
343.Aq Pa stdio.h .
344.Pp
345It is possible to handle digits as option letters.
346This allows
347.Fn getopt
348to be used with programs that expect a number
349.Pq Dq Li \-3
350as an option.
351This practice is wrong, and should not be used in any current development.
352It is provided for backward compatibility
353.Em only .
354The following code fragment works in most cases.
355.Bd -literal -offset indent
356int ch;
357long length;
358char *p;
359
360while ((ch = getopt(argc, argv, "0123456789")) != -1) {
361 switch (ch) {
362 case '0': case '1': case '2': case '3': case '4':
363 case '5': case '6': case '7': case '8': case '9':
364 p = argv[optind - 1];
365 if (p[0] == '-' && p[1] == ch && !p[2])
366 length = ch - '0';
367 else
368 length = strtol(argv[optind] + 1, NULL, 10);
369 break;
370 }
371}
372.Ed
diff --git a/src/lib/libc/stdlib/getopt_long.3 b/src/lib/libc/stdlib/getopt_long.3
new file mode 100644
index 0000000000..978583ef96
--- /dev/null
+++ b/src/lib/libc/stdlib/getopt_long.3
@@ -0,0 +1,377 @@
1.\" $OpenBSD: getopt_long.3,v 1.10 2004/01/06 23:44:28 fgsch Exp $
2.\" $NetBSD: getopt_long.3,v 1.11 2002/10/02 10:54:19 wiz Exp $
3.\"
4.\" Copyright (c) 1988, 1991, 1993
5.\" The Regents of the University of California. All rights reserved.
6.\"
7.\" Redistribution and use in source and binary forms, with or without
8.\" modification, are permitted provided that the following conditions
9.\" are met:
10.\" 1. Redistributions of source code must retain the above copyright
11.\" notice, this list of conditions and the following disclaimer.
12.\" 2. Redistributions in binary form must reproduce the above copyright
13.\" notice, this list of conditions and the following disclaimer in the
14.\" documentation and/or other materials provided with the distribution.
15.\" 3. Neither the name of the University nor the names of its contributors
16.\" may be used to endorse or promote products derived from this software
17.\" without specific prior written permission.
18.\"
19.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29.\" SUCH DAMAGE.
30.\"
31.\" @(#)getopt.3 8.5 (Berkeley) 4/27/95
32.\"
33.Dd April 1, 2000
34.Dt GETOPT_LONG 3
35.Os
36.Sh NAME
37.Nm getopt_long ,
38.Nm getopt_long_only
39.Nd get long options from command line argument list
40.Sh SYNOPSIS
41.Fd #include <getopt.h>
42.Vt extern char *optarg;
43.Vt extern int optind;
44.Vt extern int optopt;
45.Vt extern int opterr;
46.Vt extern int optreset;
47.Ft int
48.Fn getopt_long "int argc" "char * const *argv" "const char *optstring" "const struct option *longopts" "int *longindex"
49.Ft int
50.Fn getopt_long_only "int argc" "char * const *argv" "const char *optstring" "const struct option *longopts" "int *longindex"
51.Sh DESCRIPTION
52The
53.Fn getopt_long
54function is similar to
55.Xr getopt 3
56but it accepts options in two forms: words and characters.
57The
58.Fn getopt_long
59function provides a superset of the functionality of
60.Xr getopt 3 .
61.Fn getopt_long
62can be used in two ways.
63In the first way, every long option understood by the program has a
64corresponding short option, and the option structure is only used to
65translate from long options to short options.
66When used in this fashion,
67.Fn getopt_long
68behaves identically to
69.Xr getopt 3 .
70This is a good way to add long option processing to an existing program
71with the minimum of rewriting.
72.Pp
73In the second mechanism, a long option sets a flag in the
74.Fa option
75structure passed, or will store a pointer to the command line argument
76in the
77.Fa option
78structure passed to it for options that take arguments.
79Additionally, the long option's argument may be specified as a single
80argument with an equal sign, e.g.
81.Bd -literal
82myprogram --myoption=somevalue
83.Ed
84.Pp
85When a long option is processed the call to
86.Fn getopt_long
87will return 0.
88For this reason, long option processing without
89shortcuts is not backwards compatible with
90.Xr getopt 3 .
91.Pp
92It is possible to combine these methods, providing for long options
93processing with short option equivalents for some options.
94Less frequently used options would be processed as long options only.
95.Pp
96The
97.Fn getopt_long
98call requires a structure to be initialized describing the long
99options.
100The structure is:
101.Bd -literal
102struct option {
103 char *name;
104 int has_arg;
105 int *flag;
106 int val;
107};
108.Ed
109.Pp
110The
111.Fa name
112field should contain the option name without the leading double dash.
113.Pp
114The
115.Fa has_arg
116field should be one of:
117.Bl -tag -width "optional_argument"
118.It Li no_argument
119no argument to the option is expect.
120.It Li required_argument
121an argument to the option is required.
122.It Li optional_argument
123an argument to the option may be presented.
124.El
125.Pp
126If
127.Fa flag
128is not
129.Dv NULL ,
130then the integer pointed to by it will be set to the value in the
131.Fa val
132field.
133If the
134.Fa flag
135field is
136.Dv NULL ,
137then the
138.Fa val
139field will be returned.
140Setting
141.Fa flag
142to
143.Dv NULL
144and setting
145.Fa val
146to the corresponding short option will make this function act just
147like
148.Xr getopt 3 .
149.Pp
150If the
151.Fa longindex
152field is not
153.Dv NULL ,
154then the integer pointed to by it will be set to the index of the long
155option relative to
156.Fa longopts .
157.Pp
158The last element of the
159.Fa longopts
160array has to be filled with zeroes.
161.Pp
162The
163.Fn getopt_long_only
164function behaves identically to
165.Fn getopt_long
166with the exception that long options may start with
167.Sq -
168in addition to
169.Sq -- .
170If an option starting with
171.Sq -
172does not match a long option but does match a single-character option,
173the single-character option is returned.
174.Sh RETURN VALUES
175If the
176.Fa flag
177field in
178.Li struct option
179is
180.Dv NULL ,
181.Fn getopt_long
182and
183.Fn getopt_long_only
184return the value specified in the
185.Fa val
186field, which is usually just the corresponding short option.
187If
188.Fa flag
189is not
190.Dv NULL ,
191these functions return 0 and store
192.Fa val
193in the location pointed to by
194.Fa flag .
195These functions return
196.Sq \:
197if there was a missing option argument,
198.Sq \&?
199if the user specified an unknown or ambiguous option, and
200\-1 when the argument list has been exhausted.
201.Sh EXAMPLES
202.Bd -literal -compact
203int bflag, ch, fd;
204int daggerset;
205
206/* options descriptor */
207static struct option longopts[] = {
208 { "buffy", no_argument, NULL, 'b' },
209 { "fluoride", required_argument, NULL, 'f' },
210 { "daggerset", no_argument, &daggerset, 1 },
211 { NULL, 0, NULL, 0 }
212};
213
214bflag = 0;
215while ((ch = getopt_long(argc, argv, "bf:", longopts, NULL)) != -1)
216 switch (ch) {
217 case 'b':
218 bflag = 1;
219 break;
220 case 'f':
221 if ((fd = open(optarg, O_RDONLY, 0)) == -1)
222 err(1, "unable to open %s", optarg);
223 break;
224 case 0:
225 if (daggerset) {
226 fprintf(stderr,"Buffy will use her dagger to "
227 "apply fluoride to dracula's teeth\en");
228 }
229 break;
230 default:
231 usage();
232}
233argc -= optind;
234argv += optind;
235.Ed
236.Sh IMPLEMENTATION DIFFERENCES
237This section describes differences to the GNU implementation
238found in glibc-2.1.3:
239.Bl -tag -width "xxx"
240.It Li o
241handling of - as first char of option string in presence of
242environment variable POSIXLY_CORRECT:
243.Bl -tag -width "OpenBSD"
244.It Li GNU
245ignores POSIXLY_CORRECT and returns non-options as
246arguments to option '\e1'.
247.It Li OpenBSD
248honors POSIXLY_CORRECT and stops at the first non-option.
249.El
250.It Li o
251handling of - within the option string (not the first character):
252.Bl -tag -width "OpenBSD"
253.It Li GNU
254treats a
255.Ql -
256on the command line as a non-argument.
257.It Li OpenBSD
258a
259.Ql -
260within the option string matches a
261.Ql -
262(single dash) on the command line.
263This functionality is provided for backward compatibility with
264programs, such as
265.Xr su 1 ,
266that use
267.Ql -
268as an option flag.
269This practice is wrong, and should not be used in any current development.
270.El
271.It Li o
272handling of :: in options string in presence of POSIXLY_CORRECT:
273.Bl -tag -width "OpenBSD"
274.It Li Both
275GNU and OpenBSD ignore POSIXLY_CORRECT here and take :: to
276mean the preceding option takes an optional argument.
277.El
278.It Li o
279return value in case of missing argument if first character
280(after + or -) in option string is not ':':
281.Bl -tag -width "OpenBSD"
282.It Li GNU
283returns '?'
284.It OpenBSD
285returns ':' (since OpenBSD's getopt does).
286.El
287.It Li o
288handling of --a in getopt:
289.Bl -tag -width "OpenBSD"
290.It Li GNU
291parses this as option '-', option 'a'.
292.It Li OpenBSD
293parses this as '--', and returns \-1 (ignoring the a).
294(Because the original getopt does.)
295.El
296.It Li o
297setting of optopt for long options with flag !=
298.Dv NULL :
299.Bl -tag -width "OpenBSD"
300.It Li GNU
301sets optopt to val.
302.It Li OpenBSD
303sets optopt to 0 (since val would never be returned).
304.El
305.It Li o
306handling of -W with W; in option string in getopt (not getopt_long):
307.Bl -tag -width "OpenBSD"
308.It Li GNU
309causes a segfault.
310.It Li OpenBSD
311no special handling is done;
312.Dq W;
313is interpreted as two separate options, neither of which take an argument.
314.El
315.It Li o
316setting of optarg for long options without an argument that are
317invoked via -W (W; in option string):
318.Bl -tag -width "OpenBSD"
319.It Li GNU
320sets optarg to the option name (the argument of -W).
321.It Li OpenBSD
322sets optarg to
323.Dv NULL
324(the argument of the long option).
325.El
326.It Li o
327handling of -W with an argument that is not (a prefix to) a known
328long option (W; in option string):
329.Bl -tag -width "OpenBSD"
330.It Li GNU
331returns -W with optarg set to the unknown option.
332.It Li OpenBSD
333treats this as an error (unknown option) and returns '?' with
334optopt set to 0 and optarg set to
335.Dv NULL
336(as GNU's man page documents).
337.El
338.It Li o
339The error messages are different.
340.It Li o
341OpenBSD does not permute the argument vector at the same points in
342the calling sequence as GNU does.
343The aspects normally used by the caller
344(ordering after \-1 is returned, value of optind relative
345to current positions) are the same, though.
346(We do fewer variable swaps.)
347.El
348.Sh ENVIRONMENT
349.Bl -tag -width POSIXLY_CORRECT
350.It Ev POSIXLY_CORRECT
351If set, option processing stops when the first non-option is found and
352a leading
353.Sq -
354or
355.Sq +
356in the
357.Ar optstring
358is ignored.
359.El
360.Sh SEE ALSO
361.Xr getopt 3
362.Sh HISTORY
363The
364.Fn getopt_long
365and
366.Fn getopt_long_only
367functions first appeared in GNU libiberty.
368This implementation first appeared in
369.Ox 3.3 .
370.Sh BUGS
371The
372.Ar argv
373argument is not really
374.Dv const
375as its elements may be permuted (unless
376.Ev POSIXLY_CORRECT
377is set).
diff --git a/src/lib/libc/stdlib/getopt_long.c b/src/lib/libc/stdlib/getopt_long.c
new file mode 100644
index 0000000000..6ddc8e2060
--- /dev/null
+++ b/src/lib/libc/stdlib/getopt_long.c
@@ -0,0 +1,537 @@
1/* $OpenBSD: getopt_long.c,v 1.18 2005/03/30 18:51:49 pat Exp $ */
2/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */
3
4/*
5 * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 *
19 * Sponsored in part by the Defense Advanced Research Projects
20 * Agency (DARPA) and Air Force Research Laboratory, Air Force
21 * Materiel Command, USAF, under agreement number F39502-99-1-0512.
22 */
23/*-
24 * Copyright (c) 2000 The NetBSD Foundation, Inc.
25 * All rights reserved.
26 *
27 * This code is derived from software contributed to The NetBSD Foundation
28 * by Dieter Baron and Thomas Klausner.
29 *
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
32 * are met:
33 * 1. Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * 2. Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
38 * 3. All advertising materials mentioning features or use of this software
39 * must display the following acknowledgement:
40 * This product includes software developed by the NetBSD
41 * Foundation, Inc. and its contributors.
42 * 4. Neither the name of The NetBSD Foundation nor the names of its
43 * contributors may be used to endorse or promote products derived
44 * from this software without specific prior written permission.
45 *
46 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
47 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
48 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
49 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
50 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
51 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
52 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
53 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
54 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
55 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
56 * POSSIBILITY OF SUCH DAMAGE.
57 */
58
59#if defined(LIBC_SCCS) && !defined(lint)
60static char *rcsid = "$OpenBSD: getopt_long.c,v 1.18 2005/03/30 18:51:49 pat Exp $";
61#endif /* LIBC_SCCS and not lint */
62
63#include <err.h>
64#include <errno.h>
65#include <getopt.h>
66#include <stdlib.h>
67#include <string.h>
68
69#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */
70
71#ifdef REPLACE_GETOPT
72int opterr = 1; /* if error message should be printed */
73int optind = 1; /* index into parent argv vector */
74int optopt = '?'; /* character checked for validity */
75int optreset; /* reset getopt */
76char *optarg; /* argument associated with option */
77#endif
78
79#define PRINT_ERROR ((opterr) && (*options != ':'))
80
81#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
82#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
83#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
84
85/* return values */
86#define BADCH (int)'?'
87#define BADARG ((*options == ':') ? (int)':' : (int)'?')
88#define INORDER (int)1
89
90#define EMSG ""
91
92static int getopt_internal(int, char * const *, const char *,
93 const struct option *, int *, int);
94static int parse_long_options(char * const *, const char *,
95 const struct option *, int *, int);
96static int gcd(int, int);
97static void permute_args(int, int, int, char * const *);
98
99static char *place = EMSG; /* option letter processing */
100
101/* XXX: set optreset to 1 rather than these two */
102static int nonopt_start = -1; /* first non option argument (for permute) */
103static int nonopt_end = -1; /* first option after non options (for permute) */
104
105/* Error messages */
106static const char recargchar[] = "option requires an argument -- %c";
107static const char recargstring[] = "option requires an argument -- %s";
108static const char ambig[] = "ambiguous option -- %.*s";
109static const char noarg[] = "option doesn't take an argument -- %.*s";
110static const char illoptchar[] = "unknown option -- %c";
111static const char illoptstring[] = "unknown option -- %s";
112
113/*
114 * Compute the greatest common divisor of a and b.
115 */
116static int
117gcd(int a, int b)
118{
119 int c;
120
121 c = a % b;
122 while (c != 0) {
123 a = b;
124 b = c;
125 c = a % b;
126 }
127
128 return (b);
129}
130
131/*
132 * Exchange the block from nonopt_start to nonopt_end with the block
133 * from nonopt_end to opt_end (keeping the same order of arguments
134 * in each block).
135 */
136static void
137permute_args(int panonopt_start, int panonopt_end, int opt_end,
138 char * const *nargv)
139{
140 int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
141 char *swap;
142
143 /*
144 * compute lengths of blocks and number and size of cycles
145 */
146 nnonopts = panonopt_end - panonopt_start;
147 nopts = opt_end - panonopt_end;
148 ncycle = gcd(nnonopts, nopts);
149 cyclelen = (opt_end - panonopt_start) / ncycle;
150
151 for (i = 0; i < ncycle; i++) {
152 cstart = panonopt_end+i;
153 pos = cstart;
154 for (j = 0; j < cyclelen; j++) {
155 if (pos >= panonopt_end)
156 pos -= nnonopts;
157 else
158 pos += nopts;
159 swap = nargv[pos];
160 /* LINTED const cast */
161 ((char **) nargv)[pos] = nargv[cstart];
162 /* LINTED const cast */
163 ((char **)nargv)[cstart] = swap;
164 }
165 }
166}
167
168/*
169 * parse_long_options --
170 * Parse long options in argc/argv argument vector.
171 * Returns -1 if short_too is set and the option does not match long_options.
172 */
173static int
174parse_long_options(char * const *nargv, const char *options,
175 const struct option *long_options, int *idx, int short_too)
176{
177 char *current_argv, *has_equal;
178 size_t current_argv_len;
179 int i, match;
180
181 current_argv = place;
182 match = -1;
183
184 optind++;
185
186 if ((has_equal = strchr(current_argv, '=')) != NULL) {
187 /* argument found (--option=arg) */
188 current_argv_len = has_equal - current_argv;
189 has_equal++;
190 } else
191 current_argv_len = strlen(current_argv);
192
193 for (i = 0; long_options[i].name; i++) {
194 /* find matching long option */
195 if (strncmp(current_argv, long_options[i].name,
196 current_argv_len))
197 continue;
198
199 if (strlen(long_options[i].name) == current_argv_len) {
200 /* exact match */
201 match = i;
202 break;
203 }
204 /*
205 * If this is a known short option, don't allow
206 * a partial match of a single character.
207 */
208 if (short_too && current_argv_len == 1)
209 continue;
210
211 if (match == -1) /* partial match */
212 match = i;
213 else {
214 /* ambiguous abbreviation */
215 if (PRINT_ERROR)
216 warnx(ambig, (int)current_argv_len,
217 current_argv);
218 optopt = 0;
219 return (BADCH);
220 }
221 }
222 if (match != -1) { /* option found */
223 if (long_options[match].has_arg == no_argument
224 && has_equal) {
225 if (PRINT_ERROR)
226 warnx(noarg, (int)current_argv_len,
227 current_argv);
228 /*
229 * XXX: GNU sets optopt to val regardless of flag
230 */
231 if (long_options[match].flag == NULL)
232 optopt = long_options[match].val;
233 else
234 optopt = 0;
235 return (BADARG);
236 }
237 if (long_options[match].has_arg == required_argument ||
238 long_options[match].has_arg == optional_argument) {
239 if (has_equal)
240 optarg = has_equal;
241 else if (long_options[match].has_arg ==
242 required_argument) {
243 /*
244 * optional argument doesn't use next nargv
245 */
246 optarg = nargv[optind++];
247 }
248 }
249 if ((long_options[match].has_arg == required_argument)
250 && (optarg == NULL)) {
251 /*
252 * Missing argument; leading ':' indicates no error
253 * should be generated.
254 */
255 if (PRINT_ERROR)
256 warnx(recargstring,
257 current_argv);
258 /*
259 * XXX: GNU sets optopt to val regardless of flag
260 */
261 if (long_options[match].flag == NULL)
262 optopt = long_options[match].val;
263 else
264 optopt = 0;
265 --optind;
266 return (BADARG);
267 }
268 } else { /* unknown option */
269 if (short_too) {
270 --optind;
271 return (-1);
272 }
273 if (PRINT_ERROR)
274 warnx(illoptstring, current_argv);
275 optopt = 0;
276 return (BADCH);
277 }
278 if (idx)
279 *idx = match;
280 if (long_options[match].flag) {
281 *long_options[match].flag = long_options[match].val;
282 return (0);
283 } else
284 return (long_options[match].val);
285}
286
287/*
288 * getopt_internal --
289 * Parse argc/argv argument vector. Called by user level routines.
290 */
291static int
292getopt_internal(int nargc, char * const *nargv, const char *options,
293 const struct option *long_options, int *idx, int flags)
294{
295 char *oli; /* option letter list index */
296 int optchar, short_too;
297 static int posixly_correct = -1;
298
299 if (options == NULL)
300 return (-1);
301
302 /*
303 * Disable GNU extensions if POSIXLY_CORRECT is set or options
304 * string begins with a '+'.
305 */
306 if (posixly_correct == -1)
307 posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
308 if (posixly_correct || *options == '+')
309 flags &= ~FLAG_PERMUTE;
310 else if (*options == '-')
311 flags |= FLAG_ALLARGS;
312 if (*options == '+' || *options == '-')
313 options++;
314
315 /*
316 * XXX Some GNU programs (like cvs) set optind to 0 instead of
317 * XXX using optreset. Work around this braindamage.
318 */
319 if (optind == 0)
320 optind = optreset = 1;
321
322 optarg = NULL;
323 if (optreset)
324 nonopt_start = nonopt_end = -1;
325start:
326 if (optreset || !*place) { /* update scanning pointer */
327 optreset = 0;
328 if (optind >= nargc) { /* end of argument vector */
329 place = EMSG;
330 if (nonopt_end != -1) {
331 /* do permutation, if we have to */
332 permute_args(nonopt_start, nonopt_end,
333 optind, nargv);
334 optind -= nonopt_end - nonopt_start;
335 }
336 else if (nonopt_start != -1) {
337 /*
338 * If we skipped non-options, set optind
339 * to the first of them.
340 */
341 optind = nonopt_start;
342 }
343 nonopt_start = nonopt_end = -1;
344 return (-1);
345 }
346 if (*(place = nargv[optind]) != '-' ||
347 (place[1] == '\0' && strchr(options, '-') == NULL)) {
348 place = EMSG; /* found non-option */
349 if (flags & FLAG_ALLARGS) {
350 /*
351 * GNU extension:
352 * return non-option as argument to option 1
353 */
354 optarg = nargv[optind++];
355 return (INORDER);
356 }
357 if (!(flags & FLAG_PERMUTE)) {
358 /*
359 * If no permutation wanted, stop parsing
360 * at first non-option.
361 */
362 return (-1);
363 }
364 /* do permutation */
365 if (nonopt_start == -1)
366 nonopt_start = optind;
367 else if (nonopt_end != -1) {
368 permute_args(nonopt_start, nonopt_end,
369 optind, nargv);
370 nonopt_start = optind -
371 (nonopt_end - nonopt_start);
372 nonopt_end = -1;
373 }
374 optind++;
375 /* process next argument */
376 goto start;
377 }
378 if (nonopt_start != -1 && nonopt_end == -1)
379 nonopt_end = optind;
380
381 /*
382 * If we have "-" do nothing, if "--" we are done.
383 */
384 if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
385 optind++;
386 place = EMSG;
387 /*
388 * We found an option (--), so if we skipped
389 * non-options, we have to permute.
390 */
391 if (nonopt_end != -1) {
392 permute_args(nonopt_start, nonopt_end,
393 optind, nargv);
394 optind -= nonopt_end - nonopt_start;
395 }
396 nonopt_start = nonopt_end = -1;
397 return (-1);
398 }
399 }
400
401 /*
402 * Check long options if:
403 * 1) we were passed some
404 * 2) the arg is not just "-"
405 * 3) either the arg starts with -- we are getopt_long_only()
406 */
407 if (long_options != NULL && place != nargv[optind] &&
408 (*place == '-' || (flags & FLAG_LONGONLY))) {
409 short_too = 0;
410 if (*place == '-')
411 place++; /* --foo long option */
412 else if (*place != ':' && strchr(options, *place) != NULL)
413 short_too = 1; /* could be short option too */
414
415 optchar = parse_long_options(nargv, options, long_options,
416 idx, short_too);
417 if (optchar != -1) {
418 place = EMSG;
419 return (optchar);
420 }
421 }
422
423 if ((optchar = (int)*place++) == (int)':' ||
424 optchar == (int)'-' && *place != '\0' ||
425 (oli = strchr(options, optchar)) == NULL) {
426 /*
427 * If the user specified "-" and '-' isn't listed in
428 * options, return -1 (non-option) as per POSIX.
429 * Otherwise, it is an unknown option character (or ':').
430 */
431 if (optchar == (int)'-' && *place == '\0')
432 return (-1);
433 if (!*place)
434 ++optind;
435 if (PRINT_ERROR)
436 warnx(illoptchar, optchar);
437 optopt = optchar;
438 return (BADCH);
439 }
440 if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
441 /* -W long-option */
442 if (*place) /* no space */
443 /* NOTHING */;
444 else if (++optind >= nargc) { /* no arg */
445 place = EMSG;
446 if (PRINT_ERROR)
447 warnx(recargchar, optchar);
448 optopt = optchar;
449 return (BADARG);
450 } else /* white space */
451 place = nargv[optind];
452 optchar = parse_long_options(nargv, options, long_options,
453 idx, 0);
454 place = EMSG;
455 return (optchar);
456 }
457 if (*++oli != ':') { /* doesn't take argument */
458 if (!*place)
459 ++optind;
460 } else { /* takes (optional) argument */
461 optarg = NULL;
462 if (*place) /* no white space */
463 optarg = place;
464 /* XXX: disable test for :: if PC? (GNU doesn't) */
465 else if (oli[1] != ':') { /* arg not optional */
466 if (++optind >= nargc) { /* no arg */
467 place = EMSG;
468 if (PRINT_ERROR)
469 warnx(recargchar, optchar);
470 optopt = optchar;
471 return (BADARG);
472 } else
473 optarg = nargv[optind];
474 } else if (!(flags & FLAG_PERMUTE)) {
475 /*
476 * If permutation is disabled, we can accept an
477 * optional arg separated by whitespace so long
478 * as it does not start with a dash (-).
479 */
480 if (optind + 1 < nargc && *nargv[optind + 1] != '-')
481 optarg = nargv[++optind];
482 }
483 place = EMSG;
484 ++optind;
485 }
486 /* dump back option letter */
487 return (optchar);
488}
489
490#ifdef REPLACE_GETOPT
491/*
492 * getopt --
493 * Parse argc/argv argument vector.
494 *
495 * [eventually this will replace the BSD getopt]
496 */
497int
498getopt(int nargc, char * const *nargv, const char *options)
499{
500
501 /*
502 * We dont' pass FLAG_PERMUTE to getopt_internal() since
503 * the BSD getopt(3) (unlike GNU) has never done this.
504 *
505 * Furthermore, since many privileged programs call getopt()
506 * before dropping privileges it makes sense to keep things
507 * as simple (and bug-free) as possible.
508 */
509 return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
510}
511#endif /* REPLACE_GETOPT */
512
513/*
514 * getopt_long --
515 * Parse argc/argv argument vector.
516 */
517int
518getopt_long(int nargc, char * const *nargv, const char *options,
519 const struct option *long_options, int *idx)
520{
521
522 return (getopt_internal(nargc, nargv, options, long_options, idx,
523 FLAG_PERMUTE));
524}
525
526/*
527 * getopt_long_only --
528 * Parse argc/argv argument vector.
529 */
530int
531getopt_long_only(int nargc, char * const *nargv, const char *options,
532 const struct option *long_options, int *idx)
533{
534
535 return (getopt_internal(nargc, nargv, options, long_options, idx,
536 FLAG_PERMUTE|FLAG_LONGONLY));
537}
diff --git a/src/lib/libc/stdlib/getsubopt.3 b/src/lib/libc/stdlib/getsubopt.3
new file mode 100644
index 0000000000..6cb4975ced
--- /dev/null
+++ b/src/lib/libc/stdlib/getsubopt.3
@@ -0,0 +1,143 @@
1.\" $OpenBSD: getsubopt.3,v 1.9 2005/02/25 03:12:44 cloder Exp $
2.\"
3.\" Copyright (c) 1990, 1991, 1993
4.\" The Regents of the University of California. All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. Neither the name of the University nor the names of its contributors
15.\" may be used to endorse or promote products derived from this software
16.\" without specific prior written permission.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28.\" SUCH DAMAGE.
29.\"
30.\" @(#)getsubopt.3 8.1 (Berkeley) 6/9/93
31.\"
32.Dd June 9, 1993
33.Dt GETSUBOPT 3
34.Os
35.Sh NAME
36.Nm getsubopt
37.Nd get sub options from an argument
38.Sh SYNOPSIS
39.Fd #include <stdlib.h>
40.Vt extern char *suboptarg;
41.Ft int
42.Fn getsubopt "char **optionp" "char * const *tokens" "char **valuep"
43.Sh DESCRIPTION
44The
45.Fn getsubopt
46function parses a string containing tokens delimited by one or more
47tab, space or comma
48.Pq Ql \&,
49characters.
50It is intended for use in parsing groups of option arguments provided
51as part of a utility command line.
52.Pp
53The argument
54.Fa optionp
55is a pointer to a pointer to the string.
56The argument
57.Fa tokens
58is a pointer to a null-terminated array of pointers to strings.
59.Pp
60The
61.Fn getsubopt
62function returns the zero-based offset of the pointer in the
63.Fa tokens
64array referencing a string which matches the first token
65in the string, or \-1 if the string contains no tokens or
66.Fa tokens
67does not contain a matching string.
68.Pp
69If the token is of the form
70.Ar name Ns = Ns Ar value ,
71the location referenced by
72.Fa valuep
73will be set to point to the start of the
74.Dq value
75portion of the token.
76.Pp
77On return from
78.Fn getsubopt ,
79.Fa optionp
80will be set to point to the start of the next token in the string,
81or the NUL at the end of the string if no more tokens are present.
82The external variable
83.Fa suboptarg
84will be set to point to the start of the current token, or
85.Dv NULL
86if no tokens were present.
87The argument
88.Fa valuep
89will be set to point to the value portion of the token, or
90.Dv NULL
91if no value portion was present.
92.Sh EXAMPLES
93.Bd -literal -compact
94char *tokens[] = {
95 #define ONE 0
96 "one",
97 #define TWO 1
98 "two",
99 NULL
100};
101
102\&...
103
104extern char *optarg, *suboptarg;
105char *options, *value;
106
107while ((ch = getopt(argc, argv, "ab:")) != \-1) {
108 switch(ch) {
109 case 'a':
110 /* process ``a'' option */
111 break;
112 case 'b':
113 options = optarg;
114 while (*options) {
115 switch(getsubopt(&options, tokens, &value)) {
116 case ONE:
117 /* process ``one'' sub option */
118 break;
119 case TWO:
120 /* process ``two'' sub option */
121 if (!value)
122 error("no value for two");
123 i = atoi(value);
124 break;
125 case \-1:
126 if (suboptarg)
127 error("illegal sub option %s",
128 suboptarg);
129 else
130 error("missing sub option");
131 break;
132 }
133 break;
134 }
135.Ed
136.Sh SEE ALSO
137.Xr getopt 3 ,
138.Xr strsep 3
139.Sh HISTORY
140The
141.Fn getsubopt
142function first appeared in
143.Bx 4.4 .
diff --git a/src/lib/libc/stdlib/getsubopt.c b/src/lib/libc/stdlib/getsubopt.c
new file mode 100644
index 0000000000..dfd7a50bd8
--- /dev/null
+++ b/src/lib/libc/stdlib/getsubopt.c
@@ -0,0 +1,100 @@
1/* $OpenBSD: getsubopt.c,v 1.3 2005/03/30 18:51:49 pat Exp $ */
2
3/*-
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#ifndef lint
33#if 0
34static char sccsid[] = "@(#)getsubopt.c 8.1 (Berkeley) 6/4/93";
35#else
36static char rcsid[] = "$OpenBSD: getsubopt.c,v 1.3 2005/03/30 18:51:49 pat Exp $";
37#endif
38#endif /* not lint */
39
40#include <unistd.h>
41#include <stdlib.h>
42#include <string.h>
43
44/*
45 * The SVID interface to getsubopt provides no way of figuring out which
46 * part of the suboptions list wasn't matched. This makes error messages
47 * tricky... The extern variable suboptarg is a pointer to the token
48 * which didn't match.
49 */
50char *suboptarg;
51
52int
53getsubopt(char **optionp, char * const *tokens, char **valuep)
54{
55 int cnt;
56 char *p;
57
58 suboptarg = *valuep = NULL;
59
60 if (!optionp || !*optionp)
61 return(-1);
62
63 /* skip leading white-space, commas */
64 for (p = *optionp; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p);
65
66 if (!*p) {
67 *optionp = p;
68 return(-1);
69 }
70
71 /* save the start of the token, and skip the rest of the token. */
72 for (suboptarg = p;
73 *++p && *p != ',' && *p != '=' && *p != ' ' && *p != '\t';);
74
75 if (*p) {
76 /*
77 * If there's an equals sign, set the value pointer, and
78 * skip over the value part of the token. Terminate the
79 * token.
80 */
81 if (*p == '=') {
82 *p = '\0';
83 for (*valuep = ++p;
84 *p && *p != ',' && *p != ' ' && *p != '\t'; ++p);
85 if (*p)
86 *p++ = '\0';
87 } else
88 *p++ = '\0';
89 /* Skip any whitespace or commas after this token. */
90 for (; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p);
91 }
92
93 /* set optionp for next round. */
94 *optionp = p;
95
96 for (cnt = 0; *tokens; ++tokens, ++cnt)
97 if (!strcmp(suboptarg, *tokens))
98 return(cnt);
99 return(-1);
100}
diff --git a/src/lib/libc/stdlib/hcreate.3 b/src/lib/libc/stdlib/hcreate.3
new file mode 100644
index 0000000000..d1d4e5c185
--- /dev/null
+++ b/src/lib/libc/stdlib/hcreate.3
@@ -0,0 +1,195 @@
1.\" $OpenBSD: hcreate.3,v 1.1 2004/06/24 04:43:33 millert Exp $
2.\" $NetBSD: hcreate.3,v 1.6 2003/04/16 13:34:46 wiz Exp $
3.\"
4.\" Copyright (c) 1999 The NetBSD Foundation, Inc.
5.\" All rights reserved.
6.\"
7.\" This code is derived from software contributed to The NetBSD Foundation
8.\" by Klaus Klein.
9.\"
10.\" Redistribution and use in source and binary forms, with or without
11.\" modification, are permitted provided that the following conditions
12.\" are met:
13.\" 1. Redistributions of source code must retain the above copyright
14.\" notice, this list of conditions and the following disclaimer.
15.\" 2. Redistributions in binary form must reproduce the above copyright
16.\" notice, this list of conditions and the following disclaimer in the
17.\" documentation and/or other materials provided with the distribution.
18.\" 3. All advertising materials mentioning features or use of this software
19.\" must display the following acknowledgement:
20.\" This product includes software developed by the NetBSD
21.\" Foundation, Inc. and its contributors.
22.\" 4. Neither the name of The NetBSD Foundation nor the names of its
23.\" contributors may be used to endorse or promote products derived
24.\" from this software without specific prior written permission.
25.\"
26.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36.\" POSSIBILITY OF SUCH DAMAGE.
37.\"
38.Dd February 13, 2001
39.Dt HCREATE 3
40.Os
41.Sh NAME
42.Nm hcreate ,
43.Nm hdestroy ,
44.Nm hsearch
45.Nd manage hash search table
46.Sh SYNOPSIS
47.In search.h
48.Ft int
49.Fn hcreate "size_t nel"
50.Ft void
51.Fn hdestroy "void"
52.Ft ENTRY *
53.Fn hsearch "ENTRY item" "ACTION action"
54.Sh DESCRIPTION
55The
56.Fn hcreate ,
57.Fn hdestroy
58and
59.Fn hsearch
60functions manage hash search tables.
61.Pp
62The
63.Fn hcreate
64function allocates and initializes the table.
65The
66.Fa nel
67argument specifies an estimate of the maximum number of entries to be held
68by the table.
69Unless further memory allocation fails, supplying an insufficient
70.Fa nel
71value will not result in functional harm, although a performance degradation
72may occur.
73Initialization using the
74.Fn hcreate
75function is mandatory prior to any access operations using
76.Fn hsearch .
77.Pp
78The
79.Fn hdestroy
80function destroys a table previously created using
81.Fn hcreate .
82After a call to
83.Fn hdestroy ,
84the data can no longer be accessed.
85.Pp
86The
87.Fn hsearch
88function is used to search to the hash table.
89It returns a pointer into the
90hash table indicating the address of an item.
91The
92.Fa item
93argument is of type
94.Dv ENTRY ,
95a structural type which contains the following members:
96.Bl -tag -compact -offset indent -width voidX*dataXX
97.It Fa char *key
98comparison key.
99.It Fa void *data
100pointer to data associated with
101.Fa key .
102.El
103.Pp
104The key comparison function used by
105.Fn hsearch
106is
107.Xr strcmp 3 .
108.Pp
109The
110.Fa action
111argument is of type
112.Dv ACTION ,
113an enumeration type which defines the following values:
114.Bl -tag -compact -offset indent -width ENTERXX
115.It Dv ENTER
116Insert
117.Fa item
118into the hash table.
119If an existing item with the same key is found, it is not replaced.
120Note that the
121.Fa key
122and
123.Fa data
124elements of
125.Fa item
126are used directly by the new table entry.
127The storage for the
128key must not be modified during the lifetime of the hash table.
129.It Dv FIND
130Search the hash table without inserting
131.Fa item .
132.El
133.Sh RETURN VALUES
134If successful, the
135.Fn hcreate
136function returns a non-zero value.
137Otherwise, a value of 0 is returned and
138.Va errno
139is set to indicate the error.
140.Pp
141The
142.Fn hdestroy
143functions
144returns no value.
145.Pp
146If successful, the
147.Fn hsearch
148function returns a pointer to hash table entry matching
149the provided key.
150If the action is
151.Dv FIND
152and the item was not found, or if the action is
153.Dv ENTER
154and the insertion failed,
155.Dv NULL
156is returned and
157.Va errno
158is set to indicate the error.
159If the action is
160.Dv ENTER
161and an entry already existed in the table matching the given
162key, the existing entry is returned and is not replaced.
163.Sh ERRORS
164The
165.Fn hcreate
166and
167.Fn hsearch
168functions will fail if:
169.Bl -tag -width Er
170.It Bq Er ENOMEM
171Insufficient memory is available.
172.El
173.Sh SEE ALSO
174.Xr bsearch 3 ,
175.Xr lsearch 3 ,
176.Xr malloc 3 ,
177.Xr strcmp 3
178.Sh STANDARDS
179The
180.Fn hcreate ,
181.Fn hdestroy
182and
183.Fn hsearch
184functions conform to
185.St -xpg4.2 .
186.Sh HISTORY
187The
188.Fn hcreate ,
189.Fn hdestroy
190and
191.Fn hsearch
192functions first appeared in
193.At V .
194.Sh BUGS
195The interface permits the use of only one hash table at a time.
diff --git a/src/lib/libc/stdlib/hcreate.c b/src/lib/libc/stdlib/hcreate.c
new file mode 100644
index 0000000000..14e6fa41f2
--- /dev/null
+++ b/src/lib/libc/stdlib/hcreate.c
@@ -0,0 +1,200 @@
1/* $OpenBSD: hcreate.c,v 1.1 2004/06/24 04:43:33 millert Exp $ */
2/* $NetBSD: hcreate.c,v 1.5 2004/04/23 02:48:12 simonb Exp $ */
3
4/*
5 * Copyright (c) 2001 Christopher G. Demetriou
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed for the
19 * NetBSD Project. See http://www.NetBSD.org/ for
20 * information about NetBSD.
21 * 4. The name of the author may not be used to endorse or promote products
22 * derived from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *
35 * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>>
36 */
37
38/*
39 * hcreate() / hsearch() / hdestroy()
40 *
41 * SysV/XPG4 hash table functions.
42 *
43 * Implementation done based on NetBSD manual page and Solaris manual page,
44 * plus my own personal experience about how they're supposed to work.
45 *
46 * I tried to look at Knuth (as cited by the Solaris manual page), but
47 * nobody had a copy in the office, so...
48 */
49
50#ifndef lint
51static const char copyright[] =
52"@(#) Copyright (c) 2001 Christopher G. Demetriou. All rights reserved.\n";
53#endif /* not lint */
54
55#ifndef lint
56static const char rcsid[] = "$OpenBSD: hcreate.c,v 1.1 2004/06/24 04:43:33 millert Exp $";
57#endif /* not lint */
58
59#include "namespace.h"
60#include <assert.h>
61#include <errno.h>
62#include <inttypes.h>
63#include <search.h>
64#include <stdlib.h>
65#include <string.h>
66#include <sys/queue.h>
67
68#ifndef _DIAGASSERT
69#define _DIAGASSERT
70#endif
71
72/*
73 * DO NOT MAKE THIS STRUCTURE LARGER THAN 32 BYTES (4 ptrs on 64-bit
74 * ptr machine) without adjusting MAX_BUCKETS_LG2 below.
75 */
76struct internal_entry {
77 SLIST_ENTRY(internal_entry) link;
78 ENTRY ent;
79};
80SLIST_HEAD(internal_head, internal_entry);
81
82#define MIN_BUCKETS_LG2 4
83#define MIN_BUCKETS (1 << MIN_BUCKETS_LG2)
84
85/*
86 * max * sizeof internal_entry must fit into size_t.
87 * assumes internal_entry is <= 32 (2^5) bytes.
88 */
89#define MAX_BUCKETS_LG2 (sizeof (size_t) * 8 - 1 - 5)
90#define MAX_BUCKETS ((size_t)1 << MAX_BUCKETS_LG2)
91
92/* Default hash function, from db/hash/hash_func.c */
93extern u_int32_t (*__default_hash)(const void *, size_t);
94
95static struct internal_head *htable;
96static size_t htablesize;
97
98int
99hcreate(size_t nel)
100{
101 size_t idx;
102 unsigned int p2;
103
104 /* Make sure this isn't called when a table already exists. */
105 _DIAGASSERT(htable == NULL);
106 if (htable != NULL) {
107 errno = EINVAL;
108 return 0;
109 }
110
111 /* If nel is too small, make it min sized. */
112 if (nel < MIN_BUCKETS)
113 nel = MIN_BUCKETS;
114
115 /* If it's too large, cap it. */
116 if (nel > MAX_BUCKETS)
117 nel = MAX_BUCKETS;
118
119 /* If it's is not a power of two in size, round up. */
120 if ((nel & (nel - 1)) != 0) {
121 for (p2 = 0; nel != 0; p2++)
122 nel >>= 1;
123 _DIAGASSERT(p2 <= MAX_BUCKETS_LG2);
124 nel = 1 << p2;
125 }
126
127 /* Allocate the table. */
128 htablesize = nel;
129 htable = malloc(htablesize * sizeof htable[0]);
130 if (htable == NULL) {
131 errno = ENOMEM;
132 return 0;
133 }
134
135 /* Initialize it. */
136 for (idx = 0; idx < htablesize; idx++)
137 SLIST_INIT(&htable[idx]);
138
139 return 1;
140}
141
142void
143hdestroy(void)
144{
145 struct internal_entry *ie;
146 size_t idx;
147
148 _DIAGASSERT(htable != NULL);
149 if (htable == NULL)
150 return;
151
152 for (idx = 0; idx < htablesize; idx++) {
153 while (!SLIST_EMPTY(&htable[idx])) {
154 ie = SLIST_FIRST(&htable[idx]);
155 SLIST_REMOVE_HEAD(&htable[idx], link);
156 free(ie->ent.key);
157 free(ie);
158 }
159 }
160 free(htable);
161 htable = NULL;
162}
163
164ENTRY *
165hsearch(ENTRY item, ACTION action)
166{
167 struct internal_head *head;
168 struct internal_entry *ie;
169 uint32_t hashval;
170 size_t len;
171
172 _DIAGASSERT(htable != NULL);
173 _DIAGASSERT(item.key != NULL);
174 _DIAGASSERT(action == ENTER || action == FIND);
175
176 len = strlen(item.key);
177 hashval = (*__default_hash)(item.key, len);
178
179 head = &htable[hashval & (htablesize - 1)];
180 ie = SLIST_FIRST(head);
181 while (ie != NULL) {
182 if (strcmp(ie->ent.key, item.key) == 0)
183 break;
184 ie = SLIST_NEXT(ie, link);
185 }
186
187 if (ie != NULL)
188 return &ie->ent;
189 else if (action == FIND)
190 return NULL;
191
192 ie = malloc(sizeof *ie);
193 if (ie == NULL)
194 return NULL;
195 ie->ent.key = item.key;
196 ie->ent.data = item.data;
197
198 SLIST_INSERT_HEAD(head, ie, link);
199 return &ie->ent;
200}
diff --git a/src/lib/libc/stdlib/heapsort.c b/src/lib/libc/stdlib/heapsort.c
new file mode 100644
index 0000000000..dcc0c8baad
--- /dev/null
+++ b/src/lib/libc/stdlib/heapsort.c
@@ -0,0 +1,177 @@
1/*-
2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Ronnie Kon at Mindcraft Inc., Kevin Lew and Elmer Yglesias.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char *rcsid = "$OpenBSD: heapsort.c,v 1.7 2005/03/30 18:51:49 pat Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37#include <sys/types.h>
38#include <errno.h>
39#include <stdlib.h>
40
41/*
42 * Swap two areas of size number of bytes. Although qsort(3) permits random
43 * blocks of memory to be sorted, sorting pointers is almost certainly the
44 * common case (and, were it not, could easily be made so). Regardless, it
45 * isn't worth optimizing; the SWAP's get sped up by the cache, and pointer
46 * arithmetic gets lost in the time required for comparison function calls.
47 */
48#define SWAP(a, b, count, size, tmp) { \
49 count = size; \
50 do { \
51 tmp = *a; \
52 *a++ = *b; \
53 *b++ = tmp; \
54 } while (--count); \
55}
56
57/* Copy one block of size size to another. */
58#define COPY(a, b, count, size, tmp1, tmp2) { \
59 count = size; \
60 tmp1 = a; \
61 tmp2 = b; \
62 do { \
63 *tmp1++ = *tmp2++; \
64 } while (--count); \
65}
66
67/*
68 * Build the list into a heap, where a heap is defined such that for
69 * the records K1 ... KN, Kj/2 >= Kj for 1 <= j/2 <= j <= N.
70 *
71 * There are two cases. If j == nmemb, select largest of Ki and Kj. If
72 * j < nmemb, select largest of Ki, Kj and Kj+1.
73 */
74#define CREATE(initval, nmemb, par_i, child_i, par, child, size, count, tmp) { \
75 for (par_i = initval; (child_i = par_i * 2) <= nmemb; \
76 par_i = child_i) { \
77 child = base + child_i * size; \
78 if (child_i < nmemb && compar(child, child + size) < 0) { \
79 child += size; \
80 ++child_i; \
81 } \
82 par = base + par_i * size; \
83 if (compar(child, par) <= 0) \
84 break; \
85 SWAP(par, child, count, size, tmp); \
86 } \
87}
88
89/*
90 * Select the top of the heap and 'heapify'. Since by far the most expensive
91 * action is the call to the compar function, a considerable optimization
92 * in the average case can be achieved due to the fact that k, the displaced
93 * element, is usually quite small, so it would be preferable to first
94 * heapify, always maintaining the invariant that the larger child is copied
95 * over its parent's record.
96 *
97 * Then, starting from the *bottom* of the heap, finding k's correct place,
98 * again maintaining the invariant. As a result of the invariant no element
99 * is 'lost' when k is assigned its correct place in the heap.
100 *
101 * The time savings from this optimization are on the order of 15-20% for the
102 * average case. See Knuth, Vol. 3, page 158, problem 18.
103 *
104 * XXX Don't break the #define SELECT line, below. Reiser cpp gets upset.
105 */
106#define SELECT(par_i, child_i, nmemb, par, child, size, k, count, tmp1, tmp2) { \
107 for (par_i = 1; (child_i = par_i * 2) <= nmemb; par_i = child_i) { \
108 child = base + child_i * size; \
109 if (child_i < nmemb && compar(child, child + size) < 0) { \
110 child += size; \
111 ++child_i; \
112 } \
113 par = base + par_i * size; \
114 COPY(par, child, count, size, tmp1, tmp2); \
115 } \
116 for (;;) { \
117 child_i = par_i; \
118 par_i = child_i / 2; \
119 child = base + child_i * size; \
120 par = base + par_i * size; \
121 if (child_i == 1 || compar(k, par) < 0) { \
122 COPY(child, k, count, size, tmp1, tmp2); \
123 break; \
124 } \
125 COPY(child, par, count, size, tmp1, tmp2); \
126 } \
127}
128
129/*
130 * Heapsort -- Knuth, Vol. 3, page 145. Runs in O (N lg N), both average
131 * and worst. While heapsort is faster than the worst case of quicksort,
132 * the BSD quicksort does median selection so that the chance of finding
133 * a data set that will trigger the worst case is nonexistent. Heapsort's
134 * only advantage over quicksort is that it requires little additional memory.
135 */
136int
137heapsort(void *vbase, size_t nmemb, size_t size,
138 int (*compar)(const void *, const void *))
139{
140 int cnt, i, j, l;
141 char tmp, *tmp1, *tmp2;
142 char *base, *k, *p, *t;
143
144 if (nmemb <= 1)
145 return (0);
146
147 if (!size) {
148 errno = EINVAL;
149 return (-1);
150 }
151
152 if ((k = malloc(size)) == NULL)
153 return (-1);
154
155 /*
156 * Items are numbered from 1 to nmemb, so offset from size bytes
157 * below the starting address.
158 */
159 base = (char *)vbase - size;
160
161 for (l = nmemb / 2 + 1; --l;)
162 CREATE(l, nmemb, i, j, t, p, size, cnt, tmp);
163
164 /*
165 * For each element of the heap, save the largest element into its
166 * final slot, save the displaced element (k), then recreate the
167 * heap.
168 */
169 while (nmemb > 1) {
170 COPY(k, base + nmemb * size, cnt, size, tmp1, tmp2);
171 COPY(base + nmemb * size, base + size, cnt, size, tmp1, tmp2);
172 --nmemb;
173 SELECT(i, j, nmemb, t, p, size, k, cnt, tmp1, tmp2);
174 }
175 free(k);
176 return (0);
177}
diff --git a/src/lib/libc/stdlib/insque.3 b/src/lib/libc/stdlib/insque.3
new file mode 100644
index 0000000000..cd8110ed90
--- /dev/null
+++ b/src/lib/libc/stdlib/insque.3
@@ -0,0 +1,100 @@
1.\" $OpenBSD: insque.3,v 1.3 2004/01/25 14:48:32 jmc Exp $
2.\" Copyright (c) 1993 John Brezak
3.\" All rights reserved.
4.\"
5.\" Redistribution and use in source and binary forms, with or without
6.\" modification, are permitted provided that the following conditions
7.\" are met:
8.\" 1. Redistributions of source code must retain the above copyright
9.\" notice, this list of conditions and the following disclaimer.
10.\" 2. Redistributions in binary form must reproduce the above copyright
11.\" notice, this list of conditions and the following disclaimer in the
12.\" documentation and/or other materials provided with the distribution.
13.\" 3. The name of the author may be used to endorse or promote products
14.\" derived from this software without specific prior written permission.
15.\"
16.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND
17.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
20.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26.\" SUCH DAMAGE.
27.\"
28.\"
29.Dd August 12, 1993
30.Dt INSQUE 3
31.Os
32.Sh NAME
33.Nm insque ,
34.Nm remque
35.Nd insert/remove element from a queue
36.Sh SYNOPSIS
37.Fd #include <search.h>
38.Ft void
39.Fn insque "void *elem" "void *pred"
40.Ft void
41.Fn remque "void *elem"
42.Sh DESCRIPTION
43.Bf -symbolic
44These interfaces have been superceded by the
45.Xr queue 3
46macros and are provided for compatibility with legacy code.
47.Ef
48.Pp
49.Fn insque
50and
51.Fn remque
52manipulate queues built from doubly linked lists.
53The queue can be either circular or linear.
54Each element in the queue must be of the following form:
55.Bd -literal
56struct qelem {
57 struct qelem *q_forw;
58 struct qelem *q_back;
59 char q_data[];
60};
61.Ed
62.Pp
63The first two elements in the struct must be pointers of the
64same type that point to the previous and next elements in
65the queue respectively.
66Any subsequent data in the struct is application-dependent.
67.Pp
68The
69.Fn insque
70function inserts
71.Fa elem
72into a queue immediately after
73.Fa pred .
74.Pp
75The
76.Fn remque
77function removes
78.Fa elem
79from the queue.
80.Sh DIAGNOSTICS
81These functions are not atomic unless that machine architecture allows it.
82.Sh SEE ALSO
83.Xr queue 3
84.Sh STANDARDS
85The
86.Fn lsearch
87and
88.Fn lfind
89functions conform to the
90.St -p1003.1-2001
91and
92.St -xpg4.3 .
93specifications.
94.Sh HISTORY
95The
96.Fn insque
97and
98.Fn remque
99functions are derived from the insque and remque instructions on a
100.Tn VAX .
diff --git a/src/lib/libc/stdlib/insque.c b/src/lib/libc/stdlib/insque.c
new file mode 100644
index 0000000000..549246c71f
--- /dev/null
+++ b/src/lib/libc/stdlib/insque.c
@@ -0,0 +1,52 @@
1/* $OpenBSD: insque.c,v 1.1 2003/05/08 23:26:30 millert Exp $ */
2
3/*
4 * Copyright (c) 1993 John Brezak
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#if defined(LIBC_SCCS) && !defined(lint)
32static char *rcsid = "$OpenBSD: insque.c,v 1.1 2003/05/08 23:26:30 millert Exp $";
33#endif /* LIBC_SCCS and not lint */
34
35#include <search.h>
36
37struct qelem {
38 struct qelem *q_forw;
39 struct qelem *q_back;
40};
41
42void
43insque(void *entry, void *pred)
44{
45 struct qelem *e = (struct qelem *) entry;
46 struct qelem *p = (struct qelem *) pred;
47
48 e->q_forw = p->q_forw;
49 e->q_back = p;
50 p->q_forw->q_back = e;
51 p->q_forw = e;
52}
diff --git a/src/lib/libc/stdlib/jrand48.c b/src/lib/libc/stdlib/jrand48.c
new file mode 100644
index 0000000000..99cddb71e5
--- /dev/null
+++ b/src/lib/libc/stdlib/jrand48.c
@@ -0,0 +1,25 @@
1/*
2 * Copyright (c) 1993 Martin Birgmeier
3 * All rights reserved.
4 *
5 * You may redistribute unmodified or modified versions of this source
6 * code provided that the above copyright notice and this and the
7 * following conditions are retained.
8 *
9 * This software is provided ``as is'', and comes with no warranties
10 * of any kind. I shall in no event be liable for anything that happens
11 * to anyone/anything when using this software.
12 */
13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: jrand48.c,v 1.2 1996/08/19 08:33:33 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
18#include "rand48.h"
19
20long
21jrand48(unsigned short xseed[3])
22{
23 __dorand48(xseed);
24 return ((long) xseed[2] << 16) + (long) xseed[1];
25}
diff --git a/src/lib/libc/stdlib/l64a.c b/src/lib/libc/stdlib/l64a.c
new file mode 100644
index 0000000000..325b41b33b
--- /dev/null
+++ b/src/lib/libc/stdlib/l64a.c
@@ -0,0 +1,45 @@
1/*
2 * Written by J.T. Conklin <jtc@netbsd.org>.
3 * Public domain.
4 */
5
6#if defined(LIBC_SCCS) && !defined(lint)
7static char *rcsid = "$OpenBSD: l64a.c,v 1.4 2005/03/30 18:51:49 pat Exp $";
8#endif /* LIBC_SCCS and not lint */
9
10#include <errno.h>
11#include <stdlib.h>
12
13char *
14l64a(long value)
15{
16 static char buf[8];
17 char *s = buf;
18 int digit;
19 int i;
20
21 if (value < 0) {
22 errno = EINVAL;
23 return(NULL);
24 }
25
26 for (i = 0; value != 0 && i < 6; i++) {
27 digit = value & 0x3f;
28
29 if (digit < 2)
30 *s = digit + '.';
31 else if (digit < 12)
32 *s = digit + '0' - 2;
33 else if (digit < 38)
34 *s = digit + 'A' - 12;
35 else
36 *s = digit + 'a' - 38;
37
38 value >>= 6;
39 s++;
40 }
41
42 *s = '\0';
43
44 return(buf);
45}
diff --git a/src/lib/libc/stdlib/labs.3 b/src/lib/libc/stdlib/labs.3
new file mode 100644
index 0000000000..742f3eedba
--- /dev/null
+++ b/src/lib/libc/stdlib/labs.3
@@ -0,0 +1,68 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information
6.\" Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: labs.3,v 1.7 2003/07/21 20:20:04 millert Exp $
33.\"
34.Dd May 14, 2003
35.Dt LABS 3
36.Os
37.Sh NAME
38.Nm labs, llabs
39.Nd return the absolute value of a long integer
40.Sh SYNOPSIS
41.Fd #include <stdlib.h>
42.Ft long
43.Fn labs "long i"
44.Ft long long
45.Fn llabs "long long j"
46.Sh DESCRIPTION
47The
48.Fn labs
49function returns the absolute value of the long integer
50.Fa i .
51The
52.Fn llabs
53function returns the absolute value of the long long integer
54.Fa j .
55.Sh SEE ALSO
56.Xr abs 3 ,
57.Xr cabs 3 ,
58.Xr floor 3 ,
59.Xr math 3
60.Sh STANDARDS
61The
62.Fn labs
63and
64.Fn llabs
65functions conform to
66.St -ansiC-99 .
67.Sh BUGS
68The absolute value of the most negative integer remains negative.
diff --git a/src/lib/libc/stdlib/labs.c b/src/lib/libc/stdlib/labs.c
new file mode 100644
index 0000000000..1dc8b0184a
--- /dev/null
+++ b/src/lib/libc/stdlib/labs.c
@@ -0,0 +1,40 @@
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: labs.c,v 1.4 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35
36long
37labs(long j)
38{
39 return(j < 0 ? -j : j);
40}
diff --git a/src/lib/libc/stdlib/lcong48.c b/src/lib/libc/stdlib/lcong48.c
new file mode 100644
index 0000000000..44bd74e48a
--- /dev/null
+++ b/src/lib/libc/stdlib/lcong48.c
@@ -0,0 +1,34 @@
1/*
2 * Copyright (c) 1993 Martin Birgmeier
3 * All rights reserved.
4 *
5 * You may redistribute unmodified or modified versions of this source
6 * code provided that the above copyright notice and this and the
7 * following conditions are retained.
8 *
9 * This software is provided ``as is'', and comes with no warranties
10 * of any kind. I shall in no event be liable for anything that happens
11 * to anyone/anything when using this software.
12 */
13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: lcong48.c,v 1.2 1996/08/19 08:33:35 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
18#include "rand48.h"
19
20extern unsigned short __rand48_seed[3];
21extern unsigned short __rand48_mult[3];
22extern unsigned short __rand48_add;
23
24void
25lcong48(unsigned short p[7])
26{
27 __rand48_seed[0] = p[0];
28 __rand48_seed[1] = p[1];
29 __rand48_seed[2] = p[2];
30 __rand48_mult[0] = p[3];
31 __rand48_mult[1] = p[4];
32 __rand48_mult[2] = p[5];
33 __rand48_add = p[6];
34}
diff --git a/src/lib/libc/stdlib/ldiv.3 b/src/lib/libc/stdlib/ldiv.3
new file mode 100644
index 0000000000..63e1f2165c
--- /dev/null
+++ b/src/lib/libc/stdlib/ldiv.3
@@ -0,0 +1,65 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" Chris Torek and the American National Standards Committee X3,
6.\" on Information Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: ldiv.3,v 1.7 2004/01/23 23:08:46 jmc Exp $
33.\"
34.Dd June 29, 1991
35.Dt LDIV 3
36.Os
37.Sh NAME
38.Nm ldiv
39.Nd return quotient and remainder from division
40.Sh SYNOPSIS
41.Fd #include <stdlib.h>
42.Ft ldiv_t
43.Fn ldiv "long num" "long denom"
44.Sh DESCRIPTION
45The
46.Fn ldiv
47function computes the value
48.Fa num Ns / Ns Fa denom
49and returns the quotient and remainder in a structure named
50.Li ldiv_t
51that contains two
52.Li long integer
53members named
54.Fa quot
55and
56.Fa rem .
57.Sh SEE ALSO
58.Xr div 3 ,
59.Xr math 3 ,
60.Xr qdiv 3
61.Sh STANDARDS
62The
63.Fn ldiv
64function conforms to
65.St -ansiC .
diff --git a/src/lib/libc/stdlib/ldiv.c b/src/lib/libc/stdlib/ldiv.c
new file mode 100644
index 0000000000..bbb539a68b
--- /dev/null
+++ b/src/lib/libc/stdlib/ldiv.c
@@ -0,0 +1,53 @@
1/*
2 * Copyright (c) 1990 Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Chris Torek.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char *rcsid = "$OpenBSD: ldiv.c,v 1.4 2005/03/30 18:51:49 pat Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37#include <stdlib.h> /* ldiv_t */
38
39ldiv_t
40ldiv(long num, long denom)
41{
42 ldiv_t r;
43
44 /* see div.c for comments */
45
46 r.quot = num / denom;
47 r.rem = num % denom;
48 if (num >= 0 && r.rem < 0) {
49 r.quot++;
50 r.rem -= denom;
51 }
52 return (r);
53}
diff --git a/src/lib/libc/stdlib/llabs.c b/src/lib/libc/stdlib/llabs.c
new file mode 100644
index 0000000000..9611b5aefd
--- /dev/null
+++ b/src/lib/libc/stdlib/llabs.c
@@ -0,0 +1,45 @@
1/* $OpenBSD: llabs.c,v 1.1 2003/07/21 20:20:04 millert Exp $ */
2
3/*-
4 * Copyright (c) 1990 The Regents of the University of California.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#if defined(LIBC_SCCS) && !defined(lint)
37static char *rcsid = "$OpenBSD: llabs.c,v 1.1 2003/07/21 20:20:04 millert Exp $";
38#endif /* LIBC_SCCS and not lint */
39
40#include <stdlib.h>
41
42long long llabs(long long j)
43{
44 return (j < 0 ? -j : j);
45}
diff --git a/src/lib/libc/stdlib/lrand48.c b/src/lib/libc/stdlib/lrand48.c
new file mode 100644
index 0000000000..6b7524a51b
--- /dev/null
+++ b/src/lib/libc/stdlib/lrand48.c
@@ -0,0 +1,27 @@
1/*
2 * Copyright (c) 1993 Martin Birgmeier
3 * All rights reserved.
4 *
5 * You may redistribute unmodified or modified versions of this source
6 * code provided that the above copyright notice and this and the
7 * following conditions are retained.
8 *
9 * This software is provided ``as is'', and comes with no warranties
10 * of any kind. I shall in no event be liable for anything that happens
11 * to anyone/anything when using this software.
12 */
13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: lrand48.c,v 1.2 1996/08/19 08:33:36 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
18#include "rand48.h"
19
20extern unsigned short __rand48_seed[3];
21
22long
23lrand48(void)
24{
25 __dorand48(__rand48_seed);
26 return ((long) __rand48_seed[2] << 15) + ((long) __rand48_seed[1] >> 1);
27}
diff --git a/src/lib/libc/stdlib/lsearch.3 b/src/lib/libc/stdlib/lsearch.3
new file mode 100644
index 0000000000..818aa1bb43
--- /dev/null
+++ b/src/lib/libc/stdlib/lsearch.3
@@ -0,0 +1,105 @@
1.\" $OpenBSD: lsearch.3,v 1.4 2004/10/01 04:08:45 jsg Exp $
2.\"
3.\" Copyright (c) 1989, 1991, 1993
4.\" The Regents of the University of California. All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. Neither the name of the University nor the names of its contributors
15.\" may be used to endorse or promote products derived from this software
16.\" without specific prior written permission.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28.\" SUCH DAMAGE.
29.\"
30.\" @(#)lsearch.3 8.1 (Berkeley) 6/4/93
31.\"
32.Dd June 4, 1993
33.Dt LSEARCH 3
34.Os
35.Sh NAME
36.Nm lsearch ,
37.Nm lfind
38.Nd linear searching routines
39.Sh SYNOPSIS
40.Ft char *
41.Fn lsearch "const void *key" "const void *base" "size_t *nelp" "size_t width" "int (*compar)(void *, void *)"
42.Ft char *
43.Fn lfind "const void *key" "const void *base" "size_t *nelp" "size_t width" "int (*compar)(void *, void *)"
44.Sh DESCRIPTION
45The functions
46.Fn lsearch ,
47and
48.Fn lfind
49provide basic linear searching functionality.
50.Pp
51.Fa base
52is the pointer to the beginning of an array.
53The argument
54.Fa nelp
55is the current number of elements in the array, where each element
56is
57.Fa width
58bytes long.
59The
60.Fa compar
61function
62is a comparison routine which is used to compare two elements.
63It takes two arguments which point to the
64.Fa key
65object and to an array member, in that order, and must return an integer
66less than, equivalent to, or greater than zero if the
67.Fa key
68object is considered, respectively, to be less than, equal to, or greater
69than the array member.
70.Pp
71The
72.Fn lsearch
73and
74.Fn lfind
75functions
76return a pointer into the array referenced by
77.Fa base
78where
79.Fa key
80is located.
81If
82.Fa key
83does not exist,
84.Fn lfind
85will return a null pointer and
86.Fn lsearch
87will add it to the array.
88When an element is added to the array by
89.Fn lsearch
90the location referenced by the argument
91.Fa nelp
92is incremented by one.
93.Sh SEE ALSO
94.Xr bsearch 3 ,
95.Xr db 3
96.Sh STANDARDS
97The
98.Fn lsearch
99and
100.Fn lfind
101functions conform to the
102.St -p1003.1-2001
103and
104.St -xpg4.3 .
105specifications.
diff --git a/src/lib/libc/stdlib/lsearch.c b/src/lib/libc/stdlib/lsearch.c
new file mode 100644
index 0000000000..0815430199
--- /dev/null
+++ b/src/lib/libc/stdlib/lsearch.c
@@ -0,0 +1,88 @@
1/* $OpenBSD: lsearch.c,v 1.3 2004/10/01 04:08:45 jsg Exp $ */
2
3/*
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Roger L. Snyder.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#if defined(LIBC_SCCS) && !defined(lint)
36static char sccsid[] = "@(#)lsearch.c 8.1 (Berkeley) 6/4/93";
37#endif /* LIBC_SCCS and not lint */
38
39#include <sys/types.h>
40#include <string.h>
41#include <search.h>
42
43typedef int (*cmp_fn_t)(const void *, const void *);
44static void *linear_base(const void *, const void *, size_t *, size_t,
45 cmp_fn_t, int);
46
47void *
48lsearch(const void *key, const void *base, size_t *nelp, size_t width,
49 cmp_fn_t compar)
50{
51
52 return(linear_base(key, base, nelp, width, compar, 1));
53}
54
55void *
56lfind(const void *key, const void *base, size_t *nelp, size_t width,
57 cmp_fn_t compar)
58{
59 return(linear_base(key, base, nelp, width, compar, 0));
60}
61
62static void *
63linear_base(const void *key, const void *base, size_t *nelp, size_t width,
64 cmp_fn_t compar, int add_flag)
65{
66 const char *element, *end;
67
68 end = (const char *)base + *nelp * width;
69 for (element = base; element < end; element += width)
70 if (!compar(key, element)) /* key found */
71 return((void *)element);
72
73 if (!add_flag) /* key not found */
74 return(NULL);
75
76 /*
77 * The UNIX System User's Manual, 1986 edition claims that
78 * a NULL pointer is returned by lsearch with errno set
79 * appropriately, if there is not enough room in the table
80 * to add a new item. This can't be done as none of these
81 * routines have any method of determining the size of the
82 * table. This comment isn't in the 1986-87 System V
83 * manual.
84 */
85 ++*nelp;
86 memcpy((void *)end, key, width);
87 return((void *)end);
88}
diff --git a/src/lib/libc/stdlib/malloc.3 b/src/lib/libc/stdlib/malloc.3
new file mode 100644
index 0000000000..138ec708e8
--- /dev/null
+++ b/src/lib/libc/stdlib/malloc.3
@@ -0,0 +1,431 @@
1.\"
2.\" Copyright (c) 1980, 1991, 1993
3.\" The Regents of the University of California. All rights reserved.
4.\"
5.\" This code is derived from software contributed to Berkeley by
6.\" the American National Standards Committee X3, on Information
7.\" Processing Systems.
8.\"
9.\" Redistribution and use in source and binary forms, with or without
10.\" modification, are permitted provided that the following conditions
11.\" are met:
12.\" 1. Redistributions of source code must retain the above copyright
13.\" notice, this list of conditions and the following disclaimer.
14.\" 2. Redistributions in binary form must reproduce the above copyright
15.\" notice, this list of conditions and the following disclaimer in the
16.\" documentation and/or other materials provided with the distribution.
17.\" 3. Neither the name of the University nor the names of its contributors
18.\" may be used to endorse or promote products derived from this software
19.\" without specific prior written permission.
20.\"
21.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31.\" SUCH DAMAGE.
32.\"
33.\" $OpenBSD: malloc.3,v 1.37 2004/07/02 10:42:55 jmc Exp $
34.\"
35.Dd August 27, 1996
36.Dt MALLOC 3
37.Os
38.Sh NAME
39.Nm malloc ,
40.Nm calloc ,
41.Nm realloc ,
42.Nm free ,
43.Nm cfree
44.Nd memory allocation and deallocation
45.Sh SYNOPSIS
46.Fd #include <stdlib.h>
47.Ft void *
48.Fn malloc "size_t size"
49.Ft void *
50.Fn calloc "size_t nmemb" "size_t size"
51.Ft void *
52.Fn realloc "void *ptr" "size_t size"
53.Ft void
54.Fn free "void *ptr"
55.Ft void
56.Fn cfree "void *ptr"
57.Ft char *
58.Va malloc_options ;
59.Sh DESCRIPTION
60The
61.Fn malloc
62function allocates uninitialized space for an object whose
63size is specified by
64.Fa size .
65The
66.Fn malloc
67function maintains multiple lists of free blocks according to size, allocating
68space from the appropriate list.
69.Pp
70The allocated space is
71suitably aligned (after possible pointer
72coercion) for storage of any type of object.
73If the space is of
74.Em pagesize
75or larger, the memory returned will be page-aligned.
76.Pp
77Allocation of a zero size object returns a pointer to a zero size object.
78This zero size object is access protected, so any access to it will
79generate an exception (SIGSEGV).
80Many zero-sized objects can be placed consecutively in shared
81protected pages.
82The minimum size of the protection on each object is suitably aligned and
83sized as previously stated, but the protection may extend further depending
84on where in a protected zone the object lands.
85.Pp
86The
87.Fn calloc
88function allocates space for an array of
89.Fa nmemb
90objects, each of whose size is
91.Fa size .
92The space is initialized to all bits zero.
93.Pp
94The
95.Fn free
96function causes the space pointed to by
97.Fa ptr
98to be deallocated, that is, at least made available for further allocation,
99but if possible, it will passed back to the kernel with
100.Xr sbrk 2 .
101If
102.Fa ptr
103is a null pointer, no action occurs.
104.Pp
105A
106.Fn cfree
107function is also provided for compatibility with old systems and other
108.Nm malloc
109libraries; it is simply an alias for
110.Fn free .
111.Pp
112The
113.Fn realloc
114function changes the size of the object pointed to by
115.Fa ptr
116to
117.Fa size
118bytes and returns a pointer to the (possibly moved) object.
119The contents of the object are unchanged up to the lesser
120of the new and old sizes.
121If the new size is larger, the value of the newly allocated portion
122of the object is indeterminate and uninitialized.
123If
124.Fa ptr
125is a null pointer, the
126.Fn realloc
127function behaves like the
128.Fn malloc
129function for the specified size.
130If the space cannot be allocated, the object
131pointed to by
132.Fa ptr
133is unchanged.
134If
135.Fa size
136is zero and
137.Fa ptr
138is not a null pointer, the object it points to is freed and a new zero size
139object is returned.
140.Pp
141When using
142.Fn realloc
143one must be careful to avoid the following idiom:
144.Bd -literal -offset indent
145size += 50;
146if ((p = realloc(p, size)) == NULL)
147 return (NULL);
148.Ed
149.Pp
150Do not adjust the variable describing how much memory has been allocated
151until one knows the allocation has been successful.
152This can cause aberrant program behavior if the incorrect size value is used.
153In most cases, the above sample will also result in a leak of memory.
154As stated earlier, a return value of
155.Dv NULL
156indicates that the old object still remains allocated.
157Better code looks like this:
158.Bd -literal -offset indent
159newsize = size + 50;
160if ((newp = realloc(p, newsize)) == NULL) {
161 free(p);
162 p = NULL;
163 size = 0;
164 return (NULL);
165}
166p = newp;
167size = newsize;
168.Ed
169.Pp
170Malloc will first look for a symbolic link called
171.Pa /etc/malloc.conf
172and next check the environment for a variable called
173.Ev MALLOC_OPTIONS
174and finally for the global variable
175.Va malloc_options
176and scan them for flags in that order.
177Flags are single letters, uppercase means on, lowercase means off.
178.Bl -tag -width indent
179.It Cm A
180.Dq Abort .
181.Fn malloc
182will coredump the process, rather than tolerate failure.
183This is a very handy debugging aid, since the core file will represent the
184time of failure, rather than when the null pointer was accessed.
185.Pp
186.It Cm D
187.Dq Dump .
188.Fn malloc
189will dump statistics in a file called
190.Pa malloc.out
191at exit.
192This option requires the library to have been compiled with -DMALLOC_STATS in
193order to have any effect.
194.Pp
195.It Cm F
196.Dq Freeguard .
197Enable use after free protection.
198Unused pages on the freelist are read and write protected to
199cause a segmentation fault upon access.
200.Pp
201.It Cm G
202.Dq Guard .
203Enable guard pages and chunk randomization.
204Each page size or larger allocation is followed by a guard page that will
205cause a segmentation fault upon any access.
206Smaller than page size chunks are returned in a random order.
207.Pp
208.It Cm H
209.Dq Hint .
210Pass a hint to the kernel about pages we don't use.
211If the machine is paging a lot this may help a bit.
212.Pp
213.It Cm J
214.Dq Junk .
215Fill some junk into the area allocated.
216Currently junk is bytes of 0xd0; this is pronounced
217.Dq Duh .
218\&:-)
219.Pp
220.It Cm N
221Do not output warning messages when encountering possible corruption
222or bad pointers.
223.Pp
224.It Cm R
225.Dq realloc .
226Always reallocate when
227.Fn realloc
228is called, even if the initial allocation was big enough.
229This can substantially aid in compacting memory.
230.\".Pp
231.\".It Cm U
232.\".Dq utrace .
233.\"Generate entries for
234.\".Xr ktrace 1
235.\"for all operations.
236.\"Consult the source for this one.
237.Pp
238.It Cm X
239.Dq xmalloc .
240Rather than return failure,
241.Xr abort 3
242the program with a diagnostic message on stderr.
243It is the intention that this option be set at compile time by
244including in the source:
245.Bd -literal -offset indent
246extern char *malloc_options;
247malloc_options = "X";
248.Ed
249.Pp
250.It Cm Z
251.Dq Zero .
252Fill some junk into the area allocated (see
253.Cm J ) ,
254except for the exact length the user asked for, which is zeroed.
255.Pp
256.It Cm <
257.Dq Half the cache size .
258Reduce the size of the cache by a factor of two.
259.Pp
260.It Cm >
261.Dq Double the cache size .
262Double the size of the cache by a factor of two.
263.El
264.Pp
265So to set a systemwide reduction of cache size and coredumps on problems
266one would:
267.Li ln -s 'A<' /etc/malloc.conf
268.Pp
269The
270.Cm J
271and
272.Cm Z
273flags are mostly for testing and debugging.
274If a program changes behavior if either of these options are used,
275it is buggy.
276.Pp
277The default cache size is 16 pages.
278.Sh RETURN VALUES
279The
280.Fn malloc
281and
282.Fn calloc
283functions return a pointer to the allocated space if successful; otherwise,
284a null pointer is returned and
285.Va errno
286is set to
287.Er ENOMEM .
288.Pp
289The
290.Fn free
291and
292.Fn cfree
293functions return no value.
294.Pp
295The
296.Fn realloc
297function returns a pointer to the (possibly moved) allocated space
298if successful; otherwise, a null pointer is returned and
299.Va errno
300is set to
301.Er ENOMEM .
302.Sh ENVIRONMENT
303See above.
304.Sh FILES
305.Bl -tag -width "/etc/malloc.conf"
306.It Pa /etc/malloc.conf
307symbolic link to filename containing option flags
308.El
309.Sh DIAGNOSTICS
310If
311.Fn malloc ,
312.Fn calloc ,
313.Fn realloc ,
314or
315.Fn free
316detect an error or warning condition,
317a message will be printed to file descriptor
3182 (not using stdio).
319Errors will always result in the process being
320.Xr abort 3 'ed.
321If the
322.Cm A
323option has been specified, warnings will also
324.Xr abort 3
325the process.
326.Pp
327Here is a brief description of the error messages and what they mean:
328.Bl -tag -width Fl
329.It Dq (ES): mumble mumble mumble
330.Fn malloc
331has been compiled with
332.Dv \&-DEXTRA_SANITY
333and something looks fishy in there.
334Consult sources and/or wizards.
335.It Dq allocation failed
336If the
337.Cm A
338option is specified it is an error for
339.Fn malloc ,
340.Fn calloc ,
341or
342.Fn realloc
343to return
344.Dv NULL .
345.It Dq mmap(2) failed, check limits.
346This is a rather weird condition that is most likely to indicate a
347seriously overloaded system or a
348.Xr ulimit 1
349restriction.
350.It Dq freelist is destroyed.
351.Fn malloc Ns 's
352internal freelist has been stomped on.
353.El
354.Pp
355Here is a brief description of the warning messages and what they mean:
356.Bl -tag -width Fl
357.It Dq chunk/page is already free.
358There was an attempt to free a chunk that had already been freed.
359.It Dq junk pointer, too high to make sense.
360The pointer doesn't make sense.
361It's above the area of memory that
362.Fn malloc
363knows something about.
364This could be a pointer from some
365.Xr mmap 2 'ed
366memory.
367.It Dq junk pointer, too low to make sense.
368The pointer doesn't make sense.
369It's below the area of memory that
370.Fn malloc
371knows something about.
372This pointer probably came from your data or bss segments.
373.It Dq malloc() has never been called.
374Nothing has ever been allocated, yet something is being freed or
375realloc'ed.
376.It Dq modified (chunk-/page-) pointer.
377The pointer passed to free or realloc has been modified.
378.It Dq pointer to wrong page.
379The pointer that
380.Fn malloc
381is trying to free is not pointing to
382a sensible page.
383.It Dq recursive call.
384An attempt was made to call recursively into these functions, i.e., from a
385signal handler.
386This behavior is not supported.
387In particular, signal handlers should
388.Em not
389use any of the
390.Fn malloc
391functions nor utilize any other functions which may call
392.Fn malloc
393(e.g.,
394.Xr stdio 3
395routines).
396.It Dq unknown char in MALLOC_OPTIONS
397We found something we didn't understand.
398.El
399.Sh SEE ALSO
400.Xr brk 2 ,
401.Xr alloca 3 ,
402.Xr getpagesize 3
403.Sh STANDARDS
404The
405.Fn malloc
406function conforms to
407.St -ansiC .
408.Sh HISTORY
409The present implementation of
410.Fn malloc
411started out as a filesystem on a drum
412attached to a 20-bit binary challenged computer built with discrete germanium
413transistors, and it has since graduated to handle primary storage rather than
414secondary.
415.Pp
416The main difference from other
417.Fn malloc
418implementations are believed to be that
419the free pages are not accessed until allocated.
420Most
421.Fn malloc
422implementations will store a data structure containing a,
423possibly double-, linked list in the free chunks of memory, used to tie
424all the free memory together.
425That is a quite suboptimal thing to do.
426Every time the free-list is traversed, all the otherwise unused, and very
427likely paged out, pages get faulted into primary memory, just to see what
428lies after them in the list.
429.Pp
430On systems which are paging, this can increase the page-faults
431of a process by a factor of five.
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c
new file mode 100644
index 0000000000..ae89f5d72b
--- /dev/null
+++ b/src/lib/libc/stdlib/malloc.c
@@ -0,0 +1,1698 @@
1/*
2 * ----------------------------------------------------------------------------
3 * "THE BEER-WARE LICENSE" (Revision 42):
4 * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you
5 * can do whatever you want with this stuff. If we meet some day, and you think
6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
7 * ----------------------------------------------------------------------------
8 */
9
10#if defined(LIBC_SCCS) && !defined(lint)
11static char rcsid[] = "$OpenBSD: malloc.c,v 1.72 2005/03/31 21:24:46 tdeval Exp $";
12#endif /* LIBC_SCCS and not lint */
13
14/*
15 * Defining MALLOC_EXTRA_SANITY will enable extra checks which are
16 * related to internal conditions and consistency in malloc.c. This has
17 * a noticeable runtime performance hit, and generally will not do you
18 * any good unless you fiddle with the internals of malloc or want
19 * to catch random pointer corruption as early as possible.
20 */
21#ifndef MALLOC_EXTRA_SANITY
22#undef MALLOC_EXTRA_SANITY
23#endif
24
25/*
26 * Defining MALLOC_STATS will enable you to call malloc_dump() and set
27 * the [dD] options in the MALLOC_OPTIONS environment variable.
28 * It has no run-time performance hit, but does pull in stdio...
29 */
30#ifndef MALLOC_STATS
31#undef MALLOC_STATS
32#endif
33
34/*
35 * What to use for Junk. This is the byte value we use to fill with
36 * when the 'J' option is enabled.
37 */
38#define SOME_JUNK 0xd0 /* as in "Duh" :-) */
39
40#include <sys/types.h>
41#include <sys/time.h>
42#include <sys/resource.h>
43#include <sys/param.h>
44#include <sys/mman.h>
45#include <sys/uio.h>
46#include <stdio.h>
47#include <stdlib.h>
48#include <string.h>
49#include <unistd.h>
50#include <fcntl.h>
51#include <limits.h>
52#include <errno.h>
53
54#include "thread_private.h"
55
56/*
57 * The basic parameters you can tweak.
58 *
59 * malloc_pageshift pagesize = 1 << malloc_pageshift
60 * It's probably best if this is the native
61 * page size, but it shouldn't have to be.
62 *
63 * malloc_minsize minimum size of an allocation in bytes.
64 * If this is too small it's too much work
65 * to manage them. This is also the smallest
66 * unit of alignment used for the storage
67 * returned by malloc/realloc.
68 *
69 */
70
71#if defined(__OpenBSD__) && defined(__sparc__)
72# define malloc_pageshift 13U
73#endif /* __OpenBSD__ */
74
75/*
76 * No user serviceable parts behind this point.
77 *
78 * This structure describes a page worth of chunks.
79 */
80
81struct pginfo {
82 struct pginfo *next; /* next on the free list */
83 void *page; /* Pointer to the page */
84 u_short size; /* size of this page's chunks */
85 u_short shift; /* How far to shift for this size chunks */
86 u_short free; /* How many free chunks */
87 u_short total; /* How many chunk */
88 u_long bits[1]; /* Which chunks are free */
89};
90
91/*
92 * This structure describes a number of free pages.
93 */
94
95struct pgfree {
96 struct pgfree *next; /* next run of free pages */
97 struct pgfree *prev; /* prev run of free pages */
98 void *page; /* pointer to free pages */
99 void *pdir; /* pointer to the base page's dir */
100 size_t size; /* number of bytes free */
101};
102
103/*
104 * How many bits per u_long in the bitmap.
105 * Change only if not 8 bits/byte
106 */
107#define MALLOC_BITS (8*sizeof(u_long))
108
109/*
110 * Magic values to put in the page_directory
111 */
112#define MALLOC_NOT_MINE ((struct pginfo*) 0)
113#define MALLOC_FREE ((struct pginfo*) 1)
114#define MALLOC_FIRST ((struct pginfo*) 2)
115#define MALLOC_FOLLOW ((struct pginfo*) 3)
116#define MALLOC_MAGIC ((struct pginfo*) 4)
117
118#ifndef malloc_pageshift
119#define malloc_pageshift (PGSHIFT)
120#endif
121
122#ifndef malloc_minsize
123#define malloc_minsize 16U
124#endif
125
126#ifndef malloc_pageshift
127#error "malloc_pageshift undefined"
128#endif
129
130#if !defined(malloc_pagesize)
131#define malloc_pagesize (1UL<<malloc_pageshift)
132#endif
133
134#if ((1UL<<malloc_pageshift) != malloc_pagesize)
135#error "(1UL<<malloc_pageshift) != malloc_pagesize"
136#endif
137
138#ifndef malloc_maxsize
139#define malloc_maxsize ((malloc_pagesize)>>1)
140#endif
141
142/* A mask for the offset inside a page. */
143#define malloc_pagemask ((malloc_pagesize)-1)
144
145#define pageround(foo) (((foo) + (malloc_pagemask)) & ~malloc_pagemask)
146#define ptr2index(foo) (((u_long)(foo) >> malloc_pageshift)+malloc_pageshift)
147
148/* fd of /dev/zero */
149#ifdef USE_DEV_ZERO
150static int fdzero;
151#define MMAP_FD fdzero
152#define INIT_MMAP() \
153 { if ((fdzero=open("/dev/zero", O_RDWR, 0000)) == -1) \
154 wrterror("open of /dev/zero\n"); }
155#else
156#define MMAP_FD (-1)
157#define INIT_MMAP()
158#endif
159
160/* Set when initialization has been done */
161static unsigned int malloc_started;
162
163/* Number of free pages we cache */
164static unsigned int malloc_cache = 16;
165
166/* Structure used for linking discrete directory pages. */
167struct pdinfo {
168 struct pginfo **base;
169 struct pdinfo *prev;
170 struct pdinfo *next;
171 u_long dirnum;
172};
173static struct pdinfo *last_dir; /* Caches to the last and previous */
174static struct pdinfo *prev_dir; /* referenced directory pages. */
175
176static size_t pdi_off;
177static u_long pdi_mod;
178#define PD_IDX(num) ((num) / (malloc_pagesize/sizeof(struct pginfo *)))
179#define PD_OFF(num) ((num) & ((malloc_pagesize/sizeof(struct pginfo *))-1))
180#define PI_IDX(index) ((index) / pdi_mod)
181#define PI_OFF(index) ((index) % pdi_mod)
182
183/* The last index in the page directory we care about */
184static u_long last_index;
185
186/* Pointer to page directory. Allocated "as if with" malloc */
187static struct pginfo **page_dir;
188
189/* Free pages line up here */
190static struct pgfree free_list;
191
192/* Abort(), user doesn't handle problems. */
193static int malloc_abort = 2;
194
195/* Are we trying to die ? */
196static int suicide;
197
198#ifdef MALLOC_STATS
199/* dump statistics */
200static int malloc_stats;
201#endif
202
203/* avoid outputting warnings? */
204static int malloc_silent;
205
206/* always realloc ? */
207static int malloc_realloc;
208
209/* mprotect free pages PROT_NONE? */
210static int malloc_freeprot;
211
212/* use guard pages after allocations? */
213static int malloc_guard = 0;
214
215#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
216/* pass the kernel a hint on free pages ? */
217static int malloc_hint;
218#endif
219
220/* xmalloc behaviour ? */
221static int malloc_xmalloc;
222
223/* zero fill ? */
224static int malloc_zero;
225
226/* junk fill ? */
227static int malloc_junk;
228
229#ifdef __FreeBSD__
230/* utrace ? */
231static int malloc_utrace;
232
233struct ut { void *p; size_t s; void *r; };
234
235void utrace(struct ut *, int);
236
237#define UTRACE(a, b, c) \
238 if (malloc_utrace) \
239 {struct ut u; u.p=a; u.s = b; u.r=c; utrace(&u, sizeof u);}
240#else /* !__FreeBSD__ */
241#define UTRACE(a,b,c)
242#endif
243
244/* Status of malloc. */
245static int malloc_active;
246
247/* Allocated memory. */
248static size_t malloc_used;
249
250/* My last break. */
251static void *malloc_brk;
252
253/* One location cache for free-list holders. */
254static struct pgfree *px;
255
256/* Compile-time options. */
257char *malloc_options;
258
259/* Name of the current public function. */
260static char *malloc_func;
261
262/* Macro for mmap. */
263#define MMAP(size) \
264 mmap((void *)0, (size), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, \
265 MMAP_FD, (off_t)0)
266
267/*
268 * Necessary function declarations.
269 */
270static void *imalloc(size_t size);
271static void ifree(void *ptr);
272static void *irealloc(void *ptr, size_t size);
273static void *malloc_bytes(size_t size);
274
275
276/*
277 * Function for page directory lookup.
278 */
279static int
280pdir_lookup(u_long index, struct pdinfo **pdi)
281{
282 struct pdinfo *spi;
283 u_long pidx = PI_IDX(index);
284
285 if (last_dir != NULL && PD_IDX(last_dir->dirnum) == pidx)
286 *pdi = last_dir;
287 else if (prev_dir != NULL && PD_IDX(prev_dir->dirnum) == pidx)
288 *pdi = prev_dir;
289 else if (last_dir != NULL && prev_dir != NULL) {
290 if ((PD_IDX(last_dir->dirnum) > pidx) ?
291 (PD_IDX(last_dir->dirnum) - pidx):(pidx - PD_IDX(last_dir->dirnum))
292 < (PD_IDX(prev_dir->dirnum) > pidx) ?
293 (PD_IDX(prev_dir->dirnum) - pidx):(pidx - PD_IDX(prev_dir->dirnum)))
294 *pdi = last_dir;
295 else
296 *pdi = prev_dir;
297
298 if (PD_IDX((*pdi)->dirnum) > pidx) {
299 for (spi=(*pdi)->prev;spi!=NULL && PD_IDX(spi->dirnum)>pidx;
300 spi=spi->prev)
301 *pdi = spi;
302 if (spi != NULL)
303 *pdi = spi;
304 } else
305 for (spi=(*pdi)->next;spi!=NULL && PD_IDX(spi->dirnum)<=pidx;
306 spi=spi->next)
307 *pdi = spi;
308 } else {
309 *pdi = (struct pdinfo *)((caddr_t)page_dir + pdi_off);
310 for (spi=*pdi;spi!=NULL && PD_IDX(spi->dirnum)<=pidx;spi=spi->next)
311 *pdi = spi;
312 }
313
314 return ((PD_IDX((*pdi)->dirnum) == pidx)?0:(PD_IDX((*pdi)->dirnum) > pidx)?1:-1);
315}
316
317
318#ifdef MALLOC_STATS
319void
320malloc_dump(FILE *fd)
321{
322 struct pginfo **pd;
323 struct pgfree *pf;
324 struct pdinfo *pi;
325 int j;
326
327 pd = page_dir;
328 pi = (struct pdinfo *)((caddr_t)pd + pdi_off);
329
330 /* print out all the pages */
331 for(j=0;j<=last_index;) {
332 fprintf(fd, "%08lx %5d ", j << malloc_pageshift, j);
333 if (pd[PI_OFF(j)] == MALLOC_NOT_MINE) {
334 for(j++;j<=last_index && pd[PI_OFF(j)] == MALLOC_NOT_MINE;) {
335 if (!PI_OFF(++j)) {
336 if ((pi = pi->next) == NULL ||
337 PD_IDX(pi->dirnum) != PI_IDX(j)) break;
338 pd = pi->base;
339 j += pdi_mod;
340 }
341 }
342 j--;
343 fprintf(fd, ".. %5d not mine\n", j);
344 } else if (pd[PI_OFF(j)] == MALLOC_FREE) {
345 for(j++;j<=last_index && pd[PI_OFF(j)] == MALLOC_FREE;) {
346 if (!PI_OFF(++j)) {
347 if ((pi = pi->next) == NULL ||
348 PD_IDX(pi->dirnum) != PI_IDX(j)) break;
349 pd = pi->base;
350 j += pdi_mod;
351 }
352 }
353 j--;
354 fprintf(fd, ".. %5d free\n", j);
355 } else if (pd[PI_OFF(j)] == MALLOC_FIRST) {
356 for(j++;j<=last_index && pd[PI_OFF(j)] == MALLOC_FOLLOW;) {
357 if (!PI_OFF(++j)) {
358 if ((pi = pi->next) == NULL ||
359 PD_IDX(pi->dirnum) != PI_IDX(j)) break;
360 pd = pi->base;
361 j += pdi_mod;
362 }
363 }
364 j--;
365 fprintf(fd, ".. %5d in use\n", j);
366 } else if (pd[PI_OFF(j)] < MALLOC_MAGIC) {
367 fprintf(fd, "(%p)\n", pd[PI_OFF(j)]);
368 } else {
369 fprintf(fd, "%p %d (of %d) x %d @ %p --> %p\n",
370 pd[PI_OFF(j)], pd[PI_OFF(j)]->free, pd[PI_OFF(j)]->total,
371 pd[PI_OFF(j)]->size, pd[PI_OFF(j)]->page, pd[PI_OFF(j)]->next);
372 }
373 if (!PI_OFF(++j)) {
374 if ((pi = pi->next) == NULL)
375 break;
376 pd = pi->base;
377 j += (1 + PD_IDX(pi->dirnum) - PI_IDX(j)) * pdi_mod;
378 }
379 }
380
381 for(pf=free_list.next; pf; pf=pf->next) {
382 fprintf(fd, "Free: @%p [%p...%p[ %ld ->%p <-%p\n",
383 pf, pf->page, pf->page + pf->size, pf->size,
384 pf->prev, pf->next);
385 if (pf == pf->next) {
386 fprintf(fd, "Free_list loops\n");
387 break;
388 }
389 }
390
391 /* print out various info */
392 fprintf(fd, "Minsize\t%d\n", malloc_minsize);
393 fprintf(fd, "Maxsize\t%d\n", malloc_maxsize);
394 fprintf(fd, "Pagesize\t%lu\n", (u_long)malloc_pagesize);
395 fprintf(fd, "Pageshift\t%d\n", malloc_pageshift);
396 fprintf(fd, "In use\t%lu\n", (u_long)malloc_used);
397}
398#endif /* MALLOC_STATS */
399
400extern char *__progname;
401
402static void
403wrterror(char *p)
404{
405 char *q = " error: ";
406 struct iovec iov[4];
407
408 iov[0].iov_base = __progname;
409 iov[0].iov_len = strlen(__progname);
410 iov[1].iov_base = malloc_func;
411 iov[1].iov_len = strlen(malloc_func);
412 iov[2].iov_base = q;
413 iov[2].iov_len = strlen(q);
414 iov[3].iov_base = p;
415 iov[3].iov_len = strlen(p);
416 writev(STDERR_FILENO, iov, 4);
417
418 suicide = 1;
419#ifdef MALLOC_STATS
420 if (malloc_stats)
421 malloc_dump(stderr);
422#endif /* MALLOC_STATS */
423 malloc_active--;
424 if (malloc_abort)
425 abort();
426}
427
428static void
429wrtwarning(char *p)
430{
431 char *q = " warning: ";
432 struct iovec iov[4];
433
434 if (malloc_abort)
435 wrterror(p);
436 else if (malloc_silent)
437 return;
438
439 iov[0].iov_base = __progname;
440 iov[0].iov_len = strlen(__progname);
441 iov[1].iov_base = malloc_func;
442 iov[1].iov_len = strlen(malloc_func);
443 iov[2].iov_base = q;
444 iov[2].iov_len = strlen(q);
445 iov[3].iov_base = p;
446 iov[3].iov_len = strlen(p);
447 writev(STDERR_FILENO, iov, 4);
448}
449
450#ifdef MALLOC_STATS
451static void
452malloc_exit(void)
453{
454 FILE *fd = fopen("malloc.out", "a");
455 char *q = "malloc() warning: Couldn't dump stats\n";
456 if (fd != NULL) {
457 malloc_dump(fd);
458 fclose(fd);
459 } else
460 write(STDERR_FILENO, q, strlen(q));
461}
462#endif /* MALLOC_STATS */
463
464
465/*
466 * Allocate a number of pages from the OS
467 */
468static void *
469map_pages(size_t pages)
470{
471 struct pdinfo *pi, *spi;
472 struct pginfo **pd;
473 u_long pidx,lidx;
474 void *result, *tail;
475 u_long index;
476
477 pages <<= malloc_pageshift;
478 result = MMAP(pages + malloc_guard);
479 if (result == MAP_FAILED) {
480 errno = ENOMEM;
481#ifdef MALLOC_EXTRA_SANITY
482 wrtwarning("(ES): map_pages fails\n");
483#endif /* MALLOC_EXTRA_SANITY */
484 return (NULL);
485 }
486 tail = result + pages + malloc_guard;
487 if (malloc_guard)
488 mprotect(result + pages, malloc_guard, PROT_NONE);
489
490 if (tail > malloc_brk)
491 malloc_brk = tail;
492 if ((index = ptr2index(tail) - 1) > last_index)
493 last_index = index;
494
495 /* Insert directory pages, if needed. */
496 pidx = PI_IDX(ptr2index(result));
497 lidx = PI_IDX(index);
498
499 pdir_lookup(ptr2index(result), &pi);
500
501 for (index=pidx,spi=pi;index<=lidx;index++) {
502 if (pi == NULL || PD_IDX(pi->dirnum) != index) {
503 if ((pd = MMAP(malloc_pagesize)) == MAP_FAILED) {
504 errno = ENOMEM;
505 munmap(result, tail - result);
506#ifdef MALLOC_EXTRA_SANITY
507 wrtwarning("(ES): map_pages fails\n");
508#endif /* MALLOC_EXTRA_SANITY */
509 return (NULL);
510 }
511 memset(pd, 0, malloc_pagesize);
512 pi = (struct pdinfo *)((caddr_t)pd + pdi_off);
513 pi->base = pd;
514 pi->prev = spi;
515 pi->next = spi->next;
516 pi->dirnum = index * (malloc_pagesize/sizeof(struct pginfo *));
517
518 if (spi->next != NULL)
519 spi->next->prev = pi;
520 spi->next = pi;
521 }
522 if (index > pidx && index < lidx) {
523 pi->dirnum += pdi_mod;
524 } else if (index == pidx) {
525 if (pidx == lidx) {
526 pi->dirnum += (tail - result) >> malloc_pageshift;
527 } else {
528 pi->dirnum += pdi_mod - PI_OFF(ptr2index(result));
529 }
530 } else {
531 pi->dirnum += PI_OFF(ptr2index(tail - 1)) + 1;
532 }
533#ifdef MALLOC_EXTRA_SANITY
534 if (PD_OFF(pi->dirnum) > pdi_mod || PD_IDX(pi->dirnum) > index) {
535 wrterror("(ES): pages directory overflow\n");
536 errno = EFAULT;
537 return (NULL);
538 }
539#endif /* MALLOC_EXTRA_SANITY */
540 if (index == pidx && pi != last_dir) {
541 prev_dir = last_dir;
542 last_dir = pi;
543 }
544 spi = pi;
545 pi = spi->next;
546 }
547
548 return (result);
549}
550
551
552/*
553 * Initialize the world
554 */
555static void
556malloc_init(void)
557{
558 char *p, b[64];
559 int i, j;
560 int save_errno = errno;
561
562 _MALLOC_LOCK_INIT();
563
564 INIT_MMAP();
565
566#ifdef MALLOC_EXTRA_SANITY
567 malloc_junk = 1;
568#endif /* MALLOC_EXTRA_SANITY */
569
570 for (i = 0; i < 3; i++) {
571 switch (i) {
572 case 0:
573 j = readlink("/etc/malloc.conf", b, sizeof b - 1);
574 if (j <= 0)
575 continue;
576 b[j] = '\0';
577 p = b;
578 break;
579
580 case 1:
581 if (issetugid() == 0)
582 p = getenv("MALLOC_OPTIONS");
583 else
584 continue;
585 break;
586
587 case 2:
588 p = malloc_options;
589 break;
590
591 default: p = NULL;
592 }
593 for (; p != NULL && *p != '\0'; p++) {
594 switch (*p) {
595 case '>': malloc_cache <<= 1; break;
596 case '<': malloc_cache >>= 1; break;
597 case 'a': malloc_abort = 0; break;
598 case 'A': malloc_abort = 1; break;
599#ifdef MALLOC_STATS
600 case 'd': malloc_stats = 0; break;
601 case 'D': malloc_stats = 1; break;
602#endif /* MALLOC_STATS */
603 case 'f': malloc_freeprot = 0; break;
604 case 'F': malloc_freeprot = 1; break;
605 case 'g': malloc_guard = 0; break;
606 case 'G': malloc_guard = malloc_pagesize; break;
607#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
608 case 'h': malloc_hint = 0; break;
609 case 'H': malloc_hint = 1; break;
610#endif /* __FreeBSD__ */
611 case 'j': malloc_junk = 0; break;
612 case 'J': malloc_junk = 1; break;
613 case 'n': malloc_silent = 0; break;
614 case 'N': malloc_silent = 1; break;
615 case 'r': malloc_realloc = 0; break;
616 case 'R': malloc_realloc = 1; break;
617#ifdef __FreeBSD__
618 case 'u': malloc_utrace = 0; break;
619 case 'U': malloc_utrace = 1; break;
620#endif /* __FreeBSD__ */
621 case 'x': malloc_xmalloc = 0; break;
622 case 'X': malloc_xmalloc = 1; break;
623 case 'z': malloc_zero = 0; break;
624 case 'Z': malloc_zero = 1; break;
625 default:
626 j = malloc_abort;
627 malloc_abort = 0;
628 wrtwarning("unknown char in MALLOC_OPTIONS\n");
629 malloc_abort = j;
630 break;
631 }
632 }
633 }
634
635 UTRACE(0, 0, 0);
636
637 /*
638 * We want junk in the entire allocation, and zero only in the part
639 * the user asked for.
640 */
641 if (malloc_zero)
642 malloc_junk=1;
643
644#ifdef MALLOC_STATS
645 if (malloc_stats && (atexit(malloc_exit) == -1))
646 wrtwarning("atexit(2) failed. Will not be able to dump malloc stats on exit\n");
647#endif /* MALLOC_STATS */
648
649 /* Allocate one page for the page directory. */
650 page_dir = (struct pginfo **) MMAP(malloc_pagesize);
651
652 if (page_dir == MAP_FAILED) {
653 wrterror("mmap(2) failed, check limits\n");
654 errno = ENOMEM;
655 return;
656 }
657
658 pdi_off = (malloc_pagesize - sizeof(struct pdinfo)) & ~(malloc_minsize - 1);
659 pdi_mod = pdi_off / sizeof(struct pginfo *);
660
661 last_dir = (struct pdinfo *)((caddr_t)page_dir + pdi_off);
662 last_dir->base = page_dir;
663 last_dir->prev = last_dir->next = NULL;
664 last_dir->dirnum = malloc_pageshift;
665
666 /* Been here, done that. */
667 malloc_started++;
668
669 /* Recalculate the cache size in bytes, and make sure it's nonzero. */
670
671 if (!malloc_cache)
672 malloc_cache++;
673
674 malloc_cache <<= malloc_pageshift;
675
676 errno = save_errno;
677}
678
679/*
680 * Allocate a number of complete pages
681 */
682static void *
683malloc_pages(size_t size)
684{
685 void *p, *delay_free = NULL;
686 int i;
687 struct rlimit rl;
688 struct pginfo **pd;
689 struct pdinfo *pi;
690 u_long pidx;
691 void *tp;
692 struct pgfree *pf;
693 u_long index;
694 int m;
695
696 size = pageround(size) + malloc_guard;
697
698 p = NULL;
699 /* Look for free pages before asking for more */
700 for (pf = free_list.next; pf; pf = pf->next) {
701
702#ifdef MALLOC_EXTRA_SANITY
703 if (pf->size & malloc_pagemask) {
704 wrterror("(ES): junk length entry on free_list\n");
705 errno = EFAULT;
706 return (NULL);
707 }
708 if (!pf->size) {
709 wrterror("(ES): zero length entry on free_list\n");
710 errno = EFAULT;
711 return (NULL);
712 }
713 if (pf->page > (pf->page + pf->size)) {
714 wrterror("(ES): sick entry on free_list\n");
715 errno = EFAULT;
716 return (NULL);
717 }
718 if ((pi = pf->pdir) == NULL) {
719 wrterror("(ES): invalid page directory on free-list\n");
720 errno = EFAULT;
721 return (NULL);
722 }
723 if ((pidx = PI_IDX(ptr2index(pf->page))) != PD_IDX(pi->dirnum)) {
724 wrterror("(ES): directory index mismatch on free-list\n");
725 errno = EFAULT;
726 return (NULL);
727 }
728 pd = pi->base;
729 if (pd[PI_OFF(ptr2index(pf->page))] != MALLOC_FREE) {
730 wrterror("(ES): non-free first page on free-list\n");
731 errno = EFAULT;
732 return (NULL);
733 }
734 pidx = PI_IDX(ptr2index((pf->page)+(pf->size))-1);
735 for (pi=pf->pdir; pi!=NULL && PD_IDX(pi->dirnum)<pidx; pi=pi->next);
736 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
737 wrterror("(ES): last page not referenced in page directory\n");
738 errno = EFAULT;
739 return (NULL);
740 }
741 pd = pi->base;
742 if (pd[PI_OFF(ptr2index((pf->page)+(pf->size))-1)] != MALLOC_FREE) {
743 wrterror("(ES): non-free last page on free-list\n");
744 errno = EFAULT;
745 return (NULL);
746 }
747#endif /* MALLOC_EXTRA_SANITY */
748
749 if (pf->size < size)
750 continue;
751
752 if (pf->size == size) {
753 p = pf->page;
754 pi = pf->pdir;
755 if (pf->next != NULL)
756 pf->next->prev = pf->prev;
757 pf->prev->next = pf->next;
758 delay_free = pf;
759 break;
760 }
761
762 p = pf->page;
763 pf->page = (char *)pf->page + size;
764 pf->size -= size;
765 pidx = PI_IDX(ptr2index(pf->page));
766 for (pi=pf->pdir; pi!=NULL && PD_IDX(pi->dirnum)<pidx; pi=pi->next);
767 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
768 wrterror("(ES): hole in directories\n");
769 errno = EFAULT;
770 return (NULL);
771 }
772 tp = pf->pdir;
773 pf->pdir = pi;
774 pi = tp;
775 break;
776 }
777
778 size -= malloc_guard;
779
780#ifdef MALLOC_EXTRA_SANITY
781 if (p != NULL && pi != NULL) {
782 pidx = PD_IDX(pi->dirnum);
783 pd = pi->base;
784 }
785 if (p != NULL && pd[PI_OFF(ptr2index(p))] != MALLOC_FREE) {
786 wrterror("(ES): allocated non-free page on free-list\n");
787 errno = EFAULT;
788 return (NULL);
789 }
790#endif /* MALLOC_EXTRA_SANITY */
791
792 if (p != NULL && (malloc_guard || malloc_freeprot))
793 mprotect(p, size, PROT_READ|PROT_WRITE);
794
795 size >>= malloc_pageshift;
796
797 /* Map new pages */
798 if (p == NULL)
799 p = map_pages(size);
800
801 if (p != NULL) {
802
803 index = ptr2index(p);
804 pidx = PI_IDX(index);
805 pdir_lookup(index, &pi);
806#ifdef MALLOC_EXTRA_SANITY
807 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
808 wrterror("(ES): mapped pages not found in directory\n");
809 errno = EFAULT;
810 return (NULL);
811 }
812#endif /* MALLOC_EXTRA_SANITY */
813 if (pi != last_dir) {
814 prev_dir = last_dir;
815 last_dir = pi;
816 }
817 pd = pi->base;
818 pd[PI_OFF(index)] = MALLOC_FIRST;
819 for (i=1;i<size;i++) {
820 if (!PI_OFF(index+i)) {
821 pidx++;
822 pi = pi->next;
823#ifdef MALLOC_EXTRA_SANITY
824 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
825 wrterror("(ES): hole in mapped pages directory\n");
826 errno = EFAULT;
827 return (NULL);
828 }
829#endif /* MALLOC_EXTRA_SANITY */
830 pd = pi->base;
831 }
832 pd[PI_OFF(index+i)] = MALLOC_FOLLOW;
833 }
834 if (malloc_guard) {
835 if (!PI_OFF(index+i)) {
836 pidx++;
837 pi = pi->next;
838#ifdef MALLOC_EXTRA_SANITY
839 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
840 wrterror("(ES): hole in mapped pages directory\n");
841 errno = EFAULT;
842 return (NULL);
843 }
844#endif /* MALLOC_EXTRA_SANITY */
845 pd = pi->base;
846 }
847 pd[PI_OFF(index+i)] = MALLOC_FIRST;
848 }
849
850 malloc_used += size << malloc_pageshift;
851
852 if (malloc_junk)
853 memset(p, SOME_JUNK, size << malloc_pageshift);
854 }
855
856 if (delay_free) {
857 if (px == NULL)
858 px = delay_free;
859 else
860 ifree(delay_free);
861 }
862
863 return (p);
864}
865
866/*
867 * Allocate a page of fragments
868 */
869
870static __inline__ int
871malloc_make_chunks(int bits)
872{
873 struct pginfo *bp;
874 struct pginfo **pd;
875 struct pdinfo *pi;
876 u_long pidx;
877 void *pp;
878 int i, k, l;
879
880 /* Allocate a new bucket */
881 pp = malloc_pages((size_t)malloc_pagesize);
882 if (pp == NULL)
883 return (0);
884
885 /* Find length of admin structure */
886 l = sizeof *bp - sizeof(u_long);
887 l += sizeof(u_long) *
888 (((malloc_pagesize >> bits)+MALLOC_BITS-1) / MALLOC_BITS);
889
890 /* Don't waste more than two chunks on this */
891 /*
892 * If we are to allocate a memory protected page for the malloc(0)
893 * case (when bits=0), it must be from a different page than the
894 * pginfo page.
895 * --> Treat it like the big chunk alloc, get a second data page.
896 */
897 if (bits != 0 && (1UL<<(bits)) <= l+l) {
898 bp = (struct pginfo *)pp;
899 } else {
900 bp = (struct pginfo *)imalloc(l);
901 if (bp == NULL) {
902 ifree(pp);
903 return (0);
904 }
905 }
906
907 /* memory protect the page allocated in the malloc(0) case */
908 if (bits == 0) {
909
910 bp->size = 0;
911 bp->shift = 1;
912 i = malloc_minsize-1;
913 while (i >>= 1)
914 bp->shift++;
915 bp->total = bp->free = malloc_pagesize >> bp->shift;
916 bp->page = pp;
917
918 k = mprotect(pp, malloc_pagesize, PROT_NONE);
919 if (k < 0) {
920 ifree(pp);
921 ifree(bp);
922 return (0);
923 }
924 } else {
925 bp->size = (1UL<<bits);
926 bp->shift = bits;
927 bp->total = bp->free = malloc_pagesize >> bits;
928 bp->page = pp;
929 }
930
931 /* set all valid bits in the bitmap */
932 k = bp->total;
933 i = 0;
934
935 /* Do a bunch at a time */
936 for(;k-i >= MALLOC_BITS; i += MALLOC_BITS)
937 bp->bits[i / MALLOC_BITS] = ~0UL;
938
939 for(; i < k; i++)
940 bp->bits[i/MALLOC_BITS] |= 1UL<<(i%MALLOC_BITS);
941
942 if (bp == bp->page) {
943 /* Mark the ones we stole for ourselves */
944 for(i=0;l > 0;i++) {
945 bp->bits[i/MALLOC_BITS] &= ~(1UL<<(i%MALLOC_BITS));
946 bp->free--;
947 bp->total--;
948 l -= (1 << bits);
949 }
950 }
951
952 /* MALLOC_LOCK */
953
954 pidx = PI_IDX(ptr2index(pp));
955 pdir_lookup(ptr2index(pp), &pi);
956#ifdef MALLOC_EXTRA_SANITY
957 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
958 wrterror("(ES): mapped pages not found in directory\n");
959 errno = EFAULT;
960 return (0);
961 }
962#endif /* MALLOC_EXTRA_SANITY */
963 if (pi != last_dir) {
964 prev_dir = last_dir;
965 last_dir = pi;
966 }
967 pd = pi->base;
968 pd[PI_OFF(ptr2index(pp))] = bp;
969
970 bp->next = page_dir[bits];
971 page_dir[bits] = bp;
972
973 /* MALLOC_UNLOCK */
974
975 return (1);
976}
977
978/*
979 * Allocate a fragment
980 */
981static void *
982malloc_bytes(size_t size)
983{
984 int i,j;
985 u_long u;
986 struct pginfo *bp;
987 int k;
988 u_long *lp;
989
990 /* Don't bother with anything less than this */
991 /* unless we have a malloc(0) requests */
992 if (size != 0 && size < malloc_minsize)
993 size = malloc_minsize;
994
995 /* Find the right bucket */
996 if (size == 0)
997 j=0;
998 else {
999 j = 1;
1000 i = size-1;
1001 while (i >>= 1)
1002 j++;
1003 }
1004
1005 /* If it's empty, make a page more of that size chunks */
1006 if (page_dir[j] == NULL && !malloc_make_chunks(j))
1007 return (NULL);
1008
1009 bp = page_dir[j];
1010
1011 /* Find first word of bitmap which isn't empty */
1012 for (lp = bp->bits; !*lp; lp++)
1013 ;
1014
1015 /* Find that bit, and tweak it */
1016 u = 1;
1017 k = 0;
1018 while (!(*lp & u)) {
1019 u += u;
1020 k++;
1021 }
1022
1023 if (malloc_guard) {
1024 /* Walk to a random position. */
1025 i = arc4random() % bp->free;
1026 while (i > 0) {
1027 u += u;
1028 k++;
1029 if (k >= MALLOC_BITS) {
1030 lp++;
1031 u = 1;
1032 k = 0;
1033 }
1034#ifdef MALLOC_EXTRA_SANITY
1035 if (lp - bp->bits > (bp->total - 1) / MALLOC_BITS) {
1036 wrterror("chunk overflow\n");
1037 errno = EFAULT;
1038 return (NULL);
1039 }
1040#endif /* MALLOC_EXTRA_SANITY */
1041 if (*lp & u)
1042 i--;
1043 }
1044 }
1045 *lp ^= u;
1046
1047 /* If there are no more free, remove from free-list */
1048 if (!--bp->free) {
1049 page_dir[j] = bp->next;
1050 bp->next = NULL;
1051 }
1052
1053 /* Adjust to the real offset of that chunk */
1054 k += (lp-bp->bits)*MALLOC_BITS;
1055 k <<= bp->shift;
1056
1057 if (malloc_junk && bp->size != 0)
1058 memset((char *)bp->page + k, SOME_JUNK, bp->size);
1059
1060 return ((u_char *)bp->page + k);
1061}
1062
1063/*
1064 * Allocate a piece of memory
1065 */
1066static void *
1067imalloc(size_t size)
1068{
1069 void *result;
1070 int ptralloc = 0;
1071
1072 if (!malloc_started)
1073 malloc_init();
1074
1075 if (suicide)
1076 abort();
1077
1078 if ((size + malloc_pagesize) < size) { /* Check for overflow */
1079 result = NULL;
1080 errno = ENOMEM;
1081 }
1082 else if (size <= malloc_maxsize)
1083 result = malloc_bytes(size);
1084 else
1085 result = malloc_pages(size);
1086
1087 if (malloc_abort == 1 && result == NULL)
1088 wrterror("allocation failed\n");
1089
1090 if (malloc_zero && result != NULL)
1091 memset(result, 0, size);
1092
1093 return (result);
1094}
1095
1096/*
1097 * Change the size of an allocation.
1098 */
1099static void *
1100irealloc(void *ptr, size_t size)
1101{
1102 void *p;
1103 u_long osize, index, i;
1104 struct pginfo **mp;
1105 struct pginfo **pd;
1106 struct pdinfo *pi;
1107 u_long pidx;
1108
1109 if (suicide)
1110 abort();
1111
1112 if (!malloc_started) {
1113 wrtwarning("malloc() has never been called\n");
1114 return (NULL);
1115 }
1116
1117 index = ptr2index(ptr);
1118
1119 if (index < malloc_pageshift) {
1120 wrtwarning("junk pointer, too low to make sense\n");
1121 return (NULL);
1122 }
1123
1124 if (index > last_index) {
1125 wrtwarning("junk pointer, too high to make sense\n");
1126 return (NULL);
1127 }
1128
1129 pidx = PI_IDX(index);
1130 pdir_lookup(index, &pi);
1131#ifdef MALLOC_EXTRA_SANITY
1132 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1133 wrterror("(ES): mapped pages not found in directory\n");
1134 errno = EFAULT;
1135 return (NULL);
1136 }
1137#endif /* MALLOC_EXTRA_SANITY */
1138 if (pi != last_dir) {
1139 prev_dir = last_dir;
1140 last_dir = pi;
1141 }
1142
1143 pd = pi->base;
1144 mp = &pd[PI_OFF(index)];
1145
1146 if (*mp == MALLOC_FIRST) { /* Page allocation */
1147
1148 /* Check the pointer */
1149 if ((u_long)ptr & malloc_pagemask) {
1150 wrtwarning("modified (page-) pointer\n");
1151 return (NULL);
1152 }
1153
1154 /* Find the size in bytes */
1155 i = index;
1156 if (!PI_OFF(++i)) {
1157 pi = pi->next;
1158 if (pi != NULL && PD_IDX(pi->dirnum) != PI_IDX(i))
1159 pi = NULL;
1160 if (pi != NULL)
1161 pd = pi->base;
1162 }
1163 for (osize = malloc_pagesize;
1164 pi != NULL && pd[PI_OFF(i)] == MALLOC_FOLLOW;) {
1165 osize += malloc_pagesize;
1166 if (!PI_OFF(++i)) {
1167 pi = pi->next;
1168 if (pi != NULL && PD_IDX(pi->dirnum) != PI_IDX(i))
1169 pi = NULL;
1170 if (pi != NULL)
1171 pd = pi->base;
1172 }
1173 }
1174
1175 if (!malloc_realloc && /* Unless we have to, */
1176 size <= osize && /* .. or are too small, */
1177 size > (osize - malloc_pagesize)) { /* .. or can free a page, */
1178 if (malloc_junk)
1179 memset((char *)ptr + size, SOME_JUNK, osize-size);
1180 return (ptr); /* ..don't do anything else. */
1181 }
1182
1183 } else if (*mp >= MALLOC_MAGIC) { /* Chunk allocation */
1184
1185 /* Check the pointer for sane values */
1186 if ((u_long)ptr & ((1UL<<((*mp)->shift))-1)) {
1187 wrtwarning("modified (chunk-) pointer\n");
1188 return (NULL);
1189 }
1190
1191 /* Find the chunk index in the page */
1192 i = ((u_long)ptr & malloc_pagemask) >> (*mp)->shift;
1193
1194 /* Verify that it isn't a free chunk already */
1195 if ((*mp)->bits[i/MALLOC_BITS] & (1UL<<(i%MALLOC_BITS))) {
1196 wrtwarning("chunk is already free\n");
1197 return (NULL);
1198 }
1199
1200 osize = (*mp)->size;
1201
1202 if (!malloc_realloc && /* Unless we have to, */
1203 size <= osize && /* ..or are too small, */
1204 (size > osize/2 || /* ..or could use a smaller size, */
1205 osize == malloc_minsize)) { /* ..(if there is one) */
1206 if (malloc_junk)
1207 memset((char *)ptr + size, SOME_JUNK, osize-size);
1208 return (ptr); /* ..don't do anything else. */
1209 }
1210
1211 } else {
1212 wrtwarning("pointer to wrong page\n");
1213 return (NULL);
1214 }
1215
1216 p = imalloc(size);
1217
1218 if (p != NULL) {
1219 /* copy the lesser of the two sizes, and free the old one */
1220 /* Don't move from/to 0 sized region !!! */
1221 if (osize != 0 && size != 0) {
1222 if (osize < size)
1223 memcpy(p, ptr, osize);
1224 else
1225 memcpy(p, ptr, size);
1226 }
1227 ifree(ptr);
1228 }
1229
1230 return (p);
1231}
1232
1233/*
1234 * Free a sequence of pages
1235 */
1236
1237static __inline__ void
1238free_pages(void *ptr, u_long index, struct pginfo *info)
1239{
1240 u_long i, l;
1241 struct pginfo **pd;
1242 struct pdinfo *pi, *spi;
1243 u_long pidx, lidx;
1244 struct pgfree *pf, *pt=NULL;
1245 void *tail;
1246
1247 if (info == MALLOC_FREE) {
1248 wrtwarning("page is already free\n");
1249 return;
1250 }
1251
1252 if (info != MALLOC_FIRST) {
1253 wrtwarning("pointer to wrong page\n");
1254 return;
1255 }
1256
1257 if ((u_long)ptr & malloc_pagemask) {
1258 wrtwarning("modified (page-) pointer\n");
1259 return;
1260 }
1261
1262 /* Count how many pages and mark them free at the same time */
1263 pidx = PI_IDX(index);
1264 pdir_lookup(index, &pi);
1265#ifdef MALLOC_EXTRA_SANITY
1266 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1267 wrterror("(ES): mapped pages not found in directory\n");
1268 errno = EFAULT;
1269 return;
1270 }
1271#endif /* MALLOC_EXTRA_SANITY */
1272
1273 spi = pi; /* Save page index for start of region. */
1274
1275 pd = pi->base;
1276 pd[PI_OFF(index)] = MALLOC_FREE;
1277 i = 1;
1278 if (!PI_OFF(index+i)) {
1279 pi = pi->next;
1280 if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(index+i))
1281 pi = NULL;
1282 else
1283 pd = pi->base;
1284 }
1285 while (pi != NULL && pd[PI_OFF(index+i)] == MALLOC_FOLLOW) {
1286 pd[PI_OFF(index+i)] = MALLOC_FREE;
1287 i++;
1288 if (!PI_OFF(index+i)) {
1289 if ((pi=pi->next) == NULL || PD_IDX(pi->dirnum) != PI_IDX(index+i))
1290 pi = NULL;
1291 else
1292 pd = pi->base;
1293 }
1294 }
1295
1296 l = i << malloc_pageshift;
1297
1298 if (malloc_junk)
1299 memset(ptr, SOME_JUNK, l);
1300
1301 malloc_used -= l;
1302 if (malloc_guard) {
1303#ifdef MALLOC_EXTRA_SANITY
1304 if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(index+i)) {
1305 wrterror("(ES): hole in mapped pages directory\n");
1306 errno = EFAULT;
1307 return;
1308 }
1309#endif /* MALLOC_EXTRA_SANITY */
1310 pd[PI_OFF(index+i)] = MALLOC_FREE;
1311 l += malloc_guard;
1312 }
1313 tail = (char *)ptr + l;
1314
1315#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
1316 if (malloc_hint)
1317 madvise(ptr, l, MADV_FREE);
1318#endif
1319
1320 if (malloc_freeprot)
1321 mprotect(ptr, l, PROT_NONE);
1322
1323 /* Add to free-list. */
1324 if (px == NULL)
1325 px = imalloc(sizeof *px); /* This cannot fail... */
1326 px->page = ptr;
1327 px->pdir = spi;
1328 px->size = l;
1329
1330 if (free_list.next == NULL) {
1331
1332 /* Nothing on free list, put this at head. */
1333 px->next = NULL;
1334 px->prev = &free_list;
1335 free_list.next = px;
1336 pf = px;
1337 px = NULL;
1338
1339 } else {
1340
1341 /* Find the right spot, leave pf pointing to the modified entry. */
1342
1343 for(pf = free_list.next; (pf->page+pf->size) < ptr && pf->next != NULL;
1344 pf = pf->next)
1345 ; /* Race ahead here. */
1346
1347 if (pf->page > tail) {
1348 /* Insert before entry */
1349 px->next = pf;
1350 px->prev = pf->prev;
1351 pf->prev = px;
1352 px->prev->next = px;
1353 pf = px;
1354 px = NULL;
1355 } else if ((pf->page + pf->size) == ptr ) {
1356 /* Append to the previous entry. */
1357 pf->size += l;
1358 if (pf->next != NULL && (pf->page + pf->size) == pf->next->page ) {
1359 /* And collapse the next too. */
1360 pt = pf->next;
1361 pf->size += pt->size;
1362 pf->next = pt->next;
1363 if (pf->next != NULL)
1364 pf->next->prev = pf;
1365 }
1366 } else if (pf->page == tail) {
1367 /* Prepend to entry. */
1368 pf->size += l;
1369 pf->page = ptr;
1370 pf->pdir = spi;
1371 } else if (pf->next == NULL) {
1372 /* Append at tail of chain. */
1373 px->next = NULL;
1374 px->prev = pf;
1375 pf->next = px;
1376 pf = px;
1377 px = NULL;
1378 } else {
1379 wrterror("freelist is destroyed\n");
1380 errno = EFAULT;
1381 return;
1382 }
1383 }
1384
1385 if (pf->pdir != last_dir) {
1386 prev_dir = last_dir;
1387 last_dir = pf->pdir;
1388 }
1389
1390 /* Return something to OS ? */
1391 if (pf->next == NULL && /* If we're the last one, */
1392 pf->size > malloc_cache && /* ..and the cache is full, */
1393 (pf->page + pf->size) == malloc_brk) { /* ..and none behind us, */
1394
1395 /*
1396 * Keep the cache intact. Notice that the '>' above guarantees that
1397 * the pf will always have at least one page afterwards.
1398 */
1399 if (munmap((char *)pf->page + malloc_cache, pf->size - malloc_cache)!=0)
1400 goto not_return;
1401 tail = pf->page + pf->size;
1402 lidx = ptr2index(tail) - 1;
1403 pf->size = malloc_cache;
1404
1405 malloc_brk = pf->page + malloc_cache;
1406
1407 index = ptr2index(malloc_brk);
1408
1409 pidx = PI_IDX(index);
1410 if (prev_dir != NULL && PD_IDX(prev_dir->dirnum) >= pidx)
1411 prev_dir = NULL; /* Will be wiped out below ! */
1412
1413 for (pi=pf->pdir; pi!=NULL && PD_IDX(pi->dirnum)<pidx; pi=pi->next);
1414
1415 if (pi != NULL && PD_IDX(pi->dirnum) == pidx) {
1416 pd = pi->base;
1417
1418 for(i=index;i <= last_index;) {
1419 if (pd[PI_OFF(i)] != MALLOC_NOT_MINE) {
1420 pd[PI_OFF(i)] = MALLOC_NOT_MINE;
1421#ifdef MALLOC_EXTRA_SANITY
1422 if (!PD_OFF(pi->dirnum)) {
1423 wrterror("(ES): pages directory underflow\n");
1424 errno = EFAULT;
1425 return;
1426 }
1427#endif /* MALLOC_EXTRA_SANITY */
1428 pi->dirnum--;
1429 }
1430 i++;
1431 if (!PI_OFF(i)) {
1432 /* If no page in that dir, free directory page. */
1433 if (!PD_OFF(pi->dirnum)) {
1434 /* Remove from list. */
1435 pi->prev->next = pi->next;
1436 if (pi->next != NULL)
1437 pi->next->prev = pi->prev;
1438 pi = pi->next;
1439 munmap(pd, malloc_pagesize);
1440 } else
1441 pi = pi->next;
1442 if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(i))
1443 break;
1444 pd = pi->base;
1445 }
1446 }
1447 }
1448
1449 last_index = index - 1;
1450
1451 /* XXX: We could realloc/shrink the pagedir here I guess. */
1452 }
1453not_return:
1454 if (pt != NULL)
1455 ifree(pt);
1456}
1457
1458/*
1459 * Free a chunk, and possibly the page it's on, if the page becomes empty.
1460 */
1461
1462/* ARGSUSED */
1463static __inline__ void
1464free_bytes(void *ptr, int index, struct pginfo *info)
1465{
1466 int i;
1467 struct pginfo **mp;
1468 struct pginfo **pd;
1469 struct pdinfo *pi;
1470 u_long pidx;
1471 void *vp;
1472
1473 /* Find the chunk number on the page */
1474 i = ((u_long)ptr & malloc_pagemask) >> info->shift;
1475
1476 if ((u_long)ptr & ((1UL<<(info->shift))-1)) {
1477 wrtwarning("modified (chunk-) pointer\n");
1478 return;
1479 }
1480
1481 if (info->bits[i/MALLOC_BITS] & (1UL<<(i%MALLOC_BITS))) {
1482 wrtwarning("chunk is already free\n");
1483 return;
1484 }
1485
1486 if (malloc_junk && info->size != 0)
1487 memset(ptr, SOME_JUNK, info->size);
1488
1489 info->bits[i/MALLOC_BITS] |= 1UL<<(i%MALLOC_BITS);
1490 info->free++;
1491
1492 if (info->size != 0)
1493 mp = page_dir + info->shift;
1494 else
1495 mp = page_dir;
1496
1497 if (info->free == 1) {
1498
1499 /* Page became non-full */
1500
1501 /* Insert in address order */
1502 while (*mp != NULL && (*mp)->next != NULL &&
1503 (*mp)->next->page < info->page)
1504 mp = &(*mp)->next;
1505 info->next = *mp;
1506 *mp = info;
1507 return;
1508 }
1509
1510 if (info->free != info->total)
1511 return;
1512
1513 /* Find & remove this page in the queue */
1514 while (*mp != info) {
1515 mp = &((*mp)->next);
1516#ifdef MALLOC_EXTRA_SANITY
1517 if (!*mp) {
1518 wrterror("(ES): Not on queue\n");
1519 errno = EFAULT;
1520 return;
1521 }
1522#endif /* MALLOC_EXTRA_SANITY */
1523 }
1524 *mp = info->next;
1525
1526 /* Free the page & the info structure if need be */
1527 pidx = PI_IDX(ptr2index(info->page));
1528 pdir_lookup(ptr2index(info->page), &pi);
1529#ifdef MALLOC_EXTRA_SANITY
1530 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1531 wrterror("(ES): mapped pages not found in directory\n");
1532 errno = EFAULT;
1533 return;
1534 }
1535#endif /* MALLOC_EXTRA_SANITY */
1536 if (pi != last_dir) {
1537 prev_dir = last_dir;
1538 last_dir = pi;
1539 }
1540
1541 pd = pi->base;
1542 pd[PI_OFF(ptr2index(info->page))] = MALLOC_FIRST;
1543
1544 /* If the page was mprotected, unprotect it before releasing it */
1545 if (info->size == 0) {
1546 mprotect(info->page, malloc_pagesize, PROT_READ|PROT_WRITE);
1547 /* Do we have to care if mprotect succeeds here ? */
1548 }
1549
1550 vp = info->page; /* Order is important ! */
1551 if(vp != (void*)info)
1552 ifree(info);
1553 ifree(vp);
1554}
1555
1556static void
1557ifree(void *ptr)
1558{
1559 struct pginfo *info;
1560 struct pginfo **pd;
1561 struct pdinfo *pi;
1562 u_long pidx;
1563 u_long index;
1564
1565 /* This is legal */
1566 if (ptr == NULL)
1567 return;
1568
1569 if (!malloc_started) {
1570 wrtwarning("malloc() has never been called\n");
1571 return;
1572 }
1573
1574 /* If we're already sinking, don't make matters any worse. */
1575 if (suicide)
1576 return;
1577
1578 index = ptr2index(ptr);
1579
1580 if (index < malloc_pageshift) {
1581 wrtwarning("junk pointer, too low to make sense\n");
1582 return;
1583 }
1584
1585 if (index > last_index) {
1586 wrtwarning("junk pointer, too high to make sense\n");
1587 return;
1588 }
1589
1590 pidx = PI_IDX(index);
1591 pdir_lookup(index, &pi);
1592#ifdef MALLOC_EXTRA_SANITY
1593 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1594 wrterror("(ES): mapped pages not found in directory\n");
1595 errno = EFAULT;
1596 return;
1597 }
1598#endif /* MALLOC_EXTRA_SANITY */
1599 if (pi != last_dir) {
1600 prev_dir = last_dir;
1601 last_dir = pi;
1602 }
1603
1604 pd = pi->base;
1605 info = pd[PI_OFF(index)];
1606
1607 if (info < MALLOC_MAGIC)
1608 free_pages(ptr, index, info);
1609 else
1610 free_bytes(ptr, index, info);
1611 return;
1612}
1613
1614/*
1615 * Common function for handling recursion. Only
1616 * print the error message once, to avoid making the problem
1617 * potentially worse.
1618 */
1619static void
1620malloc_recurse(void)
1621{
1622 static int noprint;
1623
1624 if (noprint == 0) {
1625 noprint = 1;
1626 wrtwarning("recursive call\n");
1627 }
1628 malloc_active--;
1629 _MALLOC_UNLOCK();
1630 errno = EDEADLK;
1631}
1632
1633/*
1634 * These are the public exported interface routines.
1635 */
1636void *
1637malloc(size_t size)
1638{
1639 void *r;
1640
1641 _MALLOC_LOCK();
1642 malloc_func = " in malloc():";
1643 if (malloc_active++) {
1644 malloc_recurse();
1645 return (NULL);
1646 }
1647 r = imalloc(size);
1648 UTRACE(0, size, r);
1649 malloc_active--;
1650 _MALLOC_UNLOCK();
1651 if (malloc_xmalloc && r == NULL) {
1652 wrterror("out of memory\n");
1653 errno = ENOMEM;
1654 }
1655 return (r);
1656}
1657
1658void
1659free(void *ptr)
1660{
1661 _MALLOC_LOCK();
1662 malloc_func = " in free():";
1663 if (malloc_active++) {
1664 malloc_recurse();
1665 return;
1666 }
1667 ifree(ptr);
1668 UTRACE(ptr, 0, 0);
1669 malloc_active--;
1670 _MALLOC_UNLOCK();
1671 return;
1672}
1673
1674void *
1675realloc(void *ptr, size_t size)
1676{
1677 void *r;
1678
1679 _MALLOC_LOCK();
1680 malloc_func = " in realloc():";
1681 if (malloc_active++) {
1682 malloc_recurse();
1683 return (NULL);
1684 }
1685 if (ptr == NULL) {
1686 r = imalloc(size);
1687 } else {
1688 r = irealloc(ptr, size);
1689 }
1690 UTRACE(ptr, size, r);
1691 malloc_active--;
1692 _MALLOC_UNLOCK();
1693 if (malloc_xmalloc && r == NULL) {
1694 wrterror("out of memory\n");
1695 errno = ENOMEM;
1696 }
1697 return (r);
1698}
diff --git a/src/lib/libc/stdlib/merge.c b/src/lib/libc/stdlib/merge.c
new file mode 100644
index 0000000000..b193ae345c
--- /dev/null
+++ b/src/lib/libc/stdlib/merge.c
@@ -0,0 +1,336 @@
1/*-
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Peter McIlroy.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char *rcsid = "$OpenBSD: merge.c,v 1.7 2005/03/30 18:51:49 pat Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37/*
38 * Hybrid exponential search/linear search merge sort with hybrid
39 * natural/pairwise first pass. Requires about .3% more comparisons
40 * for random data than LSMS with pairwise first pass alone.
41 * It works for objects as small as two bytes.
42 */
43
44#define NATURAL
45#define THRESHOLD 16 /* Best choice for natural merge cut-off. */
46
47/* #define NATURAL to get hybrid natural merge.
48 * (The default is pairwise merging.)
49 */
50
51#include <sys/types.h>
52
53#include <errno.h>
54#include <stdlib.h>
55#include <string.h>
56
57static void setup(u_char *, u_char *, size_t, size_t, int (*)());
58static void insertionsort(u_char *, size_t, size_t, int (*)());
59
60#define ISIZE sizeof(int)
61#define PSIZE sizeof(u_char *)
62#define ICOPY_LIST(src, dst, last) \
63 do \
64 *(int*)dst = *(int*)src, src += ISIZE, dst += ISIZE; \
65 while(src < last)
66#define ICOPY_ELT(src, dst, i) \
67 do \
68 *(int*) dst = *(int*) src, src += ISIZE, dst += ISIZE; \
69 while (i -= ISIZE)
70
71#define CCOPY_LIST(src, dst, last) \
72 do \
73 *dst++ = *src++; \
74 while (src < last)
75#define CCOPY_ELT(src, dst, i) \
76 do \
77 *dst++ = *src++; \
78 while (i -= 1)
79
80/*
81 * Find the next possible pointer head. (Trickery for forcing an array
82 * to do double duty as a linked list when objects do not align with word
83 * boundaries.
84 */
85/* Assumption: PSIZE is a power of 2. */
86#define EVAL(p) (u_char **) \
87 ((u_char *)0 + \
88 (((u_char *)p + PSIZE - 1 - (u_char *) 0) & ~(PSIZE - 1)))
89
90/*
91 * Arguments are as for qsort.
92 */
93int
94mergesort(void *base, size_t nmemb, size_t size,
95 int (*cmp)(const void *, const void *))
96{
97 int i, sense;
98 int big, iflag;
99 u_char *f1, *f2, *t, *b, *tp2, *q, *l1, *l2;
100 u_char *list2, *list1, *p2, *p, *last, **p1;
101
102 if (size < PSIZE / 2) { /* Pointers must fit into 2 * size. */
103 errno = EINVAL;
104 return (-1);
105 }
106
107 /*
108 * XXX
109 * Stupid subtraction for the Cray.
110 */
111 iflag = 0;
112 if (!(size % ISIZE) && !(((char *)base - (char *)0) % ISIZE))
113 iflag = 1;
114
115 if ((list2 = malloc(nmemb * size + PSIZE)) == NULL)
116 return (-1);
117
118 list1 = base;
119 setup(list1, list2, nmemb, size, cmp);
120 last = list2 + nmemb * size;
121 i = big = 0;
122 while (*EVAL(list2) != last) {
123 l2 = list1;
124 p1 = EVAL(list1);
125 for (tp2 = p2 = list2; p2 != last; p1 = EVAL(l2)) {
126 p2 = *EVAL(p2);
127 f1 = l2;
128 f2 = l1 = list1 + (p2 - list2);
129 if (p2 != last)
130 p2 = *EVAL(p2);
131 l2 = list1 + (p2 - list2);
132 while (f1 < l1 && f2 < l2) {
133 if ((*cmp)(f1, f2) <= 0) {
134 q = f2;
135 b = f1, t = l1;
136 sense = -1;
137 } else {
138 q = f1;
139 b = f2, t = l2;
140 sense = 0;
141 }
142 if (!big) { /* here i = 0 */
143 while ((b += size) < t && cmp(q, b) >sense)
144 if (++i == 6) {
145 big = 1;
146 goto EXPONENTIAL;
147 }
148 } else {
149EXPONENTIAL: for (i = size; ; i <<= 1)
150 if ((p = (b + i)) >= t) {
151 if ((p = t - size) > b &&
152 (*cmp)(q, p) <= sense)
153 t = p;
154 else
155 b = p;
156 break;
157 } else if ((*cmp)(q, p) <= sense) {
158 t = p;
159 if (i == size)
160 big = 0;
161 goto FASTCASE;
162 } else
163 b = p;
164 while (t > b+size) {
165 i = (((t - b) / size) >> 1) * size;
166 if ((*cmp)(q, p = b + i) <= sense)
167 t = p;
168 else
169 b = p;
170 }
171 goto COPY;
172FASTCASE: while (i > size)
173 if ((*cmp)(q,
174 p = b + (i >>= 1)) <= sense)
175 t = p;
176 else
177 b = p;
178COPY: b = t;
179 }
180 i = size;
181 if (q == f1) {
182 if (iflag) {
183 ICOPY_LIST(f2, tp2, b);
184 ICOPY_ELT(f1, tp2, i);
185 } else {
186 CCOPY_LIST(f2, tp2, b);
187 CCOPY_ELT(f1, tp2, i);
188 }
189 } else {
190 if (iflag) {
191 ICOPY_LIST(f1, tp2, b);
192 ICOPY_ELT(f2, tp2, i);
193 } else {
194 CCOPY_LIST(f1, tp2, b);
195 CCOPY_ELT(f2, tp2, i);
196 }
197 }
198 }
199 if (f2 < l2) {
200 if (iflag)
201 ICOPY_LIST(f2, tp2, l2);
202 else
203 CCOPY_LIST(f2, tp2, l2);
204 } else if (f1 < l1) {
205 if (iflag)
206 ICOPY_LIST(f1, tp2, l1);
207 else
208 CCOPY_LIST(f1, tp2, l1);
209 }
210 *p1 = l2;
211 }
212 tp2 = list1; /* swap list1, list2 */
213 list1 = list2;
214 list2 = tp2;
215 last = list2 + nmemb*size;
216 }
217 if (base == list2) {
218 memmove(list2, list1, nmemb*size);
219 list2 = list1;
220 }
221 free(list2);
222 return (0);
223}
224
225#define swap(a, b) { \
226 s = b; \
227 i = size; \
228 do { \
229 tmp = *a; *a++ = *s; *s++ = tmp; \
230 } while (--i); \
231 a -= size; \
232 }
233#define reverse(bot, top) { \
234 s = top; \
235 do { \
236 i = size; \
237 do { \
238 tmp = *bot; *bot++ = *s; *s++ = tmp; \
239 } while (--i); \
240 s -= size2; \
241 } while(bot < s); \
242}
243
244/*
245 * Optional hybrid natural/pairwise first pass. Eats up list1 in runs of
246 * increasing order, list2 in a corresponding linked list. Checks for runs
247 * when THRESHOLD/2 pairs compare with same sense. (Only used when NATURAL
248 * is defined. Otherwise simple pairwise merging is used.)
249 */
250void
251setup(u_char *list1, u_char *list2, size_t n, size_t size,
252 int (*cmp)(const void *, const void *))
253{
254 int i, length, size2, tmp, sense;
255 u_char *f1, *f2, *s, *l2, *last, *p2;
256
257 size2 = size*2;
258 if (n <= 5) {
259 insertionsort(list1, n, size, cmp);
260 *EVAL(list2) = (u_char*) list2 + n*size;
261 return;
262 }
263 /*
264 * Avoid running pointers out of bounds; limit n to evens
265 * for simplicity.
266 */
267 i = 4 + (n & 1);
268 insertionsort(list1 + (n - i) * size, i, size, cmp);
269 last = list1 + size * (n - i);
270 *EVAL(list2 + (last - list1)) = list2 + n * size;
271
272#ifdef NATURAL
273 p2 = list2;
274 f1 = list1;
275 sense = (cmp(f1, f1 + size) > 0);
276 for (; f1 < last; sense = !sense) {
277 length = 2;
278 /* Find pairs with same sense. */
279 for (f2 = f1 + size2; f2 < last; f2 += size2) {
280 if ((cmp(f2, f2+ size) > 0) != sense)
281 break;
282 length += 2;
283 }
284 if (length < THRESHOLD) { /* Pairwise merge */
285 do {
286 p2 = *EVAL(p2) = f1 + size2 - list1 + list2;
287 if (sense > 0)
288 swap (f1, f1 + size);
289 } while ((f1 += size2) < f2);
290 } else { /* Natural merge */
291 l2 = f2;
292 for (f2 = f1 + size2; f2 < l2; f2 += size2) {
293 if ((cmp(f2-size, f2) > 0) != sense) {
294 p2 = *EVAL(p2) = f2 - list1 + list2;
295 if (sense > 0)
296 reverse(f1, f2-size);
297 f1 = f2;
298 }
299 }
300 if (sense > 0)
301 reverse (f1, f2-size);
302 f1 = f2;
303 if (f2 < last || cmp(f2 - size, f2) > 0)
304 p2 = *EVAL(p2) = f2 - list1 + list2;
305 else
306 p2 = *EVAL(p2) = list2 + n*size;
307 }
308 }
309#else /* pairwise merge only. */
310 for (f1 = list1, p2 = list2; f1 < last; f1 += size2) {
311 p2 = *EVAL(p2) = p2 + size2;
312 if (cmp (f1, f1 + size) > 0)
313 swap(f1, f1 + size);
314 }
315#endif /* NATURAL */
316}
317
318/*
319 * This is to avoid out-of-bounds addresses in sorting the
320 * last 4 elements.
321 */
322static void
323insertionsort(u_char *a, size_t n, size_t size,
324 int (*cmp)(const void *, const void *))
325{
326 u_char *ai, *s, *t, *u, tmp;
327 int i;
328
329 for (ai = a+size; --n >= 1; ai += size)
330 for (t = ai; t > a; t -= size) {
331 u = t - size;
332 if (cmp(u, t) <= 0)
333 break;
334 swap(u, t);
335 }
336}
diff --git a/src/lib/libc/stdlib/mrand48.c b/src/lib/libc/stdlib/mrand48.c
new file mode 100644
index 0000000000..cd34260b5c
--- /dev/null
+++ b/src/lib/libc/stdlib/mrand48.c
@@ -0,0 +1,27 @@
1/*
2 * Copyright (c) 1993 Martin Birgmeier
3 * All rights reserved.
4 *
5 * You may redistribute unmodified or modified versions of this source
6 * code provided that the above copyright notice and this and the
7 * following conditions are retained.
8 *
9 * This software is provided ``as is'', and comes with no warranties
10 * of any kind. I shall in no event be liable for anything that happens
11 * to anyone/anything when using this software.
12 */
13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: mrand48.c,v 1.2 1996/08/19 08:33:39 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
18#include "rand48.h"
19
20extern unsigned short __rand48_seed[3];
21
22long
23mrand48(void)
24{
25 __dorand48(__rand48_seed);
26 return ((long) __rand48_seed[2] << 16) + (long) __rand48_seed[1];
27}
diff --git a/src/lib/libc/stdlib/multibyte.c b/src/lib/libc/stdlib/multibyte.c
new file mode 100644
index 0000000000..ba878b8fdc
--- /dev/null
+++ b/src/lib/libc/stdlib/multibyte.c
@@ -0,0 +1,120 @@
1/*
2 * Copyright (c) 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: multibyte.c,v 1.4 2003/06/02 20:18:38 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35
36/*
37 * Stub multibyte character functions.
38 * This cheezy implementation is fixed to the native single-byte
39 * character set.
40 */
41
42int
43mblen(s, n)
44 const char *s;
45 size_t n;
46{
47 if (s == NULL || *s == '\0')
48 return 0;
49 if (n == 0)
50 return -1;
51 return 1;
52}
53
54/*ARGSUSED*/
55int
56mbtowc(pwc, s, n)
57 wchar_t *pwc;
58 const char *s;
59 size_t n;
60{
61 if (s == NULL)
62 return 0;
63 if (n == 0)
64 return -1;
65 if (pwc)
66 *pwc = (wchar_t) *s;
67 return (*s != '\0');
68}
69
70/*ARGSUSED*/
71int
72wctomb(char *s, wchar_t wchar)
73{
74 if (s == NULL)
75 return 0;
76
77 *s = (char) wchar;
78 return 1;
79}
80
81/*ARGSUSED*/
82size_t
83mbstowcs(pwcs, s, n)
84 wchar_t *pwcs;
85 const char *s;
86 size_t n;
87{
88 int count = 0;
89
90 if (n != 0) {
91 do {
92 if ((*pwcs++ = (wchar_t) *s++) == 0)
93 break;
94 count++;
95 } while (--n != 0);
96 }
97
98 return count;
99}
100
101/*ARGSUSED*/
102size_t
103wcstombs(s, pwcs, n)
104 char *s;
105 const wchar_t *pwcs;
106 size_t n;
107{
108 int count = 0;
109
110 if (n != 0) {
111 do {
112 if ((*s++ = (char) *pwcs++) == 0)
113 break;
114 count++;
115 } while (--n != 0);
116 }
117
118 return count;
119}
120
diff --git a/src/lib/libc/stdlib/nrand48.c b/src/lib/libc/stdlib/nrand48.c
new file mode 100644
index 0000000000..b1ec2cebb1
--- /dev/null
+++ b/src/lib/libc/stdlib/nrand48.c
@@ -0,0 +1,25 @@
1/*
2 * Copyright (c) 1993 Martin Birgmeier
3 * All rights reserved.
4 *
5 * You may redistribute unmodified or modified versions of this source
6 * code provided that the above copyright notice and this and the
7 * following conditions are retained.
8 *
9 * This software is provided ``as is'', and comes with no warranties
10 * of any kind. I shall in no event be liable for anything that happens
11 * to anyone/anything when using this software.
12 */
13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: nrand48.c,v 1.2 1996/08/19 08:33:40 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
18#include "rand48.h"
19
20long
21nrand48(unsigned short xseed[3])
22{
23 __dorand48(xseed);
24 return ((long) xseed[2] << 15) + ((long) xseed[1] >> 1);
25}
diff --git a/src/lib/libc/stdlib/putenv.c b/src/lib/libc/stdlib/putenv.c
new file mode 100644
index 0000000000..231982bf87
--- /dev/null
+++ b/src/lib/libc/stdlib/putenv.c
@@ -0,0 +1,53 @@
1/*-
2 * Copyright (c) 1988, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: putenv.c,v 1.4 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35#include <string.h>
36
37int
38putenv(const char *str)
39{
40 char *p, *equal;
41 int rval;
42
43 if ((p = strdup(str)) == NULL)
44 return (-1);
45 if ((equal = strchr(p, '=')) == NULL) {
46 (void)free(p);
47 return (-1);
48 }
49 *equal = '\0';
50 rval = setenv(p, equal + 1, 1);
51 (void)free(p);
52 return (rval);
53}
diff --git a/src/lib/libc/stdlib/qabs.3 b/src/lib/libc/stdlib/qabs.3
new file mode 100644
index 0000000000..093212edf5
--- /dev/null
+++ b/src/lib/libc/stdlib/qabs.3
@@ -0,0 +1,56 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information
6.\" Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: qabs.3,v 1.6 2003/06/02 20:18:38 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt QABS 3
36.Os
37.Sh NAME
38.Nm qabs
39.Nd return the absolute value of a quad integer
40.Sh SYNOPSIS
41.Fd #include <stdlib.h>
42.Ft quad_t
43.Fn qabs "quad_t j"
44.Sh DESCRIPTION
45The
46.Fn qabs
47function returns the absolute value of the quad integer
48.Fa j .
49.Sh SEE ALSO
50.Xr abs 3 ,
51.Xr cabs 3 ,
52.Xr floor 3 ,
53.Xr labs 3 ,
54.Xr math 3
55.Sh BUGS
56The absolute value of the most negative integer remains negative.
diff --git a/src/lib/libc/stdlib/qabs.c b/src/lib/libc/stdlib/qabs.c
new file mode 100644
index 0000000000..4c561b3351
--- /dev/null
+++ b/src/lib/libc/stdlib/qabs.c
@@ -0,0 +1,40 @@
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: qabs.c,v 1.4 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35
36quad_t
37qabs(quad_t j)
38{
39 return(j < 0 ? -j : j);
40}
diff --git a/src/lib/libc/stdlib/qdiv.3 b/src/lib/libc/stdlib/qdiv.3
new file mode 100644
index 0000000000..5f17ec17d4
--- /dev/null
+++ b/src/lib/libc/stdlib/qdiv.3
@@ -0,0 +1,60 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" Chris Torek and the American National Standards Committee X3,
6.\" on Information Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: qdiv.3,v 1.6 2004/01/23 23:08:46 jmc Exp $
33.\"
34.Dd June 29, 1991
35.Dt QDIV 3
36.Os
37.Sh NAME
38.Nm qdiv
39.Nd return quotient and remainder from division
40.Sh SYNOPSIS
41.Fd #include <stdlib.h>
42.Ft qdiv_t
43.Fn qdiv "quad_t num" "quad_t denom"
44.Sh DESCRIPTION
45The
46.Fn qdiv
47function computes the value
48.Fa num Ns / Ns Fa denom
49and returns the quotient and remainder in a structure named
50.Li qdiv_t
51that contains two
52.Li quad integer
53members named
54.Fa quot
55and
56.Fa rem .
57.Sh SEE ALSO
58.Xr div 3 ,
59.Xr ldiv 3 ,
60.Xr math 3
diff --git a/src/lib/libc/stdlib/qdiv.c b/src/lib/libc/stdlib/qdiv.c
new file mode 100644
index 0000000000..8147ee89a6
--- /dev/null
+++ b/src/lib/libc/stdlib/qdiv.c
@@ -0,0 +1,53 @@
1/*
2 * Copyright (c) 1990 Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Chris Torek.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char *rcsid = "$OpenBSD: qdiv.c,v 1.4 2005/03/30 18:51:49 pat Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37#include <stdlib.h> /* qdiv_t */
38
39qdiv_t
40qdiv(quad_t num, quad_t denom)
41{
42 qdiv_t r;
43
44 /* see div.c for comments */
45
46 r.quot = num / denom;
47 r.rem = num % denom;
48 if (num >= 0 && r.rem < 0) {
49 r.quot++;
50 r.rem -= denom;
51 }
52 return (r);
53}
diff --git a/src/lib/libc/stdlib/qsort.3 b/src/lib/libc/stdlib/qsort.3
new file mode 100644
index 0000000000..668ea90243
--- /dev/null
+++ b/src/lib/libc/stdlib/qsort.3
@@ -0,0 +1,233 @@
1.\" Copyright (c) 1990, 1991, 1993
2.\" The Regents of the University of California. All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information
6.\" Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: qsort.3,v 1.14 2003/10/01 08:11:58 jmc Exp $
33.\"
34.Dd June 4, 1993
35.Dt QSORT 3
36.Os
37.Sh NAME
38.Nm qsort ,
39.Nm heapsort ,
40.Nm mergesort
41.Nd sort functions
42.Sh SYNOPSIS
43.Fd #include <stdlib.h>
44.Ft void
45.Fn qsort "void *base" "size_t nmemb" "size_t size" "int (*compar)(const void *, const void *)"
46.Ft int
47.Fn heapsort "void *base" "size_t nmemb" "size_t size" "int (*compar)(const void *, const void *)"
48.Ft int
49.Fn mergesort "void *base" "size_t nmemb" "size_t size" "int (*compar)(const void *, const void *)"
50.Sh DESCRIPTION
51The
52.Fn qsort
53function is a modified partition-exchange sort, or quicksort.
54The
55.Fn heapsort
56function is a modified selection sort.
57The
58.Fn mergesort
59function is a modified merge sort with exponential search
60intended for sorting data with pre-existing order.
61.Pp
62The
63.Fn qsort
64and
65.Fn heapsort
66functions sort an array of
67.Fa nmemb
68objects, the initial member of which is pointed to by
69.Fa base .
70The size of each object is specified by
71.Fa size .
72.Fn mergesort
73behaves similarly, but
74.Em requires
75that
76.Fa size
77be greater than
78.Dq "sizeof(void *) / 2" .
79.Pp
80The contents of the array
81.Fa base
82are sorted in ascending order according to
83a comparison function pointed to by
84.Fa compar ,
85which requires two arguments pointing to the objects being
86compared.
87.Pp
88The comparison function must return an integer less than, equal to, or
89greater than zero if the first argument is considered to be respectively
90less than, equal to, or greater than the second.
91.Pp
92The functions
93.Fn qsort
94and
95.Fn heapsort
96are
97.Em not
98stable, that is, if two members compare as equal, their order in
99the sorted array is undefined.
100The function
101.Fn mergesort
102is stable.
103.Pp
104The
105.Fn qsort
106function is an implementation of C.A.R. Hoare's
107.Dq quicksort
108algorithm,
109a variant of partition-exchange sorting; in particular, see D.E. Knuth's
110Algorithm Q.
111.Fn qsort
112takes O N lg N average time.
113This implementation uses median selection to avoid its
114O N**2 worst-case behavior.
115.Pp
116The
117.Fn heapsort
118function is an implementation of J.W.J. William's
119.Dq heapsort
120algorithm,
121a variant of selection sorting; in particular, see D.E. Knuth's Algorithm H.
122.Fn heapsort
123takes O N lg N worst-case time.
124This implementation of
125.Fn heapsort
126is implemented without recursive function calls.
127.Pp
128The function
129.Fn mergesort
130requires additional memory of size
131.Fa nmemb *
132.Fa size
133bytes; it should be used only when space is not at a premium.
134.Fn mergesort
135is optimized for data with pre-existing order; its worst case
136time is O N lg N; its best case is O N.
137.Pp
138Normally,
139.Fn qsort
140is faster than
141.Fn mergesort ,
142which is faster than
143.Fn heapsort .
144Memory availability and pre-existing order in the data can make this untrue.
145.Sh RETURN VALUES
146The
147.Fn qsort
148function returns no value.
149.Pp
150Upon successful completion,
151.Fn heapsort
152and
153.Fn mergesort
154return 0.
155Otherwise, they return \-1 and the global variable
156.Va errno
157is set to indicate the error.
158.Sh ERRORS
159The
160.Fn heapsort
161and
162.Fn mergesort
163functions succeed unless:
164.Bl -tag -width Er
165.It Bq Er EINVAL
166The
167.Fa size
168argument is zero, or the
169.Fa size
170argument to
171.Fn mergesort
172is less than
173.Dq "sizeof(void *) / 2" .
174.It Bq Er ENOMEM
175.Fn heapsort
176or
177.Fn mergesort
178were unable to allocate memory.
179.El
180.Sh SEE ALSO
181.Xr sort 1 ,
182.Xr radixsort 3
183.Rs
184.%A Hoare, C.A.R.
185.%D 1962
186.%T "Quicksort"
187.%J "The Computer Journal"
188.%V 5:1
189.%P pp. 10-15
190.Re
191.Rs
192.%A Williams, J.W.J
193.%D 1964
194.%T "Heapsort"
195.%J "Communications of the ACM"
196.%V 7:1
197.%P pp. 347\-348
198.Re
199.Rs
200.%A Knuth, D.E.
201.%D 1968
202.%B "The Art of Computer Programming"
203.%V Vol. 3
204.%T "Sorting and Searching"
205.%P pp. 114\-123, 145\-149
206.Re
207.Rs
208.%A McIlroy, P.M.
209.%T "Optimistic Sorting and Information Theoretic Complexity"
210.%J "Fourth Annual ACM-SIAM Symposium on Discrete Algorithms"
211.%P pp. 467\-464
212.%D January 1993
213.Re
214.Rs
215.%A Bentley, J.L.
216.%A McIlroy, M.D.
217.%T "Engineering a Sort Function"
218.%J "Software \- Practice and Experience"
219.%V Vol. 23(11)
220.%P pp. 1249\-1265
221.%D November 1993
222.Re
223.Sh STANDARDS
224Previous versions of
225.Fn qsort
226did not permit the comparison routine itself to call
227.Fn qsort .
228This is no longer true.
229.Pp
230The
231.Fn qsort
232function conforms to
233.St -ansiC .
diff --git a/src/lib/libc/stdlib/qsort.c b/src/lib/libc/stdlib/qsort.c
new file mode 100644
index 0000000000..154c51a86c
--- /dev/null
+++ b/src/lib/libc/stdlib/qsort.c
@@ -0,0 +1,164 @@
1/*-
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: qsort.c,v 1.9 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35#include <stdlib.h>
36
37static __inline char *med3(char *, char *, char *, int (*)(const void *, const void *));
38static __inline void swapfunc(char *, char *, int, int);
39
40#define min(a, b) (a) < (b) ? a : b
41
42/*
43 * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
44 */
45#define swapcode(TYPE, parmi, parmj, n) { \
46 long i = (n) / sizeof (TYPE); \
47 TYPE *pi = (TYPE *) (parmi); \
48 TYPE *pj = (TYPE *) (parmj); \
49 do { \
50 TYPE t = *pi; \
51 *pi++ = *pj; \
52 *pj++ = t; \
53 } while (--i > 0); \
54}
55
56#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
57 es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
58
59static __inline void
60swapfunc(char *a, char *b, int n, int swaptype)
61{
62 if (swaptype <= 1)
63 swapcode(long, a, b, n)
64 else
65 swapcode(char, a, b, n)
66}
67
68#define swap(a, b) \
69 if (swaptype == 0) { \
70 long t = *(long *)(a); \
71 *(long *)(a) = *(long *)(b); \
72 *(long *)(b) = t; \
73 } else \
74 swapfunc(a, b, es, swaptype)
75
76#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
77
78static __inline char *
79med3(char *a, char *b, char *c, int (*cmp)(const void *, const void *))
80{
81 return cmp(a, b) < 0 ?
82 (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))
83 :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ));
84}
85
86void
87qsort(void *aa, size_t n, size_t es, int (*cmp)(const void *, const void *))
88{
89 char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
90 int d, r, swaptype, swap_cnt;
91 char *a = aa;
92
93loop: SWAPINIT(a, es);
94 swap_cnt = 0;
95 if (n < 7) {
96 for (pm = (char *)a + es; pm < (char *) a + n * es; pm += es)
97 for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
98 pl -= es)
99 swap(pl, pl - es);
100 return;
101 }
102 pm = (char *)a + (n / 2) * es;
103 if (n > 7) {
104 pl = (char *)a;
105 pn = (char *)a + (n - 1) * es;
106 if (n > 40) {
107 d = (n / 8) * es;
108 pl = med3(pl, pl + d, pl + 2 * d, cmp);
109 pm = med3(pm - d, pm, pm + d, cmp);
110 pn = med3(pn - 2 * d, pn - d, pn, cmp);
111 }
112 pm = med3(pl, pm, pn, cmp);
113 }
114 swap(a, pm);
115 pa = pb = (char *)a + es;
116
117 pc = pd = (char *)a + (n - 1) * es;
118 for (;;) {
119 while (pb <= pc && (r = cmp(pb, a)) <= 0) {
120 if (r == 0) {
121 swap_cnt = 1;
122 swap(pa, pb);
123 pa += es;
124 }
125 pb += es;
126 }
127 while (pb <= pc && (r = cmp(pc, a)) >= 0) {
128 if (r == 0) {
129 swap_cnt = 1;
130 swap(pc, pd);
131 pd -= es;
132 }
133 pc -= es;
134 }
135 if (pb > pc)
136 break;
137 swap(pb, pc);
138 swap_cnt = 1;
139 pb += es;
140 pc -= es;
141 }
142 if (swap_cnt == 0) { /* Switch to insertion sort */
143 for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
144 for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
145 pl -= es)
146 swap(pl, pl - es);
147 return;
148 }
149
150 pn = (char *)a + n * es;
151 r = min(pa - (char *)a, pb - pa);
152 vecswap(a, pb - r, r);
153 r = min(pd - pc, pn - pd - es);
154 vecswap(pb, pn - r, r);
155 if ((r = pb - pa) > es)
156 qsort(a, r / es, es, cmp);
157 if ((r = pd - pc) > es) {
158 /* Iterate rather than recurse to save stack space */
159 a = pn - r;
160 n = r / es;
161 goto loop;
162 }
163/* qsort(pn - r, r / es, es, cmp);*/
164}
diff --git a/src/lib/libc/stdlib/radixsort.3 b/src/lib/libc/stdlib/radixsort.3
new file mode 100644
index 0000000000..028837d4d1
--- /dev/null
+++ b/src/lib/libc/stdlib/radixsort.3
@@ -0,0 +1,155 @@
1.\" Copyright (c) 1990, 1991, 1993
2.\" The Regents of the University of California. All rights reserved.
3.\"
4.\" Redistribution and use in source and binary forms, with or without
5.\" modification, are permitted provided that the following conditions
6.\" are met:
7.\" 1. Redistributions of source code must retain the above copyright
8.\" notice, this list of conditions and the following disclaimer.
9.\" 2. Redistributions in binary form must reproduce the above copyright
10.\" notice, this list of conditions and the following disclaimer in the
11.\" documentation and/or other materials provided with the distribution.
12.\" 3. Neither the name of the University nor the names of its contributors
13.\" may be used to endorse or promote products derived from this software
14.\" without specific prior written permission.
15.\"
16.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
17.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26.\" SUCH DAMAGE.
27.\"
28.\" $OpenBSD: radixsort.3,v 1.9 2003/06/02 20:18:38 millert Exp $
29.\"
30.Dd January 27, 1994
31.Dt RADIXSORT 3
32.Os
33.Sh NAME
34.Nm radixsort ,
35.Nm sradixsort
36.Nd radix sort
37.Sh SYNOPSIS
38.Fd #include <limits.h>
39.Fd #include <stdlib.h>
40.Ft int
41.Fn radixsort "const u_char **base" "int nmemb" "const u_char *table" "u_int endbyte"
42.Ft int
43.Fn sradixsort "const u_char **base" "int nmemb" "const u_char *table" "u_int endbyte"
44.Sh DESCRIPTION
45The
46.Fn radixsort
47and
48.Fn sradixsort
49functions are implementations of radix sort.
50.Pp
51These functions sort an array of
52.Fa nmemb
53pointers to byte strings.
54The initial member is referenced by
55.Fa base .
56The byte strings may contain any values; the end of each string
57is denoted by the user-specified value
58.Fa endbyte .
59.Pp
60Applications may specify a sort order by providing the
61.Fa table
62argument.
63If non-null,
64.Fa table
65must reference an array of
66.Dv UCHAR_MAX
67+ 1 bytes which contains the sort weight of each possible byte value.
68The end-of-string byte must have a sort weight of 0 or 255
69(for sorting in reverse order).
70More than one byte may have the same sort weight.
71The
72.Fa table
73argument is useful for applications which wish to sort different characters
74equally, for example, providing a table with the same weights
75for A-Z as for a-z will result in a case-insensitive sort.
76If
77.Fa table
78is
79.Dv NULL ,
80the contents of the array are sorted in ascending order according to the
81.Tn ASCII
82order of the byte strings they reference and
83.Fa endbyte
84has a sorting weight of 0.
85.Pp
86The
87.Fn sradixsort
88function is stable; that is, if two elements compare as equal, their
89order in the sorted array is unchanged.
90The
91.Fn sradixsort
92function uses additional memory sufficient to hold
93.Fa nmemb
94pointers.
95.Pp
96The
97.Fn radixsort
98function is not stable, but uses no additional memory.
99.Pp
100These functions are variants of most-significant-byte radix sorting; in
101particular, see D.E. Knuth's Algorithm R and section 5.2.5, exercise 10.
102They take linear time relative to the number of bytes in the strings.
103.Sh RETURN VALUES
104Upon successful completion 0 is returned.
105Otherwise, \-1 is returned and the global variable
106.Va errno
107is set to indicate the error.
108.Sh ERRORS
109.Bl -tag -width Er
110.It Bq Er EINVAL
111The value of the
112.Fa endbyte
113element of
114.Fa table
115is not 0 or 255.
116.El
117.Pp
118Additionally, the
119.Fn sradixsort
120function may fail and set
121.Va errno
122for any of the errors specified for the library routine
123.Xr malloc 3 .
124.Sh SEE ALSO
125.Xr sort 1 ,
126.Xr qsort 3
127.Rs
128.%A Knuth, D.E.
129.%D 1968
130.%B "The Art of Computer Programming"
131.%T "Sorting and Searching"
132.%V Vol. 3
133.%P pp. 170-178
134.Re
135.Rs
136.%A Paige, R.
137.%D 1987
138.%T "Three Partition Refinement Algorithms"
139.%J "SIAM J. Comput."
140.%V Vol. 16
141.%N No. 6
142.Re
143.Rs
144.%A McIlroy, P.
145.%D 1993
146.%B "Engineering Radix Sort"
147.%T "Computing Systems"
148.%V Vol. 6:1
149.%P pp. 5-27
150.Re
151.Sh HISTORY
152The
153.Fn radixsort
154function first appeared in
155.Bx 4.4 .
diff --git a/src/lib/libc/stdlib/radixsort.c b/src/lib/libc/stdlib/radixsort.c
new file mode 100644
index 0000000000..96392ea73a
--- /dev/null
+++ b/src/lib/libc/stdlib/radixsort.c
@@ -0,0 +1,297 @@
1/*-
2 * Copyright (c) 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Peter McIlroy and by Dan Bernstein at New York University,
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char *rcsid = "$OpenBSD: radixsort.c,v 1.7 2005/03/30 18:51:49 pat Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37/*
38 * Radixsort routines.
39 *
40 * Program r_sort_a() is unstable but uses O(logN) extra memory for a stack.
41 * Use radixsort(a, n, trace, endchar) for this case.
42 *
43 * For stable sorting (using N extra pointers) use sradixsort(), which calls
44 * r_sort_b().
45 *
46 * For a description of this code, see D. McIlroy, P. McIlroy, K. Bostic,
47 * "Engineering Radix Sort".
48 */
49
50#include <sys/types.h>
51#include <stdlib.h>
52#include <errno.h>
53
54typedef struct {
55 const u_char **sa;
56 int sn, si;
57} stack;
58
59static __inline void simplesort
60(const u_char **, int, int, const u_char *, u_int);
61static void r_sort_a(const u_char **, int, int, const u_char *, u_int);
62static void r_sort_b(const u_char **,
63 const u_char **, int, int, const u_char *, u_int);
64
65#define THRESHOLD 20 /* Divert to simplesort(). */
66#define SIZE 512 /* Default stack size. */
67
68#define SETUP { \
69 if (tab == NULL) { \
70 tr = tr0; \
71 for (c = 0; c < endch; c++) \
72 tr0[c] = c + 1; \
73 tr0[c] = 0; \
74 for (c++; c < 256; c++) \
75 tr0[c] = c; \
76 endch = 0; \
77 } else { \
78 endch = tab[endch]; \
79 tr = tab; \
80 if (endch != 0 && endch != 255) { \
81 errno = EINVAL; \
82 return (-1); \
83 } \
84 } \
85}
86
87int
88radixsort(const u_char **a, int n, const u_char *tab, u_int endch)
89{
90 const u_char *tr;
91 int c;
92 u_char tr0[256];
93
94 SETUP;
95 r_sort_a(a, n, 0, tr, endch);
96 return (0);
97}
98
99int
100sradixsort(const u_char **a, int n, const u_char *tab, u_int endch)
101{
102 const u_char *tr, **ta;
103 int c;
104 u_char tr0[256];
105
106 SETUP;
107 if (n < THRESHOLD)
108 simplesort(a, n, 0, tr, endch);
109 else {
110 if ((ta = malloc(n * sizeof(a))) == NULL)
111 return (-1);
112 r_sort_b(a, ta, n, 0, tr, endch);
113 free(ta);
114 }
115 return (0);
116}
117
118#define empty(s) (s >= sp)
119#define pop(a, n, i) a = (--sp)->sa, n = sp->sn, i = sp->si
120#define push(a, n, i) sp->sa = a, sp->sn = n, (sp++)->si = i
121#define swap(a, b, t) t = a, a = b, b = t
122
123/* Unstable, in-place sort. */
124void
125r_sort_a(const u_char **a, int n, int i, const u_char *tr, u_int endch)
126{
127 static int count[256], nc, bmin;
128 int c;
129 const u_char **ak, *r;
130 stack s[SIZE], *sp, *sp0, *sp1, temp;
131 int *cp, bigc;
132 const u_char **an, *t, **aj, **top[256];
133
134 /* Set up stack. */
135 sp = s;
136 push(a, n, i);
137 while (!empty(s)) {
138 pop(a, n, i);
139 if (n < THRESHOLD) {
140 simplesort(a, n, i, tr, endch);
141 continue;
142 }
143 an = a + n;
144
145 /* Make character histogram. */
146 if (nc == 0) {
147 bmin = 255; /* First occupied bin, excluding eos. */
148 for (ak = a; ak < an;) {
149 c = tr[(*ak++)[i]];
150 if (++count[c] == 1 && c != endch) {
151 if (c < bmin)
152 bmin = c;
153 nc++;
154 }
155 }
156 if (sp + nc > s + SIZE) { /* Get more stack. */
157 r_sort_a(a, n, i, tr, endch);
158 continue;
159 }
160 }
161
162 /*
163 * Set top[]; push incompletely sorted bins onto stack.
164 * top[] = pointers to last out-of-place element in bins.
165 * count[] = counts of elements in bins.
166 * Before permuting: top[c-1] + count[c] = top[c];
167 * during deal: top[c] counts down to top[c-1].
168 */
169 sp0 = sp1 = sp; /* Stack position of biggest bin. */
170 bigc = 2; /* Size of biggest bin. */
171 if (endch == 0) /* Special case: set top[eos]. */
172 top[0] = ak = a + count[0];
173 else {
174 ak = a;
175 top[255] = an;
176 }
177 for (cp = count + bmin; nc > 0; cp++) {
178 while (*cp == 0) /* Find next non-empty pile. */
179 cp++;
180 if (*cp > 1) {
181 if (*cp > bigc) {
182 bigc = *cp;
183 sp1 = sp;
184 }
185 push(ak, *cp, i+1);
186 }
187 top[cp-count] = ak += *cp;
188 nc--;
189 }
190 swap(*sp0, *sp1, temp); /* Play it safe -- biggest bin last. */
191
192 /*
193 * Permute misplacements home. Already home: everything
194 * before aj, and in bin[c], items from top[c] on.
195 * Inner loop:
196 * r = next element to put in place;
197 * ak = top[r[i]] = location to put the next element.
198 * aj = bottom of 1st disordered bin.
199 * Outer loop:
200 * Once the 1st disordered bin is done, ie. aj >= ak,
201 * aj<-aj + count[c] connects the bins in a linked list;
202 * reset count[c].
203 */
204 for (aj = a; aj < an; *aj = r, aj += count[c], count[c] = 0)
205 for (r = *aj; aj < (ak = --top[c = tr[r[i]]]);)
206 swap(*ak, r, t);
207 }
208}
209
210/* Stable sort, requiring additional memory. */
211void
212r_sort_b(const u_char **a, const u_char **ta, int n, int i, const u_char *tr,
213 u_int endch)
214{
215 static int count[256], nc, bmin;
216 int c;
217 const u_char **ak, **ai;
218 stack s[512], *sp, *sp0, *sp1, temp;
219 const u_char **top[256];
220 int *cp, bigc;
221
222 sp = s;
223 push(a, n, i);
224 while (!empty(s)) {
225 pop(a, n, i);
226 if (n < THRESHOLD) {
227 simplesort(a, n, i, tr, endch);
228 continue;
229 }
230
231 if (nc == 0) {
232 bmin = 255;
233 for (ak = a + n; --ak >= a;) {
234 c = tr[(*ak)[i]];
235 if (++count[c] == 1 && c != endch) {
236 if (c < bmin)
237 bmin = c;
238 nc++;
239 }
240 }
241 if (sp + nc > s + SIZE) {
242 r_sort_b(a, ta, n, i, tr, endch);
243 continue;
244 }
245 }
246
247 sp0 = sp1 = sp;
248 bigc = 2;
249 if (endch == 0) {
250 top[0] = ak = a + count[0];
251 count[0] = 0;
252 } else {
253 ak = a;
254 top[255] = a + n;
255 count[255] = 0;
256 }
257 for (cp = count + bmin; nc > 0; cp++) {
258 while (*cp == 0)
259 cp++;
260 if ((c = *cp) > 1) {
261 if (c > bigc) {
262 bigc = c;
263 sp1 = sp;
264 }
265 push(ak, c, i+1);
266 }
267 top[cp-count] = ak += c;
268 *cp = 0; /* Reset count[]. */
269 nc--;
270 }
271 swap(*sp0, *sp1, temp);
272
273 for (ak = ta + n, ai = a+n; ak > ta;) /* Copy to temp. */
274 *--ak = *--ai;
275 for (ak = ta+n; --ak >= ta;) /* Deal to piles. */
276 *--top[tr[(*ak)[i]]] = *ak;
277 }
278}
279
280static __inline void
281simplesort(const u_char **a, int n, int b, const u_char *tr, u_int endch)
282 /* insertion sort */
283{
284 u_char ch;
285 const u_char **ak, **ai, *s, *t;
286
287 for (ak = a+1; --n >= 1; ak++)
288 for (ai = ak; ai > a; ai--) {
289 for (s = ai[0] + b, t = ai[-1] + b;
290 (ch = tr[*s]) != endch; s++, t++)
291 if (ch != tr[*t])
292 break;
293 if (ch >= tr[*t])
294 break;
295 swap(ai[0], ai[-1], s);
296 }
297}
diff --git a/src/lib/libc/stdlib/rand.3 b/src/lib/libc/stdlib/rand.3
new file mode 100644
index 0000000000..0d9c52a3b9
--- /dev/null
+++ b/src/lib/libc/stdlib/rand.3
@@ -0,0 +1,98 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information
6.\" Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: rand.3,v 1.9 2003/06/02 20:18:38 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt RAND 3
36.Os
37.Sh NAME
38.Nm rand ,
39.Nm srand
40.Nd bad random number generator
41.Sh SYNOPSIS
42.Fd #include <stdlib.h>
43.Ft void
44.Fn srand "unsigned int seed"
45.Ft int
46.Fn rand void
47.Ft int
48.Fn rand_r "unsigned int *seed"
49.Sh DESCRIPTION
50.Bf -symbolic
51These interfaces are obsoleted by
52.Xr random 3 .
53.Ef
54.Pp
55The
56.Fn rand
57function computes a sequence of pseudo-random integers in the range
58of 0 to
59.Dv RAND_MAX
60(as defined by the header file
61.Aq Pa stdlib.h ) .
62.Pp
63The
64.Fn srand
65function sets its argument as the seed for a new sequence of
66pseudo-random numbers to be returned by
67.Fn rand .
68These sequences are repeatable by calling
69.Fn srand
70with the same seed value.
71.Pp
72If no seed value is provided, the functions are automatically
73seeded with a value of 1.
74.Pp
75The
76.Fn rand_r
77is a thread-safe version of
78.Fn rand .
79Storage for the seed must be provided through the
80.Fa seed
81argument, and needs to have been initialized by the caller.
82.Sh SEE ALSO
83.Xr arc4random 3 ,
84.Xr rand48 3 ,
85.Xr random 3
86.Sh STANDARDS
87The
88.Fn rand
89and
90.Fn srand
91functions conform to
92.St -ansiC .
93.Pp
94The
95.Fn rand_r
96function conforms to ISO/IEC 9945-1 ANSI/IEEE
97.Pq Dq Tn POSIX
98Std 1003.1c Draft 10.
diff --git a/src/lib/libc/stdlib/rand.c b/src/lib/libc/stdlib/rand.c
new file mode 100644
index 0000000000..6b27ad46d3
--- /dev/null
+++ b/src/lib/libc/stdlib/rand.c
@@ -0,0 +1,56 @@
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: rand.c,v 1.8 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35#include <stdlib.h>
36
37static u_int next = 1;
38
39int
40rand_r(u_int *seed)
41{
42 *seed = *seed * 1103515245 + 12345;
43 return (*seed % ((u_int)RAND_MAX + 1));
44}
45
46int
47rand(void)
48{
49 return (rand_r(&next));
50}
51
52void
53srand(u_int seed)
54{
55 next = seed;
56}
diff --git a/src/lib/libc/stdlib/rand48.3 b/src/lib/libc/stdlib/rand48.3
new file mode 100644
index 0000000000..78cd0a7cd5
--- /dev/null
+++ b/src/lib/libc/stdlib/rand48.3
@@ -0,0 +1,165 @@
1.\" Copyright (c) 1993 Martin Birgmeier
2.\" All rights reserved.
3.\"
4.\" You may redistribute unmodified or modified versions of this source
5.\" code provided that the above copyright notice and this and the
6.\" following conditions are retained.
7.\"
8.\" This software is provided ``as is'', and comes with no warranties
9.\" of any kind. I shall in no event be liable for anything that happens
10.\" to anyone/anything when using this software.
11.\"
12.\" $OpenBSD: rand48.3,v 1.10 2003/06/01 19:27:27 jmc Exp $
13.\"
14.Dd October 8, 1993
15.Dt RAND48 3
16.Os
17.Sh NAME
18.Nm drand48 ,
19.Nm erand48 ,
20.Nm lrand48 ,
21.Nm nrand48 ,
22.Nm mrand48 ,
23.Nm jrand48 ,
24.Nm srand48 ,
25.Nm seed48 ,
26.Nm lcong48
27.Nd pseudo-random number generators and initialization routines
28.Sh SYNOPSIS
29.Fd #include <stdlib.h>
30.Ft double
31.Fn drand48 void
32.Ft double
33.Fn erand48 "unsigned short xseed[3]"
34.Ft long
35.Fn lrand48 void
36.Ft long
37.Fn nrand48 "unsigned short xseed[3]"
38.Ft long
39.Fn mrand48 void
40.Ft long
41.Fn jrand48 "unsigned short xseed[3]"
42.Ft void
43.Fn srand48 "long seed"
44.Ft "unsigned short *"
45.Fn seed48 "unsigned short xseed[3]"
46.Ft void
47.Fn lcong48 "unsigned short p[7]"
48.Sh DESCRIPTION
49The
50.Fn rand48
51family of functions generates pseudo-random numbers using a linear
52congruential algorithm working on integers 48 bits in size.
53The particular formula employed is
54r(n+1) = (a * r(n) + c) mod m
55where the default values are
56for the multiplicand a = 0xfdeece66d = 25214903917 and
57the addend c = 0xb = 11.
58The modulus is always fixed at m = 2 ** 48.
59r(n) is called the seed of the random number generator.
60.Pp
61For all the six generator routines described next, the first
62computational step is to perform a single iteration of the algorithm.
63.Pp
64.Fn drand48
65and
66.Fn erand48
67return values of type double.
68The full 48 bits of r(n+1) are
69loaded into the mantissa of the returned value, with the exponent set
70such that the values produced lie in the interval [0.0, 1.0].
71.Pp
72.Fn lrand48
73and
74.Fn nrand48
75return values of type long in the range
76[0, 2**31-1].
77The high-order (31) bits of
78r(n+1) are loaded into the lower bits of the returned value, with
79the topmost (sign) bit set to zero.
80.Pp
81.Fn mrand48
82and
83.Fn jrand48
84return values of type long in the range
85[-2**31, 2**31-1].
86The high-order (32) bits of r(n+1) are loaded into the returned value.
87.Pp
88.Fn drand48 ,
89.Fn lrand48 ,
90and
91.Fn mrand48
92use an internal buffer to store r(n).
93For these functions
94the initial value of r(0) = 0x1234abcd330e = 20017429951246.
95.Pp
96On the other hand,
97.Fn erand48 ,
98.Fn nrand48 ,
99and
100.Fn jrand48
101use a user-supplied buffer to store the seed r(n),
102which consists of an array of 3 shorts, where the zeroth member
103holds the least significant bits.
104.Pp
105All functions share the same multiplicand and addend.
106.Pp
107.Fn srand48
108is used to initialize the internal buffer r(n) of
109.Fn drand48 ,
110.Fn lrand48 ,
111and
112.Fn mrand48
113such that the 32 bits of the seed value are copied into the upper 32 bits
114of r(n), with the lower 16 bits of r(n) arbitrarily being set to 0x330e.
115Additionally, the constant multiplicand and addend of the algorithm are
116reset to the default values given above.
117.Pp
118.Fn seed48
119also initializes the internal buffer r(n) of
120.Fn drand48 ,
121.Fn lrand48 ,
122and
123.Fn mrand48 ,
124but here all 48 bits of the seed can be specified in an array of 3 shorts,
125where the zeroth member specifies the lowest bits.
126Again, the constant multiplicand and addend of the algorithm are
127reset to the default values given above.
128.Fn seed48
129returns a pointer to an array of 3 shorts which contains the old seed.
130This array is statically allocated, so its contents are lost after
131each new call to
132.Fn seed48 .
133.Pp
134Finally,
135.Fn lcong48
136allows full control over the multiplicand and addend used in
137.Fn drand48 ,
138.Fn erand48 ,
139.Fn lrand48 ,
140.Fn nrand48 ,
141.Fn mrand48 ,
142and
143.Fn jrand48 ,
144and the seed used in
145.Fn drand48 ,
146.Fn lrand48 ,
147and
148.Fn mrand48 .
149An array of 7 shorts is passed as parameter; the first three shorts are
150used to initialize the seed; the second three are used to initialize the
151multiplicand; and the last short is used to initialize the addend.
152It is thus not possible to use values greater than 0xffff as the addend.
153.Pp
154Note that all three methods of seeding the random number generator
155always also set the multiplicand and addend for any of the six
156generator calls.
157.Pp
158For a more powerful random number generator, see
159.Xr random 3 .
160.Sh SEE ALSO
161.Xr arc4random 3 ,
162.Xr rand 3 ,
163.Xr random 3
164.Sh AUTHORS
165Martin Birgmeier
diff --git a/src/lib/libc/stdlib/rand48.h b/src/lib/libc/stdlib/rand48.h
new file mode 100644
index 0000000000..afa49f65f3
--- /dev/null
+++ b/src/lib/libc/stdlib/rand48.h
@@ -0,0 +1,32 @@
1/*
2 * Copyright (c) 1993 Martin Birgmeier
3 * All rights reserved.
4 *
5 * You may redistribute unmodified or modified versions of this source
6 * code provided that the above copyright notice and this and the
7 * following conditions are retained.
8 *
9 * This software is provided ``as is'', and comes with no warranties
10 * of any kind. I shall in no event be liable for anything that happens
11 * to anyone/anything when using this software.
12 *
13 * $OpenBSD: rand48.h,v 1.3 2002/02/16 21:27:24 millert Exp $
14 */
15
16#ifndef _RAND48_H_
17#define _RAND48_H_
18
19#include <math.h>
20#include <stdlib.h>
21
22void __dorand48(unsigned short[3]);
23
24#define RAND48_SEED_0 (0x330e)
25#define RAND48_SEED_1 (0xabcd)
26#define RAND48_SEED_2 (0x1234)
27#define RAND48_MULT_0 (0xe66d)
28#define RAND48_MULT_1 (0xdeec)
29#define RAND48_MULT_2 (0x0005)
30#define RAND48_ADD (0x000b)
31
32#endif /* _RAND48_H_ */
diff --git a/src/lib/libc/stdlib/random.3 b/src/lib/libc/stdlib/random.3
new file mode 100644
index 0000000000..f43f06420d
--- /dev/null
+++ b/src/lib/libc/stdlib/random.3
@@ -0,0 +1,186 @@
1.\" Copyright (c) 1983, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" Redistribution and use in source and binary forms, with or without
5.\" modification, are permitted provided that the following conditions
6.\" are met:
7.\" 1. Redistributions of source code must retain the above copyright
8.\" notice, this list of conditions and the following disclaimer.
9.\" 2. Redistributions in binary form must reproduce the above copyright
10.\" notice, this list of conditions and the following disclaimer in the
11.\" documentation and/or other materials provided with the distribution.
12.\" 3. Neither the name of the University nor the names of its contributors
13.\" may be used to endorse or promote products derived from this software
14.\" without specific prior written permission.
15.\"
16.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
17.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26.\" SUCH DAMAGE.
27.\"
28.\" $OpenBSD: random.3,v 1.17 2003/06/02 20:18:38 millert Exp $
29.\"
30.Dd April 19, 1991
31.Dt RANDOM 3
32.Os
33.Sh NAME
34.Nm random ,
35.Nm srandom ,
36.Nm srandomdev ,
37.Nm initstate ,
38.Nm setstate
39.Nd better random number generator; routines for changing generators
40.Sh SYNOPSIS
41.Fd #include <stdlib.h>
42.Ft long
43.Fn random void
44.Ft void
45.Fn srandom "unsigned int seed"
46.Ft void
47.Fn srandomdev void
48.Ft char *
49.Fn initstate "unsigned int seed" "char *state" "size_t n"
50.Ft char *
51.Fn setstate "const char *state"
52.Sh DESCRIPTION
53The
54.Fn random
55function uses a non-linear additive feedback random number generator employing
56a default table of size 31 long integers to return successive pseudo-random
57numbers in the range from 0 to (2**31)\-1.
58The period of this random number generator is very large, approximately
5916*((2**31)\-1).
60.Pp
61The
62.Fn random
63and
64.Fn srandom
65functions have (almost) the same calling sequence and initialization
66properties as
67.Xr rand 3 Ns / Ns Xr srand 3 .
68The difference is that
69.Xr rand
70produces a much less random sequence \(em in fact, the low dozen bits
71generated by rand go through a cyclic pattern.
72All the bits generated by
73.Fn random
74are usable.
75For example,
76.Sq Li random()&01
77will produce a random binary
78value.
79.Pp
80Like
81.Xr rand 3 ,
82.Fn random
83will by default produce a sequence of numbers that can be duplicated
84by calling
85.Fn srandom
86with
87.Ql 1
88as the seed.
89.Pp
90The
91.Fn srandomdev
92routine initializes a state array using the
93.Xr arandom 4
94random number device which returns good random numbers,
95suitable for cryptographic use.
96Note that this particular seeding procedure can generate
97states which are impossible to reproduce by calling
98.Fn srandom
99with any value, since the succeeding terms in the
100state buffer are no longer derived from the LC algorithm applied to
101a fixed seed.
102.Pp
103The
104.Fn initstate
105routine allows a state array, passed in as an argument, to be initialized
106for future use.
107The size of the state array (in bytes) is used by
108.Fn initstate
109to decide how sophisticated a random number generator it should use \(em the
110more state, the better the random numbers will be.
111(Current "optimal" values for the amount of state information are
1128, 32, 64, 128, and 256 bytes; other amounts will be rounded down to
113the nearest known amount.
114Using less than 8 bytes will cause an error.)
115The seed for the initialization (which specifies a starting point for
116the random number sequence, and provides for restarting at the same
117point) is also an argument.
118The
119.Fn initstate
120function returns a pointer to the previous state information array.
121.Pp
122Once a state has been initialized, the
123.Fn setstate
124routine provides for rapid switching between states.
125The
126.Fn setstate
127function returns a pointer to the previous state array; its
128argument state array is used for further random number generation
129until the next call to
130.Fn initstate
131or
132.Fn setstate .
133.Pp
134Once a state array has been initialized, it may be restarted at a
135different point either by calling
136.Fn initstate
137(with the desired seed, the state array, and its size) or by calling
138both
139.Fn setstate
140(with the state array) and
141.Fn srandom
142(with the desired seed).
143The advantage of calling both
144.Fn setstate
145and
146.Fn srandom
147is that the size of the state array does not have to be remembered after
148it is initialized.
149.Pp
150With 256 bytes of state information, the period of the random number
151generator is greater than 2**69
152which should be sufficient for most purposes.
153.Sh DIAGNOSTICS
154If
155.Fn initstate
156is called with less than 8 bytes of state information, or if
157.Fn setstate
158detects that the state information has been garbled, error
159messages are printed on the standard error output.
160.Sh SEE ALSO
161.Xr arc4random 3 ,
162.Xr drand48 3 ,
163.Xr rand 3 ,
164.Xr random 4
165.Sh STANDARDS
166The
167.Fn random ,
168.Fn srandom ,
169.Fn initstate ,
170and
171.Fn setstate
172functions conform to
173.St -xpg4.2 .
174.Pp
175The
176.Fn srandomdev
177function is an extension.
178.Sh HISTORY
179These
180functions appeared in
181.Bx 4.2 .
182.Sh AUTHORS
183.An Earl T. Cohen
184.Sh BUGS
185About 2/3 the speed of
186.Xr rand 3 .
diff --git a/src/lib/libc/stdlib/random.c b/src/lib/libc/stdlib/random.c
new file mode 100644
index 0000000000..4ca8735e75
--- /dev/null
+++ b/src/lib/libc/stdlib/random.c
@@ -0,0 +1,425 @@
1/*
2 * Copyright (c) 1983 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: random.c,v 1.13 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/param.h>
35#include <sys/sysctl.h>
36#include <sys/time.h>
37#include <fcntl.h>
38#include <stdio.h>
39#include <stdlib.h>
40#include <unistd.h>
41
42/*
43 * random.c:
44 *
45 * An improved random number generation package. In addition to the standard
46 * rand()/srand() like interface, this package also has a special state info
47 * interface. The initstate() routine is called with a seed, an array of
48 * bytes, and a count of how many bytes are being passed in; this array is
49 * then initialized to contain information for random number generation with
50 * that much state information. Good sizes for the amount of state
51 * information are 32, 64, 128, and 256 bytes. The state can be switched by
52 * calling the setstate() routine with the same array as was initiallized
53 * with initstate(). By default, the package runs with 128 bytes of state
54 * information and generates far better random numbers than a linear
55 * congruential generator. If the amount of state information is less than
56 * 32 bytes, a simple linear congruential R.N.G. is used.
57 *
58 * Internally, the state information is treated as an array of int32_t; the
59 * zeroeth element of the array is the type of R.N.G. being used (small
60 * integer); the remainder of the array is the state information for the
61 * R.N.G. Thus, 32 bytes of state information will give 7 int32_ts worth of
62 * state information, which will allow a degree seven polynomial. (Note:
63 * the zeroeth word of state information also has some other information
64 * stored in it -- see setstate() for details).
65 *
66 * The random number generation technique is a linear feedback shift register
67 * approach, employing trinomials (since there are fewer terms to sum up that
68 * way). In this approach, the least significant bit of all the numbers in
69 * the state table will act as a linear feedback shift register, and will
70 * have period 2^deg - 1 (where deg is the degree of the polynomial being
71 * used, assuming that the polynomial is irreducible and primitive). The
72 * higher order bits will have longer periods, since their values are also
73 * influenced by pseudo-random carries out of the lower bits. The total
74 * period of the generator is approximately deg*(2**deg - 1); thus doubling
75 * the amount of state information has a vast influence on the period of the
76 * generator. Note: the deg*(2**deg - 1) is an approximation only good for
77 * large deg, when the period of the shift register is the dominant factor.
78 * With deg equal to seven, the period is actually much longer than the
79 * 7*(2**7 - 1) predicted by this formula.
80 */
81
82/*
83 * For each of the currently supported random number generators, we have a
84 * break value on the amount of state information (you need at least this
85 * many bytes of state info to support this random number generator), a degree
86 * for the polynomial (actually a trinomial) that the R.N.G. is based on, and
87 * the separation between the two lower order coefficients of the trinomial.
88 */
89#define TYPE_0 0 /* linear congruential */
90#define BREAK_0 8
91#define DEG_0 0
92#define SEP_0 0
93
94#define TYPE_1 1 /* x**7 + x**3 + 1 */
95#define BREAK_1 32
96#define DEG_1 7
97#define SEP_1 3
98
99#define TYPE_2 2 /* x**15 + x + 1 */
100#define BREAK_2 64
101#define DEG_2 15
102#define SEP_2 1
103
104#define TYPE_3 3 /* x**31 + x**3 + 1 */
105#define BREAK_3 128
106#define DEG_3 31
107#define SEP_3 3
108
109#define TYPE_4 4 /* x**63 + x + 1 */
110#define BREAK_4 256
111#define DEG_4 63
112#define SEP_4 1
113
114/*
115 * Array versions of the above information to make code run faster --
116 * relies on fact that TYPE_i == i.
117 */
118#define MAX_TYPES 5 /* max number of types above */
119
120static int degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 };
121static int seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
122
123/*
124 * Initially, everything is set up as if from:
125 *
126 * initstate(1, &randtbl, 128);
127 *
128 * Note that this initialization takes advantage of the fact that srandom()
129 * advances the front and rear pointers 10*rand_deg times, and hence the
130 * rear pointer which starts at 0 will also end up at zero; thus the zeroeth
131 * element of the state information, which contains info about the current
132 * position of the rear pointer is just
133 *
134 * MAX_TYPES * (rptr - state) + TYPE_3 == TYPE_3.
135 */
136
137static int32_t randtbl[DEG_3 + 1] = {
138 TYPE_3,
139 0x991539b1, 0x16a5bce3, 0x6774a4cd, 0x3e01511e, 0x4e508aaa, 0x61048c05,
140 0xf5500617, 0x846b7115, 0x6a19892c, 0x896a97af, 0xdb48f936, 0x14898454,
141 0x37ffd106, 0xb58bff9c, 0x59e17104, 0xcf918a49, 0x09378c83, 0x52c7a471,
142 0x8d293ea9, 0x1f4fc301, 0xc3db71be, 0x39b44e1c, 0xf8a44ef9, 0x4c8b80b1,
143 0x19edc328, 0x87bf4bdd, 0xc9b240e5, 0xe9ee4b1b, 0x4382aee7, 0x535b6b41,
144 0xf3bec5da,
145};
146
147/*
148 * fptr and rptr are two pointers into the state info, a front and a rear
149 * pointer. These two pointers are always rand_sep places aparts, as they
150 * cycle cyclically through the state information. (Yes, this does mean we
151 * could get away with just one pointer, but the code for random() is more
152 * efficient this way). The pointers are left positioned as they would be
153 * from the call
154 *
155 * initstate(1, randtbl, 128);
156 *
157 * (The position of the rear pointer, rptr, is really 0 (as explained above
158 * in the initialization of randtbl) because the state table pointer is set
159 * to point to randtbl[1] (as explained below).
160 */
161static int32_t *fptr = &randtbl[SEP_3 + 1];
162static int32_t *rptr = &randtbl[1];
163
164/*
165 * The following things are the pointer to the state information table, the
166 * type of the current generator, the degree of the current polynomial being
167 * used, and the separation between the two pointers. Note that for efficiency
168 * of random(), we remember the first location of the state information, not
169 * the zeroeth. Hence it is valid to access state[-1], which is used to
170 * store the type of the R.N.G. Also, we remember the last location, since
171 * this is more efficient than indexing every time to find the address of
172 * the last element to see if the front and rear pointers have wrapped.
173 */
174static int32_t *state = &randtbl[1];
175static int32_t *end_ptr = &randtbl[DEG_3 + 1];
176static int rand_type = TYPE_3;
177static int rand_deg = DEG_3;
178static int rand_sep = SEP_3;
179
180/*
181 * srandom:
182 *
183 * Initialize the random number generator based on the given seed. If the
184 * type is the trivial no-state-information type, just remember the seed.
185 * Otherwise, initializes state[] based on the given "seed" via a linear
186 * congruential generator. Then, the pointers are set to known locations
187 * that are exactly rand_sep places apart. Lastly, it cycles the state
188 * information a given number of times to get rid of any initial dependencies
189 * introduced by the L.C.R.N.G. Note that the initialization of randtbl[]
190 * for default usage relies on values produced by this routine.
191 */
192void
193srandom(unsigned int x)
194{
195 int i;
196 int32_t test;
197 div_t val;
198
199 if (rand_type == TYPE_0)
200 state[0] = x;
201 else {
202 state[0] = x;
203 for (i = 1; i < rand_deg; i++) {
204 /*
205 * Implement the following, without overflowing 31 bits:
206 *
207 * state[i] = (16807 * state[i - 1]) % 2147483647;
208 *
209 * 2^31-1 (prime) = 2147483647 = 127773*16807+2836
210 */
211 val = div(state[i-1], 127773);
212 test = 16807 * val.rem - 2836 * val.quot;
213 state[i] = test + (test < 0 ? 2147483647 : 0);
214 }
215 fptr = &state[rand_sep];
216 rptr = &state[0];
217 for (i = 0; i < 10 * rand_deg; i++)
218 (void)random();
219 }
220}
221
222/*
223 * srandomdev:
224 *
225 * Many programs choose the seed value in a totally predictable manner.
226 * This often causes problems. We seed the generator using the much more
227 * secure arandom(4) interface. Note that this particular seeding
228 * procedure can generate states which are impossible to reproduce by
229 * calling srandom() with any value, since the succeeding terms in the
230 * state buffer are no longer derived from the LC algorithm applied to
231 * a fixed seed.
232 */
233void
234srandomdev(void)
235{
236 int fd, i, mib[2], n;
237 size_t len;
238
239 if (rand_type == TYPE_0)
240 len = sizeof(state[0]);
241 else
242 len = rand_deg * sizeof(state[0]);
243
244 /*
245 * To get seed data, first try reading from /dev/arandom.
246 * If that fails, try the KERN_ARND sysctl() (one int at a time).
247 * As a last resort, call srandom().
248 */
249 if ((fd = open("/dev/arandom", O_RDONLY, 0)) != -1 &&
250 read(fd, (void *) state, len) == (ssize_t) len) {
251 close(fd);
252 } else {
253 if (fd != -1)
254 close(fd);
255 mib[0] = CTL_KERN;
256 mib[1] = KERN_ARND;
257 n = len / sizeof(int);
258 len = sizeof(int);
259 for (i = 0; i < n; i++) {
260 if (sysctl(mib, 2, (char *)((int *)state + i), &len,
261 NULL, 0) == -1)
262 break;
263 }
264 if (i != n) {
265 struct timeval tv;
266 u_int junk;
267
268 /* XXX - this could be better */
269 gettimeofday(&tv, NULL);
270 srandom(getpid() ^ tv.tv_sec ^ tv.tv_usec ^ junk);
271 return;
272 }
273 }
274
275 if (rand_type != TYPE_0) {
276 fptr = &state[rand_sep];
277 rptr = &state[0];
278 }
279}
280
281/*
282 * initstate:
283 *
284 * Initialize the state information in the given array of n bytes for future
285 * random number generation. Based on the number of bytes we are given, and
286 * the break values for the different R.N.G.'s, we choose the best (largest)
287 * one we can and set things up for it. srandom() is then called to
288 * initialize the state information.
289 *
290 * Note that on return from srandom(), we set state[-1] to be the type
291 * multiplexed with the current value of the rear pointer; this is so
292 * successive calls to initstate() won't lose this information and will be
293 * able to restart with setstate().
294 *
295 * Note: the first thing we do is save the current state, if any, just like
296 * setstate() so that it doesn't matter when initstate is called.
297 *
298 * Returns a pointer to the old state.
299 */
300char *
301initstate(u_int seed, char *arg_state, size_t n)
302{
303 char *ostate = (char *)(&state[-1]);
304
305 if (rand_type == TYPE_0)
306 state[-1] = rand_type;
307 else
308 state[-1] = MAX_TYPES * (rptr - state) + rand_type;
309 if (n < BREAK_0)
310 return(NULL);
311 if (n < BREAK_1) {
312 rand_type = TYPE_0;
313 rand_deg = DEG_0;
314 rand_sep = SEP_0;
315 } else if (n < BREAK_2) {
316 rand_type = TYPE_1;
317 rand_deg = DEG_1;
318 rand_sep = SEP_1;
319 } else if (n < BREAK_3) {
320 rand_type = TYPE_2;
321 rand_deg = DEG_2;
322 rand_sep = SEP_2;
323 } else if (n < BREAK_4) {
324 rand_type = TYPE_3;
325 rand_deg = DEG_3;
326 rand_sep = SEP_3;
327 } else {
328 rand_type = TYPE_4;
329 rand_deg = DEG_4;
330 rand_sep = SEP_4;
331 }
332 state = &(((int32_t *)arg_state)[1]); /* first location */
333 end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */
334 srandom(seed);
335 if (rand_type == TYPE_0)
336 state[-1] = rand_type;
337 else
338 state[-1] = MAX_TYPES*(rptr - state) + rand_type;
339 return(ostate);
340}
341
342/*
343 * setstate:
344 *
345 * Restore the state from the given state array.
346 *
347 * Note: it is important that we also remember the locations of the pointers
348 * in the current state information, and restore the locations of the pointers
349 * from the old state information. This is done by multiplexing the pointer
350 * location into the zeroeth word of the state information.
351 *
352 * Note that due to the order in which things are done, it is OK to call
353 * setstate() with the same state as the current state.
354 *
355 * Returns a pointer to the old state information.
356 */
357char *
358setstate(const char *arg_state)
359{
360 int32_t *new_state = (int32_t *)arg_state;
361 int32_t type = new_state[0] % MAX_TYPES;
362 int32_t rear = new_state[0] / MAX_TYPES;
363 char *ostate = (char *)(&state[-1]);
364
365 if (rand_type == TYPE_0)
366 state[-1] = rand_type;
367 else
368 state[-1] = MAX_TYPES * (rptr - state) + rand_type;
369 switch(type) {
370 case TYPE_0:
371 case TYPE_1:
372 case TYPE_2:
373 case TYPE_3:
374 case TYPE_4:
375 rand_type = type;
376 rand_deg = degrees[type];
377 rand_sep = seps[type];
378 break;
379 default:
380 return(NULL);
381 }
382 state = &new_state[1];
383 if (rand_type != TYPE_0) {
384 rptr = &state[rear];
385 fptr = &state[(rear + rand_sep) % rand_deg];
386 }
387 end_ptr = &state[rand_deg]; /* set end_ptr too */
388 return(ostate);
389}
390
391/*
392 * random:
393 *
394 * If we are using the trivial TYPE_0 R.N.G., just do the old linear
395 * congruential bit. Otherwise, we do our fancy trinomial stuff, which is
396 * the same in all the other cases due to all the global variables that have
397 * been set up. The basic operation is to add the number at the rear pointer
398 * into the one at the front pointer. Then both pointers are advanced to
399 * the next location cyclically in the table. The value returned is the sum
400 * generated, reduced to 31 bits by throwing away the "least random" low bit.
401 *
402 * Note: the code takes advantage of the fact that both the front and
403 * rear pointers can't wrap on the same call by not testing the rear
404 * pointer if the front one has wrapped.
405 *
406 * Returns a 31-bit random number.
407 */
408long
409random(void)
410{
411 int32_t i;
412
413 if (rand_type == TYPE_0)
414 i = state[0] = (state[0] * 1103515245 + 12345) & 0x7fffffff;
415 else {
416 *fptr += *rptr;
417 i = (*fptr >> 1) & 0x7fffffff; /* chucking least random bit */
418 if (++fptr >= end_ptr) {
419 fptr = state;
420 ++rptr;
421 } else if (++rptr >= end_ptr)
422 rptr = state;
423 }
424 return((long)i);
425}
diff --git a/src/lib/libc/stdlib/realpath.3 b/src/lib/libc/stdlib/realpath.3
new file mode 100644
index 0000000000..e1e0b10605
--- /dev/null
+++ b/src/lib/libc/stdlib/realpath.3
@@ -0,0 +1,117 @@
1.\" Copyright (c) 1994
2.\" The Regents of the University of California. All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" Jan-Simon Pendry.
6.\"
7.\" Redistribution and use in source and binary forms, with or without
8.\" modification, are permitted provided that the following conditions
9.\" are met:
10.\" 1. Redistributions of source code must retain the above copyright
11.\" notice, this list of conditions and the following disclaimer.
12.\" 2. Redistributions in binary form must reproduce the above copyright
13.\" notice, this list of conditions and the following disclaimer in the
14.\" documentation and/or other materials provided with the distribution.
15.\" 3. Neither the name of the University nor the names of its contributors
16.\" may be used to endorse or promote products derived from this software
17.\" without specific prior written permission.
18.\"
19.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29.\" SUCH DAMAGE.
30.\"
31.\" $OpenBSD: realpath.3,v 1.13 2005/04/03 18:59:15 otto Exp $
32.\"
33.Dd February 16, 1994
34.Dt REALPATH 3
35.Os
36.Sh NAME
37.Nm realpath
38.Nd returns the canonicalized absolute pathname
39.Sh SYNOPSIS
40.Fd #include <sys/param.h>
41.Fd #include <stdlib.h>
42.Ft "char *"
43.Fn realpath "const char *pathname" "char resolved[PATH_MAX]"
44.Sh DESCRIPTION
45The
46.Fn realpath
47function resolves all symbolic links, extra
48.Dq /
49characters and references to
50.Pa /./
51and
52.Pa /../
53in
54.Fa pathname ,
55and copies the resulting absolute pathname into the memory referenced by
56.Fa resolved .
57The
58.Fa resolved
59argument
60.Em must
61refer to a buffer capable of storing at least
62.Dv PATH_MAX
63characters.
64.Pp
65The
66.Fn realpath
67function will resolve both absolute and relative paths
68and return the absolute pathname corresponding to
69.Fa pathname .
70All but the last component of
71.Fa pathname
72must exist when
73.Fn realpath
74is called.
75.Sh RETURN VALUES
76The
77.Fn realpath
78function returns
79.Fa resolved
80on success.
81If an error occurs,
82.Fn realpath
83returns
84.Dv NULL
85and the contents of
86.Fa resolved
87are undefined.
88.Sh ERRORS
89The function
90.Fn realpath
91may fail and set the external variable
92.Va errno
93for any of the errors specified for the library functions
94.Xr lstat 2 ,
95.Xr readlink 2 ,
96and
97.Xr getcwd 3 .
98.Sh SEE ALSO
99.Xr readlink 1 ,
100.Xr getcwd 3
101.Sh HISTORY
102The
103.Fn realpath
104function call first appeared in
105.Bx 4.4 .
106.Sh CAVEATS
107This implementation of
108.Fn realpath
109differs slightly from the Solaris implementation.
110The
111.Bx 4.4
112version always returns absolute pathnames,
113whereas the Solaris implementation will,
114under certain circumstances, return a relative
115.Fa resolved
116when given a relative
117.Fa pathname .
diff --git a/src/lib/libc/stdlib/realpath.c b/src/lib/libc/stdlib/realpath.c
new file mode 100644
index 0000000000..62e06b00be
--- /dev/null
+++ b/src/lib/libc/stdlib/realpath.c
@@ -0,0 +1,198 @@
1/*
2 * Copyright (c) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru>
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The names of the authors may not be used to endorse or promote
13 * products derived from this software without specific prior written
14 * permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#if 0
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD: /usr/local/www/cvsroot/FreeBSD/src/lib/libc/stdlib/realpath.c,v 1.9.2.1 2003/05/22 17:11:44 fjoe Exp $");
32#endif
33
34#if defined(LIBC_SCCS) && !defined(lint)
35static char *rcsid = "$OpenBSD: realpath.c,v 1.12 2005/03/29 19:34:14 brad Exp $";
36#endif /* LIBC_SCCS and not lint */
37
38#include <sys/param.h>
39#include <sys/stat.h>
40
41#include <errno.h>
42#include <stdlib.h>
43#include <string.h>
44#include <unistd.h>
45
46/*
47 * char *realpath(const char *path, char resolved[PATH_MAX]);
48 *
49 * Find the real name of path, by removing all ".", ".." and symlink
50 * components. Returns (resolved) on success, or (NULL) on failure,
51 * in which case the path which caused trouble is left in (resolved).
52 */
53char *
54realpath(const char *path, char resolved[PATH_MAX])
55{
56 struct stat sb;
57 char *p, *q, *s;
58 size_t left_len, resolved_len;
59 unsigned symlinks;
60 int serrno, slen;
61 char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
62
63 serrno = errno;
64 symlinks = 0;
65 if (path[0] == '/') {
66 resolved[0] = '/';
67 resolved[1] = '\0';
68 if (path[1] == '\0')
69 return (resolved);
70 resolved_len = 1;
71 left_len = strlcpy(left, path + 1, sizeof(left));
72 } else {
73 if (getcwd(resolved, PATH_MAX) == NULL) {
74 strlcpy(resolved, ".", PATH_MAX);
75 return (NULL);
76 }
77 resolved_len = strlen(resolved);
78 left_len = strlcpy(left, path, sizeof(left));
79 }
80 if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
81 errno = ENAMETOOLONG;
82 return (NULL);
83 }
84
85 /*
86 * Iterate over path components in `left'.
87 */
88 while (left_len != 0) {
89 /*
90 * Extract the next path component and adjust `left'
91 * and its length.
92 */
93 p = strchr(left, '/');
94 s = p ? p : left + left_len;
95 if (s - left >= sizeof(next_token)) {
96 errno = ENAMETOOLONG;
97 return (NULL);
98 }
99 memcpy(next_token, left, s - left);
100 next_token[s - left] = '\0';
101 left_len -= s - left;
102 if (p != NULL)
103 memmove(left, s + 1, left_len + 1);
104 if (resolved[resolved_len - 1] != '/') {
105 if (resolved_len + 1 >= PATH_MAX) {
106 errno = ENAMETOOLONG;
107 return (NULL);
108 }
109 resolved[resolved_len++] = '/';
110 resolved[resolved_len] = '\0';
111 }
112 if (next_token[0] == '\0')
113 continue;
114 else if (strcmp(next_token, ".") == 0)
115 continue;
116 else if (strcmp(next_token, "..") == 0) {
117 /*
118 * Strip the last path component except when we have
119 * single "/"
120 */
121 if (resolved_len > 1) {
122 resolved[resolved_len - 1] = '\0';
123 q = strrchr(resolved, '/') + 1;
124 *q = '\0';
125 resolved_len = q - resolved;
126 }
127 continue;
128 }
129
130 /*
131 * Append the next path component and lstat() it. If
132 * lstat() fails we still can return successfully if
133 * there are no more path components left.
134 */
135 resolved_len = strlcat(resolved, next_token, PATH_MAX);
136 if (resolved_len >= PATH_MAX) {
137 errno = ENAMETOOLONG;
138 return (NULL);
139 }
140 if (lstat(resolved, &sb) != 0) {
141 if (errno == ENOENT && p == NULL) {
142 errno = serrno;
143 return (resolved);
144 }
145 return (NULL);
146 }
147 if (S_ISLNK(sb.st_mode)) {
148 if (symlinks++ > MAXSYMLINKS) {
149 errno = ELOOP;
150 return (NULL);
151 }
152 slen = readlink(resolved, symlink, sizeof(symlink) - 1);
153 if (slen < 0)
154 return (NULL);
155 symlink[slen] = '\0';
156 if (symlink[0] == '/') {
157 resolved[1] = 0;
158 resolved_len = 1;
159 } else if (resolved_len > 1) {
160 /* Strip the last path component. */
161 resolved[resolved_len - 1] = '\0';
162 q = strrchr(resolved, '/') + 1;
163 *q = '\0';
164 resolved_len = q - resolved;
165 }
166
167 /*
168 * If there are any path components left, then
169 * append them to symlink. The result is placed
170 * in `left'.
171 */
172 if (p != NULL) {
173 if (symlink[slen - 1] != '/') {
174 if (slen + 1 >= sizeof(symlink)) {
175 errno = ENAMETOOLONG;
176 return (NULL);
177 }
178 symlink[slen] = '/';
179 symlink[slen + 1] = 0;
180 }
181 left_len = strlcat(symlink, left, sizeof(left));
182 if (left_len >= sizeof(left)) {
183 errno = ENAMETOOLONG;
184 return (NULL);
185 }
186 }
187 left_len = strlcpy(left, symlink, sizeof(left));
188 }
189 }
190
191 /*
192 * Remove trailing slash except when the resolved pathname
193 * is a single "/".
194 */
195 if (resolved_len > 1 && resolved[resolved_len - 1] == '/')
196 resolved[resolved_len - 1] = '\0';
197 return (resolved);
198}
diff --git a/src/lib/libc/stdlib/remque.c b/src/lib/libc/stdlib/remque.c
new file mode 100644
index 0000000000..f4c5769a8c
--- /dev/null
+++ b/src/lib/libc/stdlib/remque.c
@@ -0,0 +1,48 @@
1/* $OpenBSD: remque.c,v 1.1 2003/05/08 23:26:30 millert Exp $ */
2
3/*
4 * Copyright (c) 1993 John Brezak
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#if defined(LIBC_SCCS) && !defined(lint)
32static char *rcsid = "$OpenBSD: remque.c,v 1.1 2003/05/08 23:26:30 millert Exp $";
33#endif /* LIBC_SCCS and not lint */
34
35#include <search.h>
36
37struct qelem {
38 struct qelem *q_forw;
39 struct qelem *q_back;
40};
41
42void
43remque(void *element)
44{
45 struct qelem *e = (struct qelem *) element;
46 e->q_forw->q_back = e->q_back;
47 e->q_back->q_forw = e->q_forw;
48}
diff --git a/src/lib/libc/stdlib/seed48.c b/src/lib/libc/stdlib/seed48.c
new file mode 100644
index 0000000000..c4dcd0ead8
--- /dev/null
+++ b/src/lib/libc/stdlib/seed48.c
@@ -0,0 +1,40 @@
1/*
2 * Copyright (c) 1993 Martin Birgmeier
3 * All rights reserved.
4 *
5 * You may redistribute unmodified or modified versions of this source
6 * code provided that the above copyright notice and this and the
7 * following conditions are retained.
8 *
9 * This software is provided ``as is'', and comes with no warranties
10 * of any kind. I shall in no event be liable for anything that happens
11 * to anyone/anything when using this software.
12 */
13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: seed48.c,v 1.2 1996/08/19 08:33:48 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
18#include "rand48.h"
19
20extern unsigned short __rand48_seed[3];
21extern unsigned short __rand48_mult[3];
22extern unsigned short __rand48_add;
23
24unsigned short *
25seed48(unsigned short xseed[3])
26{
27 static unsigned short sseed[3];
28
29 sseed[0] = __rand48_seed[0];
30 sseed[1] = __rand48_seed[1];
31 sseed[2] = __rand48_seed[2];
32 __rand48_seed[0] = xseed[0];
33 __rand48_seed[1] = xseed[1];
34 __rand48_seed[2] = xseed[2];
35 __rand48_mult[0] = RAND48_MULT_0;
36 __rand48_mult[1] = RAND48_MULT_1;
37 __rand48_mult[2] = RAND48_MULT_2;
38 __rand48_add = RAND48_ADD;
39 return sseed;
40}
diff --git a/src/lib/libc/stdlib/setenv.c b/src/lib/libc/stdlib/setenv.c
new file mode 100644
index 0000000000..ce0d3f9699
--- /dev/null
+++ b/src/lib/libc/stdlib/setenv.c
@@ -0,0 +1,106 @@
1/*
2 * Copyright (c) 1987 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: setenv.c,v 1.8 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35#include <string.h>
36
37char *__findenv(const char *name, int *offset);
38
39extern char **environ;
40
41/*
42 * setenv --
43 * Set the value of the environmental variable "name" to be
44 * "value". If rewrite is set, replace any current value.
45 */
46int
47setenv(const char *name, const char *value, int rewrite)
48{
49 static char **lastenv; /* last value of environ */
50 char *C;
51 int l_value, offset;
52
53 if (*value == '=') /* no `=' in value */
54 ++value;
55 l_value = strlen(value);
56 if ((C = __findenv(name, &offset))) { /* find if already exists */
57 if (!rewrite)
58 return (0);
59 if (strlen(C) >= l_value) { /* old larger; copy over */
60 while ((*C++ = *value++))
61 ;
62 return (0);
63 }
64 } else { /* create new slot */
65 size_t cnt;
66 char **P;
67
68 for (P = environ; *P != NULL; P++)
69 ;
70 cnt = P - environ;
71 P = (char **)realloc(lastenv, sizeof(char *) * (cnt + 2));
72 if (!P)
73 return (-1);
74 if (lastenv != environ)
75 memcpy(P, environ, cnt * sizeof(char *));
76 lastenv = environ = P;
77 offset = cnt;
78 environ[cnt + 1] = NULL;
79 }
80 for (C = (char *)name; *C && *C != '='; ++C)
81 ; /* no `=' in name */
82 if (!(environ[offset] = /* name + `=' + value */
83 malloc((size_t)((int)(C - name) + l_value + 2))))
84 return (-1);
85 for (C = environ[offset]; (*C = *name++) && *C != '='; ++C)
86 ;
87 for (*C++ = '='; (*C++ = *value++); )
88 ;
89 return (0);
90}
91
92/*
93 * unsetenv(name) --
94 * Delete environmental variable "name".
95 */
96void
97unsetenv(const char *name)
98{
99 char **P;
100 int offset;
101
102 while (__findenv(name, &offset)) /* if set multiple times */
103 for (P = &environ[offset];; ++P)
104 if (!(*P = *(P + 1)))
105 break;
106}
diff --git a/src/lib/libc/stdlib/srand48.c b/src/lib/libc/stdlib/srand48.c
new file mode 100644
index 0000000000..fcff8a172e
--- /dev/null
+++ b/src/lib/libc/stdlib/srand48.c
@@ -0,0 +1,34 @@
1/*
2 * Copyright (c) 1993 Martin Birgmeier
3 * All rights reserved.
4 *
5 * You may redistribute unmodified or modified versions of this source
6 * code provided that the above copyright notice and this and the
7 * following conditions are retained.
8 *
9 * This software is provided ``as is'', and comes with no warranties
10 * of any kind. I shall in no event be liable for anything that happens
11 * to anyone/anything when using this software.
12 */
13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: srand48.c,v 1.2 1996/08/19 08:33:49 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
18#include "rand48.h"
19
20extern unsigned short __rand48_seed[3];
21extern unsigned short __rand48_mult[3];
22extern unsigned short __rand48_add;
23
24void
25srand48(long seed)
26{
27 __rand48_seed[0] = RAND48_SEED_0;
28 __rand48_seed[1] = (unsigned short) seed;
29 __rand48_seed[2] = (unsigned short) (seed >> 16);
30 __rand48_mult[0] = RAND48_MULT_0;
31 __rand48_mult[1] = RAND48_MULT_1;
32 __rand48_mult[2] = RAND48_MULT_2;
33 __rand48_add = RAND48_ADD;
34}
diff --git a/src/lib/libc/stdlib/strtod.3 b/src/lib/libc/stdlib/strtod.3
new file mode 100644
index 0000000000..e25b0a5511
--- /dev/null
+++ b/src/lib/libc/stdlib/strtod.3
@@ -0,0 +1,113 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information
6.\" Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: strtod.3,v 1.8 2003/06/02 20:18:38 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt STRTOD 3
36.Os
37.Sh NAME
38.Nm strtod
39.Nd convert
40.Tn ASCII
41string to double
42.Sh SYNOPSIS
43.Fd #include <stdlib.h>
44.Ft double
45.Fn strtod "const char *nptr" "char **endptr"
46.Sh DESCRIPTION
47The
48.Fn strtod
49function converts the initial portion of the string pointed to by
50.Fa nptr
51to
52.Li double
53representation.
54.Pp
55The expected form of the string is an optional plus
56.Pq Ql +
57or minus sign
58.Pq Ql -
59followed by a sequence of digits optionally containing
60a decimal-point character, optionally followed by an exponent.
61An exponent consists of an
62.Sq E
63or
64.Sq e ,
65followed by an optional plus or minus sign, followed by a sequence of digits.
66.Pp
67Leading whitespace characters in the string (as defined by the
68.Xr isspace 3
69function) are skipped.
70.Sh RETURN VALUES
71The
72.Fn strtod
73function returns the converted value, if any.
74.Pp
75If
76.Fa endptr
77is not
78.Dv NULL ,
79a pointer to the character after the last character used
80in the conversion is stored in the location referenced by
81.Fa endptr .
82.Pp
83If no conversion is performed, zero is returned and the value of
84.Fa nptr
85is stored in the location referenced by
86.Fa endptr .
87.Pp
88If the correct value would cause overflow, plus or minus
89.Dv HUGE_VAL
90is returned (according to the sign of the value), and
91.Er ERANGE
92is stored in
93.Va errno .
94If the correct value would cause underflow, zero is returned and
95.Er ERANGE
96is stored in
97.Va errno .
98.Sh ERRORS
99.Bl -tag -width Er
100.It Bq Er ERANGE
101Overflow or underflow occurred.
102.El
103.Sh SEE ALSO
104.Xr atof 3 ,
105.Xr atoi 3 ,
106.Xr atol 3 ,
107.Xr strtol 3 ,
108.Xr strtoul 3
109.Sh STANDARDS
110The
111.Fn strtod
112function conforms to
113.St -ansiC .
diff --git a/src/lib/libc/stdlib/strtod.c b/src/lib/libc/stdlib/strtod.c
new file mode 100644
index 0000000000..94eca88659
--- /dev/null
+++ b/src/lib/libc/stdlib/strtod.c
@@ -0,0 +1,2411 @@
1/****************************************************************
2 *
3 * The author of this software is David M. Gay.
4 *
5 * Copyright (c) 1991 by AT&T.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose without fee is hereby granted, provided that this entire notice
9 * is included in all copies of any software which is or includes a copy
10 * or modification of this software and in all copies of the supporting
11 * documentation for such software.
12 *
13 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
14 * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY
15 * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
16 * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
17 *
18 ***************************************************************/
19
20/* Please send bug reports to
21 David M. Gay
22 AT&T Bell Laboratories, Room 2C-463
23 600 Mountain Avenue
24 Murray Hill, NJ 07974-2070
25 U.S.A.
26 dmg@research.att.com or research!dmg
27 */
28
29/* strtod for IEEE-, VAX-, and IBM-arithmetic machines.
30 *
31 * This strtod returns a nearest machine number to the input decimal
32 * string (or sets errno to ERANGE). With IEEE arithmetic, ties are
33 * broken by the IEEE round-even rule. Otherwise ties are broken by
34 * biased rounding (add half and chop).
35 *
36 * Inspired loosely by William D. Clinger's paper "How to Read Floating
37 * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101].
38 *
39 * Modifications:
40 *
41 * 1. We only require IEEE, IBM, or VAX double-precision
42 * arithmetic (not IEEE double-extended).
43 * 2. We get by with floating-point arithmetic in a case that
44 * Clinger missed -- when we're computing d * 10^n
45 * for a small integer d and the integer n is not too
46 * much larger than 22 (the maximum integer k for which
47 * we can represent 10^k exactly), we may be able to
48 * compute (d*10^k) * 10^(e-k) with just one roundoff.
49 * 3. Rather than a bit-at-a-time adjustment of the binary
50 * result in the hard case, we use floating-point
51 * arithmetic to determine the adjustment to within
52 * one bit; only in really hard cases do we need to
53 * compute a second residual.
54 * 4. Because of 3., we don't need a large table of powers of 10
55 * for ten-to-e (just some small tables, e.g. of 10^k
56 * for 0 <= k <= 22).
57 */
58
59/*
60 * #define IEEE_LITTLE_ENDIAN for IEEE-arithmetic machines where the least
61 * significant byte has the lowest address.
62 * #define IEEE_BIG_ENDIAN for IEEE-arithmetic machines where the most
63 * significant byte has the lowest address.
64 * #define Long int on machines with 32-bit ints and 64-bit longs.
65 * #define Sudden_Underflow for IEEE-format machines without gradual
66 * underflow (i.e., that flush to zero on underflow).
67 * #define IBM for IBM mainframe-style floating-point arithmetic.
68 * #define VAX for VAX-style floating-point arithmetic.
69 * #define Unsigned_Shifts if >> does treats its left operand as unsigned.
70 * #define No_leftright to omit left-right logic in fast floating-point
71 * computation of dtoa.
72 * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3.
73 * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines
74 * that use extended-precision instructions to compute rounded
75 * products and quotients) with IBM.
76 * #define ROUND_BIASED for IEEE-format with biased rounding.
77 * #define Inaccurate_Divide for IEEE-format with correctly rounded
78 * products but inaccurate quotients, e.g., for Intel i860.
79 * #define Just_16 to store 16 bits per 32-bit Long when doing high-precision
80 * integer arithmetic. Whether this speeds things up or slows things
81 * down depends on the machine and the number being converted.
82 * #define Bad_float_h if your system lacks a float.h or if it does not
83 * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP,
84 * FLT_RADIX, FLT_ROUNDS, and DBL_MAX.
85 * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n)
86 * if memory is available and otherwise does something you deem
87 * appropriate. If MALLOC is undefined, malloc will be invoked
88 * directly -- and assumed always to succeed.
89 */
90
91#if defined(LIBC_SCCS) && !defined(lint)
92static char *rcsid = "$OpenBSD: strtod.c,v 1.20 2005/03/30 18:51:49 pat Exp $";
93#endif /* LIBC_SCCS and not lint */
94
95#if defined(__m68k__) || defined(__sparc__) || defined(__i386__) || \
96 defined(__mips__) || defined(__ns32k__) || defined(__alpha__) || \
97 defined(__powerpc__) || defined(__m88k__) || defined(__hppa__) || \
98 defined(__x86_64__) || (defined(__arm__) && defined(__VFP_FP__))
99#include <sys/types.h>
100#if BYTE_ORDER == BIG_ENDIAN
101#define IEEE_BIG_ENDIAN
102#else
103#define IEEE_LITTLE_ENDIAN
104#endif
105#endif
106
107#if defined(__arm__) && !defined(__VFP_FP__)
108/*
109 * Although the CPU is little endian the FP has different
110 * byte and word endianness. The byte order is still little endian
111 * but the word order is big endian.
112 */
113#define IEEE_BIG_ENDIAN
114#endif
115
116#ifdef __vax__
117#define VAX
118#endif
119
120#define Long int32_t
121#define ULong u_int32_t
122
123#ifdef DEBUG
124#include "stdio.h"
125#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);}
126#endif
127
128#ifdef __cplusplus
129#include "malloc.h"
130#include "memory.h"
131#else
132#include "stdlib.h"
133#include "string.h"
134#include "locale.h"
135#endif
136
137#ifdef MALLOC
138extern void *MALLOC(size_t);
139#else
140#define MALLOC malloc
141#endif
142
143#include "ctype.h"
144#include "errno.h"
145
146#ifdef Bad_float_h
147#ifdef IEEE_BIG_ENDIAN
148#define IEEE_ARITHMETIC
149#endif
150#ifdef IEEE_LITTLE_ENDIAN
151#define IEEE_ARITHMETIC
152#endif
153
154#ifdef IEEE_ARITHMETIC
155#define DBL_DIG 15
156#define DBL_MAX_10_EXP 308
157#define DBL_MAX_EXP 1024
158#define FLT_RADIX 2
159#define FLT_ROUNDS 1
160#define DBL_MAX 1.7976931348623157e+308
161#endif
162
163#ifdef IBM
164#define DBL_DIG 16
165#define DBL_MAX_10_EXP 75
166#define DBL_MAX_EXP 63
167#define FLT_RADIX 16
168#define FLT_ROUNDS 0
169#define DBL_MAX 7.2370055773322621e+75
170#endif
171
172#ifdef VAX
173#define DBL_DIG 16
174#define DBL_MAX_10_EXP 38
175#define DBL_MAX_EXP 127
176#define FLT_RADIX 2
177#define FLT_ROUNDS 1
178#define DBL_MAX 1.7014118346046923e+38
179#endif
180
181#ifndef LONG_MAX
182#define LONG_MAX 2147483647
183#endif
184#else
185#include "float.h"
186#endif
187#ifndef __MATH_H__
188#include "math.h"
189#endif
190
191#ifdef __cplusplus
192extern "C" {
193#endif
194
195#ifndef CONST
196#define CONST const
197#endif
198
199#ifdef Unsigned_Shifts
200#define Sign_Extend(a,b) if (b < 0) a |= 0xffff0000;
201#else
202#define Sign_Extend(a,b) /*no-op*/
203#endif
204
205#if defined(IEEE_LITTLE_ENDIAN) + defined(IEEE_BIG_ENDIAN) + defined(VAX) + \
206 defined(IBM) != 1
207Exactly one of IEEE_LITTLE_ENDIAN IEEE_BIG_ENDIAN, VAX, or
208IBM should be defined.
209#endif
210
211typedef union {
212 double d;
213 ULong ul[2];
214} _double;
215#define value(x) ((x).d)
216#ifdef IEEE_LITTLE_ENDIAN
217#define word0(x) ((x).ul[1])
218#define word1(x) ((x).ul[0])
219#else
220#define word0(x) ((x).ul[0])
221#define word1(x) ((x).ul[1])
222#endif
223
224/* The following definition of Storeinc is appropriate for MIPS processors.
225 * An alternative that might be better on some machines is
226 * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff)
227 */
228#if defined(IEEE_LITTLE_ENDIAN) + defined(VAX) + defined(__arm__)
229#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \
230((unsigned short *)a)[0] = (unsigned short)c, a++)
231#else
232#define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \
233((unsigned short *)a)[1] = (unsigned short)c, a++)
234#endif
235
236/* #define P DBL_MANT_DIG */
237/* Ten_pmax = floor(P*log(2)/log(5)) */
238/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */
239/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */
240/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */
241
242#if defined(IEEE_LITTLE_ENDIAN) + defined(IEEE_BIG_ENDIAN)
243#define Exp_shift 20
244#define Exp_shift1 20
245#define Exp_msk1 0x100000
246#define Exp_msk11 0x100000
247#define Exp_mask 0x7ff00000
248#define P 53
249#define Bias 1023
250#define IEEE_Arith
251#define Emin (-1022)
252#define Exp_1 0x3ff00000
253#define Exp_11 0x3ff00000
254#define Ebits 11
255#define Frac_mask 0xfffff
256#define Frac_mask1 0xfffff
257#define Ten_pmax 22
258#define Bletch 0x10
259#define Bndry_mask 0xfffff
260#define Bndry_mask1 0xfffff
261#define LSB 1
262#define Sign_bit 0x80000000
263#define Log2P 1
264#define Tiny0 0
265#define Tiny1 1
266#define Quick_max 14
267#define Int_max 14
268#define Infinite(x) (word0(x) == 0x7ff00000) /* sufficient test for here */
269#else
270#undef Sudden_Underflow
271#define Sudden_Underflow
272#ifdef IBM
273#define Exp_shift 24
274#define Exp_shift1 24
275#define Exp_msk1 0x1000000
276#define Exp_msk11 0x1000000
277#define Exp_mask 0x7f000000
278#define P 14
279#define Bias 65
280#define Exp_1 0x41000000
281#define Exp_11 0x41000000
282#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */
283#define Frac_mask 0xffffff
284#define Frac_mask1 0xffffff
285#define Bletch 4
286#define Ten_pmax 22
287#define Bndry_mask 0xefffff
288#define Bndry_mask1 0xffffff
289#define LSB 1
290#define Sign_bit 0x80000000
291#define Log2P 4
292#define Tiny0 0x100000
293#define Tiny1 0
294#define Quick_max 14
295#define Int_max 15
296#else /* VAX */
297#define Exp_shift 23
298#define Exp_shift1 7
299#define Exp_msk1 0x80
300#define Exp_msk11 0x800000
301#define Exp_mask 0x7f80
302#define P 56
303#define Bias 129
304#define Exp_1 0x40800000
305#define Exp_11 0x4080
306#define Ebits 8
307#define Frac_mask 0x7fffff
308#define Frac_mask1 0xffff007f
309#define Ten_pmax 24
310#define Bletch 2
311#define Bndry_mask 0xffff007f
312#define Bndry_mask1 0xffff007f
313#define LSB 0x10000
314#define Sign_bit 0x8000
315#define Log2P 1
316#define Tiny0 0x80
317#define Tiny1 0
318#define Quick_max 15
319#define Int_max 15
320#endif
321#endif
322
323#ifndef IEEE_Arith
324#define ROUND_BIASED
325#endif
326
327#ifdef RND_PRODQUOT
328#define rounded_product(a,b) a = rnd_prod(a, b)
329#define rounded_quotient(a,b) a = rnd_quot(a, b)
330extern double rnd_prod(double, double), rnd_quot(double, double);
331#else
332#define rounded_product(a,b) a *= b
333#define rounded_quotient(a,b) a /= b
334#endif
335
336#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1))
337#define Big1 0xffffffff
338
339#ifndef Just_16
340/* When Pack_32 is not defined, we store 16 bits per 32-bit Long.
341 * This makes some inner loops simpler and sometimes saves work
342 * during multiplications, but it often seems to make things slightly
343 * slower. Hence the default is now to store 32 bits per Long.
344 */
345#ifndef Pack_32
346#define Pack_32
347#endif
348#endif
349
350#define Kmax 15
351
352#ifdef __cplusplus
353extern "C" double strtod(const char *s00, char **se);
354extern "C" char *__dtoa(double d, int mode, int ndigits,
355 int *decpt, int *sign, char **rve);
356#endif
357
358 struct
359Bigint {
360 struct Bigint *next;
361 int k, maxwds, sign, wds;
362 ULong x[1];
363 };
364
365 typedef struct Bigint Bigint;
366
367 static Bigint *freelist[Kmax+1];
368
369 static Bigint *
370Balloc(int k)
371{
372 int x;
373 Bigint *rv;
374
375 if ((rv = freelist[k])) {
376 freelist[k] = rv->next;
377 }
378 else {
379 x = 1 << k;
380 rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(Long));
381 rv->k = k;
382 rv->maxwds = x;
383 }
384 rv->sign = rv->wds = 0;
385 return rv;
386 }
387
388 static void
389Bfree(Bigint *v)
390{
391 if (v) {
392 v->next = freelist[v->k];
393 freelist[v->k] = v;
394 }
395 }
396
397#define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \
398y->wds*sizeof(Long) + 2*sizeof(int))
399
400 static Bigint *
401multadd(Bigint *b, int m, int a) /* multiply by m and add a */
402{
403 int i, wds;
404 ULong *x, y;
405#ifdef Pack_32
406 ULong xi, z;
407#endif
408 Bigint *b1;
409
410 wds = b->wds;
411 x = b->x;
412 i = 0;
413 do {
414#ifdef Pack_32
415 xi = *x;
416 y = (xi & 0xffff) * m + a;
417 z = (xi >> 16) * m + (y >> 16);
418 a = (int)(z >> 16);
419 *x++ = (z << 16) + (y & 0xffff);
420#else
421 y = *x * m + a;
422 a = (int)(y >> 16);
423 *x++ = y & 0xffff;
424#endif
425 }
426 while(++i < wds);
427 if (a) {
428 if (wds >= b->maxwds) {
429 b1 = Balloc(b->k+1);
430 Bcopy(b1, b);
431 Bfree(b);
432 b = b1;
433 }
434 b->x[wds++] = a;
435 b->wds = wds;
436 }
437 return b;
438 }
439
440 static Bigint *
441s2b(CONST char *s, int nd0, int nd, ULong y9)
442{
443 Bigint *b;
444 int i, k;
445 Long x, y;
446
447 x = (nd + 8) / 9;
448 for(k = 0, y = 1; x > y; y <<= 1, k++) ;
449#ifdef Pack_32
450 b = Balloc(k);
451 b->x[0] = y9;
452 b->wds = 1;
453#else
454 b = Balloc(k+1);
455 b->x[0] = y9 & 0xffff;
456 b->wds = (b->x[1] = y9 >> 16) ? 2 : 1;
457#endif
458
459 i = 9;
460 if (9 < nd0) {
461 s += 9;
462 do b = multadd(b, 10, *s++ - '0');
463 while(++i < nd0);
464 s++;
465 }
466 else
467 s += 10;
468 for(; i < nd; i++)
469 b = multadd(b, 10, *s++ - '0');
470 return b;
471 }
472
473 static int
474hi0bits(ULong x)
475{
476 int k = 0;
477
478 if (!(x & 0xffff0000)) {
479 k = 16;
480 x <<= 16;
481 }
482 if (!(x & 0xff000000)) {
483 k += 8;
484 x <<= 8;
485 }
486 if (!(x & 0xf0000000)) {
487 k += 4;
488 x <<= 4;
489 }
490 if (!(x & 0xc0000000)) {
491 k += 2;
492 x <<= 2;
493 }
494 if (!(x & 0x80000000)) {
495 k++;
496 if (!(x & 0x40000000))
497 return 32;
498 }
499 return k;
500 }
501
502 static int
503lo0bits(ULong *y)
504{
505 int k;
506 ULong x = *y;
507
508 if (x & 7) {
509 if (x & 1)
510 return 0;
511 if (x & 2) {
512 *y = x >> 1;
513 return 1;
514 }
515 *y = x >> 2;
516 return 2;
517 }
518 k = 0;
519 if (!(x & 0xffff)) {
520 k = 16;
521 x >>= 16;
522 }
523 if (!(x & 0xff)) {
524 k += 8;
525 x >>= 8;
526 }
527 if (!(x & 0xf)) {
528 k += 4;
529 x >>= 4;
530 }
531 if (!(x & 0x3)) {
532 k += 2;
533 x >>= 2;
534 }
535 if (!(x & 1)) {
536 k++;
537 x >>= 1;
538 if (!x & 1)
539 return 32;
540 }
541 *y = x;
542 return k;
543 }
544
545 static Bigint *
546i2b(int i)
547{
548 Bigint *b;
549
550 b = Balloc(1);
551 b->x[0] = i;
552 b->wds = 1;
553 return b;
554 }
555
556 static Bigint *
557mult(Bigint *a, Bigint *b)
558{
559 Bigint *c;
560 int k, wa, wb, wc;
561 ULong carry, y, z;
562 ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
563#ifdef Pack_32
564 ULong z2;
565#endif
566
567 if (a->wds < b->wds) {
568 c = a;
569 a = b;
570 b = c;
571 }
572 k = a->k;
573 wa = a->wds;
574 wb = b->wds;
575 wc = wa + wb;
576 if (wc > a->maxwds)
577 k++;
578 c = Balloc(k);
579 for(x = c->x, xa = x + wc; x < xa; x++)
580 *x = 0;
581 xa = a->x;
582 xae = xa + wa;
583 xb = b->x;
584 xbe = xb + wb;
585 xc0 = c->x;
586#ifdef Pack_32
587 for(; xb < xbe; xb++, xc0++) {
588 if ((y = *xb & 0xffff)) {
589 x = xa;
590 xc = xc0;
591 carry = 0;
592 do {
593 z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
594 carry = z >> 16;
595 z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
596 carry = z2 >> 16;
597 Storeinc(xc, z2, z);
598 }
599 while(x < xae);
600 *xc = carry;
601 }
602 if ((y = *xb >> 16)) {
603 x = xa;
604 xc = xc0;
605 carry = 0;
606 z2 = *xc;
607 do {
608 z = (*x & 0xffff) * y + (*xc >> 16) + carry;
609 carry = z >> 16;
610 Storeinc(xc, z, z2);
611 z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
612 carry = z2 >> 16;
613 }
614 while(x < xae);
615 *xc = z2;
616 }
617 }
618#else
619 for(; xb < xbe; xc0++) {
620 if (y = *xb++) {
621 x = xa;
622 xc = xc0;
623 carry = 0;
624 do {
625 z = *x++ * y + *xc + carry;
626 carry = z >> 16;
627 *xc++ = z & 0xffff;
628 }
629 while(x < xae);
630 *xc = carry;
631 }
632 }
633#endif
634 for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
635 c->wds = wc;
636 return c;
637 }
638
639 static Bigint *p5s;
640
641 static Bigint *
642pow5mult(Bigint *b, int k)
643{
644 Bigint *b1, *p5, *p51;
645 int i;
646 static int p05[3] = { 5, 25, 125 };
647
648 if ((i = k & 3))
649 b = multadd(b, p05[i-1], 0);
650
651 if (!(k >>= 2))
652 return b;
653 if (!(p5 = p5s)) {
654 /* first time */
655 p5 = p5s = i2b(625);
656 p5->next = 0;
657 }
658 for(;;) {
659 if (k & 1) {
660 b1 = mult(b, p5);
661 Bfree(b);
662 b = b1;
663 }
664 if (!(k >>= 1))
665 break;
666 if (!(p51 = p5->next)) {
667 p51 = p5->next = mult(p5,p5);
668 p51->next = 0;
669 }
670 p5 = p51;
671 }
672 return b;
673 }
674
675 static Bigint *
676lshift(Bigint *b, int k)
677{
678 int i, k1, n, n1;
679 Bigint *b1;
680 ULong *x, *x1, *xe, z;
681
682#ifdef Pack_32
683 n = k >> 5;
684#else
685 n = k >> 4;
686#endif
687 k1 = b->k;
688 n1 = n + b->wds + 1;
689 for(i = b->maxwds; n1 > i; i <<= 1)
690 k1++;
691 b1 = Balloc(k1);
692 x1 = b1->x;
693 for(i = 0; i < n; i++)
694 *x1++ = 0;
695 x = b->x;
696 xe = x + b->wds;
697#ifdef Pack_32
698 if (k &= 0x1f) {
699 k1 = 32 - k;
700 z = 0;
701 do {
702 *x1++ = *x << k | z;
703 z = *x++ >> k1;
704 }
705 while(x < xe);
706 if ((*x1 = z))
707 ++n1;
708 }
709#else
710 if (k &= 0xf) {
711 k1 = 16 - k;
712 z = 0;
713 do {
714 *x1++ = *x << k & 0xffff | z;
715 z = *x++ >> k1;
716 }
717 while(x < xe);
718 if (*x1 = z)
719 ++n1;
720 }
721#endif
722 else do
723 *x1++ = *x++;
724 while(x < xe);
725 b1->wds = n1 - 1;
726 Bfree(b);
727 return b1;
728 }
729
730 static int
731cmp(Bigint *a, Bigint *b)
732{
733 ULong *xa, *xa0, *xb, *xb0;
734 int i, j;
735
736 i = a->wds;
737 j = b->wds;
738#ifdef DEBUG
739 if (i > 1 && !a->x[i-1])
740 Bug("cmp called with a->x[a->wds-1] == 0");
741 if (j > 1 && !b->x[j-1])
742 Bug("cmp called with b->x[b->wds-1] == 0");
743#endif
744 if (i -= j)
745 return i;
746 xa0 = a->x;
747 xa = xa0 + j;
748 xb0 = b->x;
749 xb = xb0 + j;
750 for(;;) {
751 if (*--xa != *--xb)
752 return *xa < *xb ? -1 : 1;
753 if (xa <= xa0)
754 break;
755 }
756 return 0;
757 }
758
759 static Bigint *
760diff(Bigint *a, Bigint *b)
761{
762 Bigint *c;
763 int i, wa, wb;
764 Long borrow, y; /* We need signed shifts here. */
765 ULong *xa, *xae, *xb, *xbe, *xc;
766#ifdef Pack_32
767 Long z;
768#endif
769
770 i = cmp(a,b);
771 if (!i) {
772 c = Balloc(0);
773 c->wds = 1;
774 c->x[0] = 0;
775 return c;
776 }
777 if (i < 0) {
778 c = a;
779 a = b;
780 b = c;
781 i = 1;
782 }
783 else
784 i = 0;
785 c = Balloc(a->k);
786 c->sign = i;
787 wa = a->wds;
788 xa = a->x;
789 xae = xa + wa;
790 wb = b->wds;
791 xb = b->x;
792 xbe = xb + wb;
793 xc = c->x;
794 borrow = 0;
795#ifdef Pack_32
796 do {
797 y = (*xa & 0xffff) - (*xb & 0xffff) + borrow;
798 borrow = y >> 16;
799 Sign_Extend(borrow, y);
800 z = (*xa++ >> 16) - (*xb++ >> 16) + borrow;
801 borrow = z >> 16;
802 Sign_Extend(borrow, z);
803 Storeinc(xc, z, y);
804 }
805 while(xb < xbe);
806 while(xa < xae) {
807 y = (*xa & 0xffff) + borrow;
808 borrow = y >> 16;
809 Sign_Extend(borrow, y);
810 z = (*xa++ >> 16) + borrow;
811 borrow = z >> 16;
812 Sign_Extend(borrow, z);
813 Storeinc(xc, z, y);
814 }
815#else
816 do {
817 y = *xa++ - *xb++ + borrow;
818 borrow = y >> 16;
819 Sign_Extend(borrow, y);
820 *xc++ = y & 0xffff;
821 }
822 while(xb < xbe);
823 while(xa < xae) {
824 y = *xa++ + borrow;
825 borrow = y >> 16;
826 Sign_Extend(borrow, y);
827 *xc++ = y & 0xffff;
828 }
829#endif
830 while(!*--xc)
831 wa--;
832 c->wds = wa;
833 return c;
834 }
835
836 static double
837ulp(double _x)
838{
839 _double x;
840 Long L;
841 _double a;
842
843 value(x) = _x;
844 L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1;
845#ifndef Sudden_Underflow
846 if (L > 0) {
847#endif
848#ifdef IBM
849 L |= Exp_msk1 >> 4;
850#endif
851 word0(a) = L;
852 word1(a) = 0;
853#ifndef Sudden_Underflow
854 }
855 else {
856 L = -L >> Exp_shift;
857 if (L < Exp_shift) {
858 word0(a) = 0x80000 >> L;
859 word1(a) = 0;
860 }
861 else {
862 word0(a) = 0;
863 L -= Exp_shift;
864 word1(a) = L >= 31 ? 1 : 1 << 31 - L;
865 }
866 }
867#endif
868 return value(a);
869 }
870
871 static double
872b2d(Bigint *a, int *e)
873{
874 ULong *xa, *xa0, w, y, z;
875 int k;
876 _double d;
877#ifdef VAX
878 ULong d0, d1;
879#else
880#define d0 word0(d)
881#define d1 word1(d)
882#endif
883
884 xa0 = a->x;
885 xa = xa0 + a->wds;
886 y = *--xa;
887#ifdef DEBUG
888 if (!y) Bug("zero y in b2d");
889#endif
890 k = hi0bits(y);
891 *e = 32 - k;
892#ifdef Pack_32
893 if (k < Ebits) {
894 d0 = Exp_1 | y >> Ebits - k;
895 w = xa > xa0 ? *--xa : 0;
896 d1 = y << (32-Ebits) + k | w >> Ebits - k;
897 goto ret_d;
898 }
899 z = xa > xa0 ? *--xa : 0;
900 if (k -= Ebits) {
901 d0 = Exp_1 | y << k | z >> 32 - k;
902 y = xa > xa0 ? *--xa : 0;
903 d1 = z << k | y >> 32 - k;
904 }
905 else {
906 d0 = Exp_1 | y;
907 d1 = z;
908 }
909#else
910 if (k < Ebits + 16) {
911 z = xa > xa0 ? *--xa : 0;
912 d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
913 w = xa > xa0 ? *--xa : 0;
914 y = xa > xa0 ? *--xa : 0;
915 d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
916 goto ret_d;
917 }
918 z = xa > xa0 ? *--xa : 0;
919 w = xa > xa0 ? *--xa : 0;
920 k -= Ebits + 16;
921 d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
922 y = xa > xa0 ? *--xa : 0;
923 d1 = w << k + 16 | y << k;
924#endif
925 ret_d:
926#ifdef VAX
927 word0(d) = d0 >> 16 | d0 << 16;
928 word1(d) = d1 >> 16 | d1 << 16;
929#else
930#undef d0
931#undef d1
932#endif
933 return value(d);
934 }
935
936 static Bigint *
937d2b(double _d, int *e, int *bits)
938{
939 Bigint *b;
940 int de, i, k;
941 ULong *x, y, z;
942 _double d;
943#ifdef VAX
944 ULong d0, d1;
945#endif
946
947 value(d) = _d;
948#ifdef VAX
949 d0 = word0(d) >> 16 | word0(d) << 16;
950 d1 = word1(d) >> 16 | word1(d) << 16;
951#else
952#define d0 word0(d)
953#define d1 word1(d)
954#endif
955
956#ifdef Pack_32
957 b = Balloc(1);
958#else
959 b = Balloc(2);
960#endif
961 x = b->x;
962
963 z = d0 & Frac_mask;
964 d0 &= 0x7fffffff; /* clear sign bit, which we ignore */
965#ifdef Sudden_Underflow
966 de = (int)(d0 >> Exp_shift);
967#ifndef IBM
968 z |= Exp_msk11;
969#endif
970#else
971 if (de = (int)(d0 >> Exp_shift))
972 z |= Exp_msk1;
973#endif
974#ifdef Pack_32
975 if (y = d1) {
976 if (k = lo0bits(&y)) {
977 x[0] = y | z << 32 - k;
978 z >>= k;
979 }
980 else
981 x[0] = y;
982 i = b->wds = (x[1] = z) ? 2 : 1;
983 }
984 else {
985#ifdef DEBUG
986 if (!z)
987 Bug("Zero passed to d2b");
988#endif
989 k = lo0bits(&z);
990 x[0] = z;
991 i = b->wds = 1;
992 k += 32;
993 }
994#else
995 if (y = d1) {
996 if (k = lo0bits(&y))
997 if (k >= 16) {
998 x[0] = y | z << 32 - k & 0xffff;
999 x[1] = z >> k - 16 & 0xffff;
1000 x[2] = z >> k;
1001 i = 2;
1002 }
1003 else {
1004 x[0] = y & 0xffff;
1005 x[1] = y >> 16 | z << 16 - k & 0xffff;
1006 x[2] = z >> k & 0xffff;
1007 x[3] = z >> k+16;
1008 i = 3;
1009 }
1010 else {
1011 x[0] = y & 0xffff;
1012 x[1] = y >> 16;
1013 x[2] = z & 0xffff;
1014 x[3] = z >> 16;
1015 i = 3;
1016 }
1017 }
1018 else {
1019#ifdef DEBUG
1020 if (!z)
1021 Bug("Zero passed to d2b");
1022#endif
1023 k = lo0bits(&z);
1024 if (k >= 16) {
1025 x[0] = z;
1026 i = 0;
1027 }
1028 else {
1029 x[0] = z & 0xffff;
1030 x[1] = z >> 16;
1031 i = 1;
1032 }
1033 k += 32;
1034 }
1035 while(!x[i])
1036 --i;
1037 b->wds = i + 1;
1038#endif
1039#ifndef Sudden_Underflow
1040 if (de) {
1041#endif
1042#ifdef IBM
1043 *e = (de - Bias - (P-1) << 2) + k;
1044 *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask);
1045#else
1046 *e = de - Bias - (P-1) + k;
1047 *bits = P - k;
1048#endif
1049#ifndef Sudden_Underflow
1050 }
1051 else {
1052 *e = de - Bias - (P-1) + 1 + k;
1053#ifdef Pack_32
1054 *bits = 32*i - hi0bits(x[i-1]);
1055#else
1056 *bits = (i+2)*16 - hi0bits(x[i]);
1057#endif
1058 }
1059#endif
1060 return b;
1061 }
1062#undef d0
1063#undef d1
1064
1065 static double
1066ratio(Bigint *a, Bigint *b)
1067{
1068 _double da, db;
1069 int k, ka, kb;
1070
1071 value(da) = b2d(a, &ka);
1072 value(db) = b2d(b, &kb);
1073#ifdef Pack_32
1074 k = ka - kb + 32*(a->wds - b->wds);
1075#else
1076 k = ka - kb + 16*(a->wds - b->wds);
1077#endif
1078#ifdef IBM
1079 if (k > 0) {
1080 word0(da) += (k >> 2)*Exp_msk1;
1081 if (k &= 3)
1082 da *= 1 << k;
1083 }
1084 else {
1085 k = -k;
1086 word0(db) += (k >> 2)*Exp_msk1;
1087 if (k &= 3)
1088 db *= 1 << k;
1089 }
1090#else
1091 if (k > 0)
1092 word0(da) += k*Exp_msk1;
1093 else {
1094 k = -k;
1095 word0(db) += k*Exp_msk1;
1096 }
1097#endif
1098 return value(da) / value(db);
1099 }
1100
1101static CONST double
1102tens[] = {
1103 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
1104 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
1105 1e20, 1e21, 1e22
1106#ifdef VAX
1107 , 1e23, 1e24
1108#endif
1109 };
1110
1111#ifdef IEEE_Arith
1112static CONST double bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
1113static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
1114#define n_bigtens 5
1115#else
1116#ifdef IBM
1117static CONST double bigtens[] = { 1e16, 1e32, 1e64 };
1118static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64 };
1119#define n_bigtens 3
1120#else
1121static CONST double bigtens[] = { 1e16, 1e32 };
1122static CONST double tinytens[] = { 1e-16, 1e-32 };
1123#define n_bigtens 2
1124#endif
1125#endif
1126
1127 double
1128strtod(CONST char *s00, char **se)
1129{
1130 int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
1131 e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
1132 CONST char *s, *s0, *s1;
1133 double aadj, aadj1, adj;
1134 _double rv, rv0;
1135 Long L;
1136 ULong y, z;
1137 Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
1138
1139 CONST char decimal_point = localeconv()->decimal_point[0];
1140
1141 sign = nz0 = nz = 0;
1142 value(rv) = 0.;
1143
1144
1145 for(s = s00; isspace((unsigned char) *s); s++)
1146 ;
1147
1148 if (*s == '-') {
1149 sign = 1;
1150 s++;
1151 } else if (*s == '+') {
1152 s++;
1153 }
1154
1155 if (*s == '\0') {
1156 s = s00;
1157 goto ret;
1158 }
1159
1160 if (*s == '0') {
1161 nz0 = 1;
1162 while(*++s == '0') ;
1163 if (!*s)
1164 goto ret;
1165 }
1166 s0 = s;
1167 y = z = 0;
1168 for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
1169 if (nd < 9)
1170 y = 10*y + c - '0';
1171 else if (nd < 16)
1172 z = 10*z + c - '0';
1173 nd0 = nd;
1174 if (c == decimal_point) {
1175 c = *++s;
1176 if (!nd) {
1177 for(; c == '0'; c = *++s)
1178 nz++;
1179 if (c > '0' && c <= '9') {
1180 s0 = s;
1181 nf += nz;
1182 nz = 0;
1183 goto have_dig;
1184 }
1185 goto dig_done;
1186 }
1187 for(; c >= '0' && c <= '9'; c = *++s) {
1188 have_dig:
1189 nz++;
1190 if (c -= '0') {
1191 nf += nz;
1192 for(i = 1; i < nz; i++)
1193 if (nd++ < 9)
1194 y *= 10;
1195 else if (nd <= DBL_DIG + 1)
1196 z *= 10;
1197 if (nd++ < 9)
1198 y = 10*y + c;
1199 else if (nd <= DBL_DIG + 1)
1200 z = 10*z + c;
1201 nz = 0;
1202 }
1203 }
1204 }
1205 dig_done:
1206 e = 0;
1207 if (c == 'e' || c == 'E') {
1208 if (!nd && !nz && !nz0) {
1209 s = s00;
1210 goto ret;
1211 }
1212 s00 = s;
1213 esign = 0;
1214 switch(c = *++s) {
1215 case '-':
1216 esign = 1;
1217 case '+':
1218 c = *++s;
1219 }
1220 if (c >= '0' && c <= '9') {
1221 while(c == '0')
1222 c = *++s;
1223 if (c > '0' && c <= '9') {
1224 L = c - '0';
1225 s1 = s;
1226 while((c = *++s) >= '0' && c <= '9')
1227 L = 10*L + c - '0';
1228 if (s - s1 > 8 || L > 19999)
1229 /* Avoid confusion from exponents
1230 * so large that e might overflow.
1231 */
1232 e = 19999; /* safe for 16 bit ints */
1233 else
1234 e = (int)L;
1235 if (esign)
1236 e = -e;
1237 }
1238 else
1239 e = 0;
1240 }
1241 else
1242 s = s00;
1243 }
1244 if (!nd) {
1245 if (!nz && !nz0)
1246 s = s00;
1247 goto ret;
1248 }
1249 e1 = e -= nf;
1250
1251 /* Now we have nd0 digits, starting at s0, followed by a
1252 * decimal point, followed by nd-nd0 digits. The number we're
1253 * after is the integer represented by those digits times
1254 * 10**e */
1255
1256 if (!nd0)
1257 nd0 = nd;
1258 k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
1259 value(rv) = y;
1260 if (k > 9)
1261 value(rv) = tens[k - 9] * value(rv) + z;
1262 bd0 = 0;
1263 if (nd <= DBL_DIG
1264#ifndef RND_PRODQUOT
1265 && FLT_ROUNDS == 1
1266#endif
1267 ) {
1268 if (!e)
1269 goto ret;
1270 if (e > 0) {
1271 if (e <= Ten_pmax) {
1272#ifdef VAX
1273 goto vax_ovfl_check;
1274#else
1275 /* value(rv) = */ rounded_product(value(rv),
1276 tens[e]);
1277 goto ret;
1278#endif
1279 }
1280 i = DBL_DIG - nd;
1281 if (e <= Ten_pmax + i) {
1282 /* A fancier test would sometimes let us do
1283 * this for larger i values.
1284 */
1285 e -= i;
1286 value(rv) *= tens[i];
1287#ifdef VAX
1288 /* VAX exponent range is so narrow we must
1289 * worry about overflow here...
1290 */
1291 vax_ovfl_check:
1292 word0(rv) -= P*Exp_msk1;
1293 /* value(rv) = */ rounded_product(value(rv),
1294 tens[e]);
1295 if ((word0(rv) & Exp_mask)
1296 > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
1297 goto ovfl;
1298 word0(rv) += P*Exp_msk1;
1299#else
1300 /* value(rv) = */ rounded_product(value(rv),
1301 tens[e]);
1302#endif
1303 goto ret;
1304 }
1305 }
1306#ifndef Inaccurate_Divide
1307 else if (e >= -Ten_pmax) {
1308 /* value(rv) = */ rounded_quotient(value(rv),
1309 tens[-e]);
1310 goto ret;
1311 }
1312#endif
1313 }
1314 e1 += nd - k;
1315
1316 /* Get starting approximation = rv * 10**e1 */
1317
1318 if (e1 > 0) {
1319 if (i = e1 & 15)
1320 value(rv) *= tens[i];
1321 if (e1 &= ~15) {
1322 if (e1 > DBL_MAX_10_EXP) {
1323 ovfl:
1324 errno = ERANGE;
1325#ifndef Bad_float_h
1326 value(rv) = HUGE_VAL;
1327#else
1328 /* Can't trust HUGE_VAL */
1329#ifdef IEEE_Arith
1330 word0(rv) = Exp_mask;
1331 word1(rv) = 0;
1332#else
1333 word0(rv) = Big0;
1334 word1(rv) = Big1;
1335#endif
1336#endif
1337 if (bd0)
1338 goto retfree;
1339 goto ret;
1340 }
1341 if (e1 >>= 4) {
1342 for(j = 0; e1 > 1; j++, e1 >>= 1)
1343 if (e1 & 1)
1344 value(rv) *= bigtens[j];
1345 /* The last multiplication could overflow. */
1346 word0(rv) -= P*Exp_msk1;
1347 value(rv) *= bigtens[j];
1348 if ((z = word0(rv) & Exp_mask)
1349 > Exp_msk1*(DBL_MAX_EXP+Bias-P))
1350 goto ovfl;
1351 if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {
1352 /* set to largest number */
1353 /* (Can't trust DBL_MAX) */
1354 word0(rv) = Big0;
1355 word1(rv) = Big1;
1356 }
1357 else
1358 word0(rv) += P*Exp_msk1;
1359 }
1360
1361 }
1362 }
1363 else if (e1 < 0) {
1364 e1 = -e1;
1365 if (i = e1 & 15)
1366 value(rv) /= tens[i];
1367 if (e1 &= ~15) {
1368 e1 >>= 4;
1369 if (e1 >= 1 << n_bigtens)
1370 goto undfl;
1371 for(j = 0; e1 > 1; j++, e1 >>= 1)
1372 if (e1 & 1)
1373 value(rv) *= tinytens[j];
1374 /* The last multiplication could underflow. */
1375 value(rv0) = value(rv);
1376 value(rv) *= tinytens[j];
1377 if (!value(rv)) {
1378 value(rv) = 2.*value(rv0);
1379 value(rv) *= tinytens[j];
1380 if (!value(rv)) {
1381 undfl:
1382 value(rv) = 0.;
1383 errno = ERANGE;
1384 if (bd0)
1385 goto retfree;
1386 goto ret;
1387 }
1388 word0(rv) = Tiny0;
1389 word1(rv) = Tiny1;
1390 /* The refinement below will clean
1391 * this approximation up.
1392 */
1393 }
1394 }
1395 }
1396
1397 /* Now the hard part -- adjusting rv to the correct value.*/
1398
1399 /* Put digits into bd: true value = bd * 10^e */
1400
1401 bd0 = s2b(s0, nd0, nd, y);
1402
1403 for(;;) {
1404 bd = Balloc(bd0->k);
1405 Bcopy(bd, bd0);
1406 bb = d2b(value(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */
1407 bs = i2b(1);
1408
1409 if (e >= 0) {
1410 bb2 = bb5 = 0;
1411 bd2 = bd5 = e;
1412 }
1413 else {
1414 bb2 = bb5 = -e;
1415 bd2 = bd5 = 0;
1416 }
1417 if (bbe >= 0)
1418 bb2 += bbe;
1419 else
1420 bd2 -= bbe;
1421 bs2 = bb2;
1422#ifdef Sudden_Underflow
1423#ifdef IBM
1424 j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3);
1425#else
1426 j = P + 1 - bbbits;
1427#endif
1428#else
1429 i = bbe + bbbits - 1; /* logb(rv) */
1430 if (i < Emin) /* denormal */
1431 j = bbe + (P-Emin);
1432 else
1433 j = P + 1 - bbbits;
1434#endif
1435 bb2 += j;
1436 bd2 += j;
1437 i = bb2 < bd2 ? bb2 : bd2;
1438 if (i > bs2)
1439 i = bs2;
1440 if (i > 0) {
1441 bb2 -= i;
1442 bd2 -= i;
1443 bs2 -= i;
1444 }
1445 if (bb5 > 0) {
1446 bs = pow5mult(bs, bb5);
1447 bb1 = mult(bs, bb);
1448 Bfree(bb);
1449 bb = bb1;
1450 }
1451 if (bb2 > 0)
1452 bb = lshift(bb, bb2);
1453 if (bd5 > 0)
1454 bd = pow5mult(bd, bd5);
1455 if (bd2 > 0)
1456 bd = lshift(bd, bd2);
1457 if (bs2 > 0)
1458 bs = lshift(bs, bs2);
1459 delta = diff(bb, bd);
1460 dsign = delta->sign;
1461 delta->sign = 0;
1462 i = cmp(delta, bs);
1463 if (i < 0) {
1464 /* Error is less than half an ulp -- check for
1465 * special case of mantissa a power of two.
1466 */
1467 if (dsign || word1(rv) || word0(rv) & Bndry_mask)
1468 break;
1469 delta = lshift(delta,Log2P);
1470 if (cmp(delta, bs) > 0)
1471 goto drop_down;
1472 break;
1473 }
1474 if (i == 0) {
1475 /* exactly half-way between */
1476 if (dsign) {
1477 if ((word0(rv) & Bndry_mask1) == Bndry_mask1
1478 && word1(rv) == 0xffffffff) {
1479 /*boundary case -- increment exponent*/
1480 word0(rv) = (word0(rv) & Exp_mask)
1481 + Exp_msk1
1482#ifdef IBM
1483 | Exp_msk1 >> 4
1484#endif
1485 ;
1486 word1(rv) = 0;
1487 break;
1488 }
1489 }
1490 else if (!(word0(rv) & Bndry_mask) && !word1(rv)) {
1491 drop_down:
1492 /* boundary case -- decrement exponent */
1493#ifdef Sudden_Underflow
1494 L = word0(rv) & Exp_mask;
1495#ifdef IBM
1496 if (L < Exp_msk1)
1497#else
1498 if (L <= Exp_msk1)
1499#endif
1500 goto undfl;
1501 L -= Exp_msk1;
1502#else
1503 L = (word0(rv) & Exp_mask) - Exp_msk1;
1504#endif
1505 word0(rv) = L | Bndry_mask1;
1506 word1(rv) = 0xffffffff;
1507#ifdef IBM
1508 goto cont;
1509#else
1510 break;
1511#endif
1512 }
1513#ifndef ROUND_BIASED
1514 if (!(word1(rv) & LSB))
1515 break;
1516#endif
1517 if (dsign)
1518 value(rv) += ulp(value(rv));
1519#ifndef ROUND_BIASED
1520 else {
1521 value(rv) -= ulp(value(rv));
1522#ifndef Sudden_Underflow
1523 if (!value(rv))
1524 goto undfl;
1525#endif
1526 }
1527#endif
1528 break;
1529 }
1530 if ((aadj = ratio(delta, bs)) <= 2.) {
1531 if (dsign)
1532 aadj = aadj1 = 1.;
1533 else if (word1(rv) || word0(rv) & Bndry_mask) {
1534#ifndef Sudden_Underflow
1535 if (word1(rv) == Tiny1 && !word0(rv))
1536 goto undfl;
1537#endif
1538 aadj = 1.;
1539 aadj1 = -1.;
1540 }
1541 else {
1542 /* special case -- power of FLT_RADIX to be */
1543 /* rounded down... */
1544
1545 if (aadj < 2./FLT_RADIX)
1546 aadj = 1./FLT_RADIX;
1547 else
1548 aadj *= 0.5;
1549 aadj1 = -aadj;
1550 }
1551 }
1552 else {
1553 aadj *= 0.5;
1554 aadj1 = dsign ? aadj : -aadj;
1555#ifdef Check_FLT_ROUNDS
1556 switch(FLT_ROUNDS) {
1557 case 2: /* towards +infinity */
1558 aadj1 -= 0.5;
1559 break;
1560 case 0: /* towards 0 */
1561 case 3: /* towards -infinity */
1562 aadj1 += 0.5;
1563 }
1564#else
1565 if (FLT_ROUNDS == 0)
1566 aadj1 += 0.5;
1567#endif
1568 }
1569 y = word0(rv) & Exp_mask;
1570
1571 /* Check for overflow */
1572
1573 if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
1574 value(rv0) = value(rv);
1575 word0(rv) -= P*Exp_msk1;
1576 adj = aadj1 * ulp(value(rv));
1577 value(rv) += adj;
1578 if ((word0(rv) & Exp_mask) >=
1579 Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
1580 if (word0(rv0) == Big0 && word1(rv0) == Big1)
1581 goto ovfl;
1582 word0(rv) = Big0;
1583 word1(rv) = Big1;
1584 goto cont;
1585 }
1586 else
1587 word0(rv) += P*Exp_msk1;
1588 }
1589 else {
1590#ifdef Sudden_Underflow
1591 if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
1592 value(rv0) = value(rv);
1593 word0(rv) += P*Exp_msk1;
1594 adj = aadj1 * ulp(value(rv));
1595 value(rv) += adj;
1596#ifdef IBM
1597 if ((word0(rv) & Exp_mask) < P*Exp_msk1)
1598#else
1599 if ((word0(rv) & Exp_mask) <= P*Exp_msk1)
1600#endif
1601 {
1602 if (word0(rv0) == Tiny0
1603 && word1(rv0) == Tiny1)
1604 goto undfl;
1605 word0(rv) = Tiny0;
1606 word1(rv) = Tiny1;
1607 goto cont;
1608 }
1609 else
1610 word0(rv) -= P*Exp_msk1;
1611 }
1612 else {
1613 adj = aadj1 * ulp(value(rv));
1614 value(rv) += adj;
1615 }
1616#else
1617 /* Compute adj so that the IEEE rounding rules will
1618 * correctly round rv + adj in some half-way cases.
1619 * If rv * ulp(rv) is denormalized (i.e.,
1620 * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid
1621 * trouble from bits lost to denormalization;
1622 * example: 1.2e-307 .
1623 */
1624 if (y <= (P-1)*Exp_msk1 && aadj >= 1.) {
1625 aadj1 = (double)(int)(aadj + 0.5);
1626 if (!dsign)
1627 aadj1 = -aadj1;
1628 }
1629 adj = aadj1 * ulp(value(rv));
1630 value(rv) += adj;
1631#endif
1632 }
1633 z = word0(rv) & Exp_mask;
1634 if (y == z) {
1635 /* Can we stop now? */
1636 L = aadj;
1637 aadj -= L;
1638 /* The tolerances below are conservative. */
1639 if (dsign || word1(rv) || word0(rv) & Bndry_mask) {
1640 if (aadj < .4999999 || aadj > .5000001)
1641 break;
1642 }
1643 else if (aadj < .4999999/FLT_RADIX)
1644 break;
1645 }
1646 cont:
1647 Bfree(bb);
1648 Bfree(bd);
1649 Bfree(bs);
1650 Bfree(delta);
1651 }
1652 retfree:
1653 Bfree(bb);
1654 Bfree(bd);
1655 Bfree(bs);
1656 Bfree(bd0);
1657 Bfree(delta);
1658 ret:
1659 if (se)
1660 *se = (char *)s;
1661 return sign ? -value(rv) : value(rv);
1662 }
1663
1664 static int
1665quorem(Bigint *b, Bigint *S)
1666{
1667 int n;
1668 Long borrow, y;
1669 ULong carry, q, ys;
1670 ULong *bx, *bxe, *sx, *sxe;
1671#ifdef Pack_32
1672 Long z;
1673 ULong si, zs;
1674#endif
1675
1676 n = S->wds;
1677#ifdef DEBUG
1678 /*debug*/ if (b->wds > n)
1679 /*debug*/ Bug("oversize b in quorem");
1680#endif
1681 if (b->wds < n)
1682 return 0;
1683 sx = S->x;
1684 sxe = sx + --n;
1685 bx = b->x;
1686 bxe = bx + n;
1687 q = *bxe / (*sxe + 1); /* ensure q <= true quotient */
1688#ifdef DEBUG
1689 /*debug*/ if (q > 9)
1690 /*debug*/ Bug("oversized quotient in quorem");
1691#endif
1692 if (q) {
1693 borrow = 0;
1694 carry = 0;
1695 do {
1696#ifdef Pack_32
1697 si = *sx++;
1698 ys = (si & 0xffff) * q + carry;
1699 zs = (si >> 16) * q + (ys >> 16);
1700 carry = zs >> 16;
1701 y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
1702 borrow = y >> 16;
1703 Sign_Extend(borrow, y);
1704 z = (*bx >> 16) - (zs & 0xffff) + borrow;
1705 borrow = z >> 16;
1706 Sign_Extend(borrow, z);
1707 Storeinc(bx, z, y);
1708#else
1709 ys = *sx++ * q + carry;
1710 carry = ys >> 16;
1711 y = *bx - (ys & 0xffff) + borrow;
1712 borrow = y >> 16;
1713 Sign_Extend(borrow, y);
1714 *bx++ = y & 0xffff;
1715#endif
1716 }
1717 while(sx <= sxe);
1718 if (!*bxe) {
1719 bx = b->x;
1720 while(--bxe > bx && !*bxe)
1721 --n;
1722 b->wds = n;
1723 }
1724 }
1725 if (cmp(b, S) >= 0) {
1726 q++;
1727 borrow = 0;
1728 carry = 0;
1729 bx = b->x;
1730 sx = S->x;
1731 do {
1732#ifdef Pack_32
1733 si = *sx++;
1734 ys = (si & 0xffff) + carry;
1735 zs = (si >> 16) + (ys >> 16);
1736 carry = zs >> 16;
1737 y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
1738 borrow = y >> 16;
1739 Sign_Extend(borrow, y);
1740 z = (*bx >> 16) - (zs & 0xffff) + borrow;
1741 borrow = z >> 16;
1742 Sign_Extend(borrow, z);
1743 Storeinc(bx, z, y);
1744#else
1745 ys = *sx++ + carry;
1746 carry = ys >> 16;
1747 y = *bx - (ys & 0xffff) + borrow;
1748 borrow = y >> 16;
1749 Sign_Extend(borrow, y);
1750 *bx++ = y & 0xffff;
1751#endif
1752 }
1753 while(sx <= sxe);
1754 bx = b->x;
1755 bxe = bx + n;
1756 if (!*bxe) {
1757 while(--bxe > bx && !*bxe)
1758 --n;
1759 b->wds = n;
1760 }
1761 }
1762 return q;
1763 }
1764
1765/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
1766 *
1767 * Inspired by "How to Print Floating-Point Numbers Accurately" by
1768 * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101].
1769 *
1770 * Modifications:
1771 * 1. Rather than iterating, we use a simple numeric overestimate
1772 * to determine k = floor(log10(d)). We scale relevant
1773 * quantities using O(log2(k)) rather than O(k) multiplications.
1774 * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
1775 * try to generate digits strictly left to right. Instead, we
1776 * compute with fewer bits and propagate the carry if necessary
1777 * when rounding the final digit up. This is often faster.
1778 * 3. Under the assumption that input will be rounded nearest,
1779 * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
1780 * That is, we allow equality in stopping tests when the
1781 * round-nearest rule will give the same floating-point value
1782 * as would satisfaction of the stopping test with strict
1783 * inequality.
1784 * 4. We remove common factors of powers of 2 from relevant
1785 * quantities.
1786 * 5. When converting floating-point integers less than 1e16,
1787 * we use floating-point arithmetic rather than resorting
1788 * to multiple-precision integers.
1789 * 6. When asked to produce fewer than 15 digits, we first try
1790 * to get by with floating-point arithmetic; we resort to
1791 * multiple-precision integer arithmetic only if we cannot
1792 * guarantee that the floating-point calculation has given
1793 * the correctly rounded result. For k requested digits and
1794 * "uniformly" distributed input, the probability is
1795 * something like 10^(k-15) that we must resort to the Long
1796 * calculation.
1797 */
1798
1799 char *
1800__dtoa(double _d, int mode, int ndigits, int *decpt, int *sign, char **rve)
1801{
1802 /* Arguments ndigits, decpt, sign are similar to those
1803 of ecvt and fcvt; trailing zeros are suppressed from
1804 the returned string. If not null, *rve is set to point
1805 to the end of the return value. If d is +-Infinity or NaN,
1806 then *decpt is set to 9999.
1807
1808 mode:
1809 0 ==> shortest string that yields d when read in
1810 and rounded to nearest.
1811 1 ==> like 0, but with Steele & White stopping rule;
1812 e.g. with IEEE P754 arithmetic , mode 0 gives
1813 1e23 whereas mode 1 gives 9.999999999999999e22.
1814 2 ==> max(1,ndigits) significant digits. This gives a
1815 return value similar to that of ecvt, except
1816 that trailing zeros are suppressed.
1817 3 ==> through ndigits past the decimal point. This
1818 gives a return value similar to that from fcvt,
1819 except that trailing zeros are suppressed, and
1820 ndigits can be negative.
1821 4-9 should give the same return values as 2-3, i.e.,
1822 4 <= mode <= 9 ==> same return as mode
1823 2 + (mode & 1). These modes are mainly for
1824 debugging; often they run slower but sometimes
1825 faster than modes 2-3.
1826 4,5,8,9 ==> left-to-right digit generation.
1827 6-9 ==> don't try fast floating-point estimate
1828 (if applicable).
1829
1830 Values of mode other than 0-9 are treated as mode 0.
1831
1832 Sufficient space is allocated to the return value
1833 to hold the suppressed trailing zeros.
1834 */
1835
1836 int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1,
1837 j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
1838 spec_case, try_quick;
1839 Long L;
1840#ifndef Sudden_Underflow
1841 int denorm;
1842 ULong x;
1843#endif
1844 Bigint *b, *b1, *delta, *mlo, *mhi, *S;
1845 double ds;
1846 char *s, *s0;
1847 static Bigint *result;
1848 static int result_k;
1849 _double d, d2, eps;
1850
1851 value(d) = _d;
1852 if (result) {
1853 result->k = result_k;
1854 result->maxwds = 1 << result_k;
1855 Bfree(result);
1856 result = 0;
1857 }
1858
1859 if (word0(d) & Sign_bit) {
1860 /* set sign for everything, including 0's and NaNs */
1861 *sign = 1;
1862 word0(d) &= ~Sign_bit; /* clear sign bit */
1863 }
1864 else
1865 *sign = 0;
1866
1867#if defined(IEEE_Arith) + defined(VAX)
1868#ifdef IEEE_Arith
1869 if ((word0(d) & Exp_mask) == Exp_mask)
1870#else
1871 if (word0(d) == 0x8000)
1872#endif
1873 {
1874 /* Infinity or NaN */
1875 *decpt = 9999;
1876 s =
1877#ifdef IEEE_Arith
1878 !word1(d) && !(word0(d) & 0xfffff) ? ndigits < 8 ? "Inf" : "Infinity" :
1879#endif
1880 "NaN";
1881 if (rve)
1882 *rve =
1883#ifdef IEEE_Arith
1884 s[3] ? s + 8 :
1885#endif
1886 s + 3;
1887 return s;
1888 }
1889#endif
1890#ifdef IBM
1891 value(d) += 0; /* normalize */
1892#endif
1893 if (!value(d)) {
1894 *decpt = 1;
1895 s = "0";
1896 if (rve)
1897 *rve = s + 1;
1898 return s;
1899 }
1900
1901 b = d2b(value(d), &be, &bbits);
1902#ifdef Sudden_Underflow
1903 i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
1904#else
1905 if (i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) {
1906#endif
1907 value(d2) = value(d);
1908 word0(d2) &= Frac_mask1;
1909 word0(d2) |= Exp_11;
1910#ifdef IBM
1911 if (j = 11 - hi0bits(word0(d2) & Frac_mask))
1912 value(d2) /= 1 << j;
1913#endif
1914
1915 /* log(x) ~=~ log(1.5) + (x-1.5)/1.5
1916 * log10(x) = log(x) / log(10)
1917 * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
1918 * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
1919 *
1920 * This suggests computing an approximation k to log10(d) by
1921 *
1922 * k = (i - Bias)*0.301029995663981
1923 * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
1924 *
1925 * We want k to be too large rather than too small.
1926 * The error in the first-order Taylor series approximation
1927 * is in our favor, so we just round up the constant enough
1928 * to compensate for any error in the multiplication of
1929 * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
1930 * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
1931 * adding 1e-13 to the constant term more than suffices.
1932 * Hence we adjust the constant term to 0.1760912590558.
1933 * (We could get a more accurate k by invoking log10,
1934 * but this is probably not worthwhile.)
1935 */
1936
1937 i -= Bias;
1938#ifdef IBM
1939 i <<= 2;
1940 i += j;
1941#endif
1942#ifndef Sudden_Underflow
1943 denorm = 0;
1944 }
1945 else {
1946 /* d is denormalized */
1947
1948 i = bbits + be + (Bias + (P-1) - 1);
1949 x = i > 32 ? word0(d) << 64 - i | word1(d) >> i - 32
1950 : word1(d) << 32 - i;
1951 value(d2) = x;
1952 word0(d2) -= 31*Exp_msk1; /* adjust exponent */
1953 i -= (Bias + (P-1) - 1) + 1;
1954 denorm = 1;
1955 }
1956#endif
1957 ds = (value(d2)-1.5)*0.289529654602168 + 0.1760912590558 +
1958 i*0.301029995663981;
1959 k = (int)ds;
1960 if (ds < 0. && ds != k)
1961 k--; /* want k = floor(ds) */
1962 k_check = 1;
1963 if (k >= 0 && k <= Ten_pmax) {
1964 if (value(d) < tens[k])
1965 k--;
1966 k_check = 0;
1967 }
1968 j = bbits - i - 1;
1969 if (j >= 0) {
1970 b2 = 0;
1971 s2 = j;
1972 }
1973 else {
1974 b2 = -j;
1975 s2 = 0;
1976 }
1977 if (k >= 0) {
1978 b5 = 0;
1979 s5 = k;
1980 s2 += k;
1981 }
1982 else {
1983 b2 -= k;
1984 b5 = -k;
1985 s5 = 0;
1986 }
1987 if (mode < 0 || mode > 9)
1988 mode = 0;
1989 try_quick = 1;
1990 if (mode > 5) {
1991 mode -= 4;
1992 try_quick = 0;
1993 }
1994 leftright = 1;
1995 switch(mode) {
1996 case 0:
1997 case 1:
1998 ilim = ilim1 = -1;
1999 i = 18;
2000 ndigits = 0;
2001 break;
2002 case 2:
2003 leftright = 0;
2004 /* no break */
2005 case 4:
2006 if (ndigits <= 0)
2007 ndigits = 1;
2008 ilim = ilim1 = i = ndigits;
2009 break;
2010 case 3:
2011 leftright = 0;
2012 /* no break */
2013 case 5:
2014 i = ndigits + k + 1;
2015 ilim = i;
2016 ilim1 = i - 1;
2017 if (i <= 0)
2018 i = 1;
2019 }
2020 j = sizeof(ULong);
2021 for(result_k = 0; sizeof(Bigint) - sizeof(ULong) + j <= i;
2022 j <<= 1) result_k++;
2023 result = Balloc(result_k);
2024 s = s0 = (char *)result;
2025
2026 if (ilim >= 0 && ilim <= Quick_max && try_quick) {
2027
2028 /* Try to get by with floating-point arithmetic. */
2029
2030 i = 0;
2031 value(d2) = value(d);
2032 k0 = k;
2033 ilim0 = ilim;
2034 ieps = 2; /* conservative */
2035 if (k > 0) {
2036 ds = tens[k&0xf];
2037 j = k >> 4;
2038 if (j & Bletch) {
2039 /* prevent overflows */
2040 j &= Bletch - 1;
2041 value(d) /= bigtens[n_bigtens-1];
2042 ieps++;
2043 }
2044 for(; j; j >>= 1, i++)
2045 if (j & 1) {
2046 ieps++;
2047 ds *= bigtens[i];
2048 }
2049 value(d) /= ds;
2050 }
2051 else if (j1 = -k) {
2052 value(d) *= tens[j1 & 0xf];
2053 for(j = j1 >> 4; j; j >>= 1, i++)
2054 if (j & 1) {
2055 ieps++;
2056 value(d) *= bigtens[i];
2057 }
2058 }
2059 if (k_check && value(d) < 1. && ilim > 0) {
2060 if (ilim1 <= 0)
2061 goto fast_failed;
2062 ilim = ilim1;
2063 k--;
2064 value(d) *= 10.;
2065 ieps++;
2066 }
2067 value(eps) = ieps*value(d) + 7.;
2068 word0(eps) -= (P-1)*Exp_msk1;
2069 if (ilim == 0) {
2070 S = mhi = 0;
2071 value(d) -= 5.;
2072 if (value(d) > value(eps))
2073 goto one_digit;
2074 if (value(d) < -value(eps))
2075 goto no_digits;
2076 goto fast_failed;
2077 }
2078#ifndef No_leftright
2079 if (leftright) {
2080 /* Use Steele & White method of only
2081 * generating digits needed.
2082 */
2083 value(eps) = 0.5/tens[ilim-1] - value(eps);
2084 for(i = 0;;) {
2085 L = value(d);
2086 value(d) -= L;
2087 *s++ = '0' + (int)L;
2088 if (value(d) < value(eps))
2089 goto ret1;
2090 if (1. - value(d) < value(eps))
2091 goto bump_up;
2092 if (++i >= ilim)
2093 break;
2094 value(eps) *= 10.;
2095 value(d) *= 10.;
2096 }
2097 }
2098 else {
2099#endif
2100 /* Generate ilim digits, then fix them up. */
2101 value(eps) *= tens[ilim-1];
2102 for(i = 1;; i++, value(d) *= 10.) {
2103 L = value(d);
2104 value(d) -= L;
2105 *s++ = '0' + (int)L;
2106 if (i == ilim) {
2107 if (value(d) > 0.5 + value(eps))
2108 goto bump_up;
2109 else if (value(d) < 0.5 - value(eps)) {
2110 while(*--s == '0');
2111 s++;
2112 goto ret1;
2113 }
2114 break;
2115 }
2116 }
2117#ifndef No_leftright
2118 }
2119#endif
2120 fast_failed:
2121 s = s0;
2122 value(d) = value(d2);
2123 k = k0;
2124 ilim = ilim0;
2125 }
2126
2127 /* Do we have a "small" integer? */
2128
2129 if (be >= 0 && k <= Int_max) {
2130 /* Yes. */
2131 ds = tens[k];
2132 if (ndigits < 0 && ilim <= 0) {
2133 S = mhi = 0;
2134 if (ilim < 0 || value(d) <= 5*ds)
2135 goto no_digits;
2136 goto one_digit;
2137 }
2138 for(i = 1;; i++) {
2139 L = value(d) / ds;
2140 value(d) -= L*ds;
2141#ifdef Check_FLT_ROUNDS
2142 /* If FLT_ROUNDS == 2, L will usually be high by 1 */
2143 if (value(d) < 0) {
2144 L--;
2145 value(d) += ds;
2146 }
2147#endif
2148 *s++ = '0' + (int)L;
2149 if (i == ilim) {
2150 value(d) += value(d);
2151 if (value(d) > ds || value(d) == ds && L & 1) {
2152 bump_up:
2153 while(*--s == '9')
2154 if (s == s0) {
2155 k++;
2156 *s = '0';
2157 break;
2158 }
2159 ++*s++;
2160 }
2161 break;
2162 }
2163 if (!(value(d) *= 10.))
2164 break;
2165 }
2166 goto ret1;
2167 }
2168
2169 m2 = b2;
2170 m5 = b5;
2171 mhi = mlo = 0;
2172 if (leftright) {
2173 if (mode < 2) {
2174 i =
2175#ifndef Sudden_Underflow
2176 denorm ? be + (Bias + (P-1) - 1 + 1) :
2177#endif
2178#ifdef IBM
2179 1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3);
2180#else
2181 1 + P - bbits;
2182#endif
2183 }
2184 else {
2185 j = ilim - 1;
2186 if (m5 >= j)
2187 m5 -= j;
2188 else {
2189 s5 += j -= m5;
2190 b5 += j;
2191 m5 = 0;
2192 }
2193 if ((i = ilim) < 0) {
2194 m2 -= i;
2195 i = 0;
2196 }
2197 }
2198 b2 += i;
2199 s2 += i;
2200 mhi = i2b(1);
2201 }
2202 if (m2 > 0 && s2 > 0) {
2203 i = m2 < s2 ? m2 : s2;
2204 b2 -= i;
2205 m2 -= i;
2206 s2 -= i;
2207 }
2208 if (b5 > 0) {
2209 if (leftright) {
2210 if (m5 > 0) {
2211 mhi = pow5mult(mhi, m5);
2212 b1 = mult(mhi, b);
2213 Bfree(b);
2214 b = b1;
2215 }
2216 if (j = b5 - m5)
2217 b = pow5mult(b, j);
2218 }
2219 else
2220 b = pow5mult(b, b5);
2221 }
2222 S = i2b(1);
2223 if (s5 > 0)
2224 S = pow5mult(S, s5);
2225
2226 /* Check for special case that d is a normalized power of 2. */
2227
2228 if (mode < 2) {
2229 if (!word1(d) && !(word0(d) & Bndry_mask)
2230#ifndef Sudden_Underflow
2231 && word0(d) & Exp_mask
2232#endif
2233 ) {
2234 /* The special case */
2235 b2 += Log2P;
2236 s2 += Log2P;
2237 spec_case = 1;
2238 }
2239 else
2240 spec_case = 0;
2241 }
2242
2243 /* Arrange for convenient computation of quotients:
2244 * shift left if necessary so divisor has 4 leading 0 bits.
2245 *
2246 * Perhaps we should just compute leading 28 bits of S once
2247 * and for all and pass them and a shift to quorem, so it
2248 * can do shifts and ors to compute the numerator for q.
2249 */
2250#ifdef Pack_32
2251 if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f)
2252 i = 32 - i;
2253#else
2254 if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf)
2255 i = 16 - i;
2256#endif
2257 if (i > 4) {
2258 i -= 4;
2259 b2 += i;
2260 m2 += i;
2261 s2 += i;
2262 }
2263 else if (i < 4) {
2264 i += 28;
2265 b2 += i;
2266 m2 += i;
2267 s2 += i;
2268 }
2269 if (b2 > 0)
2270 b = lshift(b, b2);
2271 if (s2 > 0)
2272 S = lshift(S, s2);
2273 if (k_check) {
2274 if (cmp(b,S) < 0) {
2275 k--;
2276 b = multadd(b, 10, 0); /* we botched the k estimate */
2277 if (leftright)
2278 mhi = multadd(mhi, 10, 0);
2279 ilim = ilim1;
2280 }
2281 }
2282 if (ilim <= 0 && mode > 2) {
2283 if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) {
2284 /* no digits, fcvt style */
2285 no_digits:
2286 k = -1 - ndigits;
2287 goto ret;
2288 }
2289 one_digit:
2290 *s++ = '1';
2291 k++;
2292 goto ret;
2293 }
2294 if (leftright) {
2295 if (m2 > 0)
2296 mhi = lshift(mhi, m2);
2297
2298 /* Compute mlo -- check for special case
2299 * that d is a normalized power of 2.
2300 */
2301
2302 mlo = mhi;
2303 if (spec_case) {
2304 mhi = Balloc(mhi->k);
2305 Bcopy(mhi, mlo);
2306 mhi = lshift(mhi, Log2P);
2307 }
2308
2309 for(i = 1;;i++) {
2310 dig = quorem(b,S) + '0';
2311 /* Do we yet have the shortest decimal string
2312 * that will round to d?
2313 */
2314 j = cmp(b, mlo);
2315 delta = diff(S, mhi);
2316 j1 = delta->sign ? 1 : cmp(b, delta);
2317 Bfree(delta);
2318#ifndef ROUND_BIASED
2319 if (j1 == 0 && !mode && !(word1(d) & 1)) {
2320 if (dig == '9')
2321 goto round_9_up;
2322 if (j > 0)
2323 dig++;
2324 *s++ = dig;
2325 goto ret;
2326 }
2327#endif
2328 if (j < 0 || j == 0 && !mode
2329#ifndef ROUND_BIASED
2330 && !(word1(d) & 1)
2331#endif
2332 ) {
2333 if (j1 > 0) {
2334 b = lshift(b, 1);
2335 j1 = cmp(b, S);
2336 if ((j1 > 0 || j1 == 0 && dig & 1)
2337 && dig++ == '9')
2338 goto round_9_up;
2339 }
2340 *s++ = dig;
2341 goto ret;
2342 }
2343 if (j1 > 0) {
2344 if (dig == '9') { /* possible if i == 1 */
2345 round_9_up:
2346 *s++ = '9';
2347 goto roundoff;
2348 }
2349 *s++ = dig + 1;
2350 goto ret;
2351 }
2352 *s++ = dig;
2353 if (i == ilim)
2354 break;
2355 b = multadd(b, 10, 0);
2356 if (mlo == mhi)
2357 mlo = mhi = multadd(mhi, 10, 0);
2358 else {
2359 mlo = multadd(mlo, 10, 0);
2360 mhi = multadd(mhi, 10, 0);
2361 }
2362 }
2363 }
2364 else
2365 for(i = 1;; i++) {
2366 *s++ = dig = quorem(b,S) + '0';
2367 if (i >= ilim)
2368 break;
2369 b = multadd(b, 10, 0);
2370 }
2371
2372 /* Round off last digit */
2373
2374 b = lshift(b, 1);
2375 j = cmp(b, S);
2376 if (j > 0 || j == 0 && dig & 1) {
2377 roundoff:
2378 while(*--s == '9')
2379 if (s == s0) {
2380 k++;
2381 *s++ = '1';
2382 goto ret;
2383 }
2384 ++*s++;
2385 }
2386 else {
2387 while(*--s == '0');
2388 s++;
2389 }
2390 ret:
2391 Bfree(S);
2392 if (mhi) {
2393 if (mlo && mlo != mhi)
2394 Bfree(mlo);
2395 Bfree(mhi);
2396 }
2397 ret1:
2398 Bfree(b);
2399 if (s == s0) { /* don't return empty string */
2400 *s++ = '0';
2401 k = 0;
2402 }
2403 *s = 0;
2404 *decpt = k + 1;
2405 if (rve)
2406 *rve = s;
2407 return s0;
2408 }
2409#ifdef __cplusplus
2410}
2411#endif
diff --git a/src/lib/libc/stdlib/strtol.3 b/src/lib/libc/stdlib/strtol.3
new file mode 100644
index 0000000000..3f5375c5e3
--- /dev/null
+++ b/src/lib/libc/stdlib/strtol.3
@@ -0,0 +1,247 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" Chris Torek and the American National Standards Committee X3,
6.\" on Information Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: strtol.3,v 1.13 2003/06/02 20:18:38 millert Exp $
33.\"
34.Dd June 25, 1992
35.Dt STRTOL 3
36.Os
37.Sh NAME
38.Nm strtol ,
39.Nm strtoll ,
40.Nm strtoq
41.Nd "convert string value to a long or long long integer"
42.Sh SYNOPSIS
43.Fd #include <stdlib.h>
44.Fd #include <limits.h>
45.Ft long
46.Fn strtol "const char *nptr" "char **endptr" "int base"
47.Pp
48.Fd #include <stdlib.h>
49.Fd #include <limits.h>
50.Ft long long
51.Fn strtoll "const char *nptr" "char **endptr" "int base"
52.Pp
53.Fd #include <sys/types.h>
54.Fd #include <stdlib.h>
55.Fd #include <limits.h>
56.Ft quad_t
57.Fn strtoq "const char *nptr" "char **endptr" "int base"
58.Sh DESCRIPTION
59The
60.Fn strtol
61function converts the string in
62.Fa nptr
63to a
64.Li long
65value.
66The
67.Fn strtoll
68function converts the string in
69.Fa nptr
70to a
71.Li long long
72value.
73The
74.Fn strtoq
75function is a deprecated equivalent of
76.Fn strtoll
77and is provided for backwards compatibility with legacy programs.
78The conversion is done according to the given
79.Fa base ,
80which must be a number between 2 and 36 inclusive or the special value 0.
81.Pp
82The string may begin with an arbitrary amount of whitespace
83(as determined by
84.Xr isspace 3 )
85followed by a single optional
86.Ql +
87or
88.Ql -
89sign.
90If
91.Fa base
92is zero or 16, the string may then include a
93.Ql 0x
94prefix, and the number will be read in base 16; otherwise, a zero
95.Fa base
96is taken as 10 (decimal) unless the next character is
97.Ql 0 ,
98in which case it is taken as 8 (octal).
99.Pp
100The remainder of the string is converted to a
101.Li long
102value in the obvious manner,
103stopping at the first character which is not a valid digit
104in the given base.
105(In bases above 10, the letter
106.Ql A
107in either upper or lower case represents 10,
108.Ql B
109represents 11, and so forth, with
110.Ql Z
111representing 35.)
112.Pp
113If
114.Fa endptr
115is non-null,
116.Fn strtol
117stores the address of the first invalid character in
118.Fa *endptr .
119If there were no digits at all, however,
120.Fn strtol
121stores the original value of
122.Fa nptr
123in
124.Fa *endptr .
125(Thus, if
126.Fa *nptr
127is not
128.Ql \e0
129but
130.Fa **endptr
131is
132.Ql \e0
133on return, the entire string was valid.)
134.Sh RETURN VALUES
135The
136.Fn strtol
137function returns the result of the conversion,
138unless the value would underflow or overflow.
139If an underflow occurs,
140.Fn strtol
141returns
142.Dv LONG_MIN .
143If an overflow occurs,
144.Fn strtol
145returns
146.Dv LONG_MAX .
147In both cases,
148.Va errno
149is set to
150.Er ERANGE .
151.Pp
152The
153.Fn strtoll
154function has identical return values except that
155.Dv LLONG_MIN
156and
157.Dv LLONG_MAX
158are used to indicate underflow and overflow respectively.
159.Sh EXAMPLES
160Ensuring that a string is a valid number (i.e., in range and containing no
161trailing characters) requires clearing
162.Va errno
163beforehand explicitly since
164.Va errno
165is not changed on a successful call to
166.Fn strtol ,
167and the return value of
168.Fn strtol
169cannot be used unambiguously to signal an error:
170.Bd -literal -offset indent
171char *ep;
172long lval;
173
174\&...
175
176errno = 0;
177lval = strtol(buf, &ep, 10);
178if (buf[0] == '\e0' || *ep != '\e0')
179 goto not_a_number;
180if (errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN))
181 goto out_of_range;
182.Ed
183.Pp
184This example will accept
185.Dq 12
186but not
187.Dq 12foo
188or
189.Dq 12\en .
190If trailing whitespace is acceptable, further checks must be done on
191.Va *ep ;
192alternately, use
193.Xr sscanf 3 .
194.Pp
195If
196.Fn strtol
197is being used instead of
198.Xr atoi 3 ,
199error checking is further complicated because the desired return value is an
200.Li int
201rather than a
202.Li long ;
203however, on some architectures integers and long integers are the same size.
204Thus the following is necessary:
205.Bd -literal -offset indent
206char *ep;
207int ival;
208long lval;
209
210\&...
211
212errno = 0;
213lval = strtol(buf, &ep, 10);
214if (buf[0] == '\e0' || *ep != '\e0')
215 goto not_a_number;
216if ((errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN)) ||
217 (lval > INT_MAX || lval < INT_MIN))
218 goto out_of_range;
219ival = lval;
220.Ed
221.Sh ERRORS
222.Bl -tag -width Er
223.It Bq Er ERANGE
224The given string was out of range; the value converted has been clamped.
225.El
226.Sh SEE ALSO
227.Xr atof 3 ,
228.Xr atoi 3 ,
229.Xr atol 3 ,
230.Xr atoll 3 ,
231.Xr sscanf 3 ,
232.Xr strtod 3 ,
233.Xr strtoul 3
234.Sh STANDARDS
235The
236.Fn strtol
237and
238.Fn strtoll
239functions conform to
240.St -ansiC-99 .
241The
242.Fn strtoq
243function is a
244.Bx
245extension and is provided for backwards compatibility with legacy programs.
246.Sh BUGS
247Ignores the current locale.
diff --git a/src/lib/libc/stdlib/strtol.c b/src/lib/libc/stdlib/strtol.c
new file mode 100644
index 0000000000..9692bb6b07
--- /dev/null
+++ b/src/lib/libc/stdlib/strtol.c
@@ -0,0 +1,143 @@
1/*-
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: strtol.c,v 1.6 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <ctype.h>
35#include <errno.h>
36#include <limits.h>
37#include <stdlib.h>
38
39
40/*
41 * Convert a string to a long integer.
42 *
43 * Ignores `locale' stuff. Assumes that the upper and lower case
44 * alphabets and digits are each contiguous.
45 */
46long
47strtol(const char *nptr, char **endptr, int base)
48{
49 const char *s;
50 long acc, cutoff;
51 int c;
52 int neg, any, cutlim;
53
54 /*
55 * Skip white space and pick up leading +/- sign if any.
56 * If base is 0, allow 0x for hex and 0 for octal, else
57 * assume decimal; if base is already 16, allow 0x.
58 */
59 s = nptr;
60 do {
61 c = (unsigned char) *s++;
62 } while (isspace(c));
63 if (c == '-') {
64 neg = 1;
65 c = *s++;
66 } else {
67 neg = 0;
68 if (c == '+')
69 c = *s++;
70 }
71 if ((base == 0 || base == 16) &&
72 c == '0' && (*s == 'x' || *s == 'X')) {
73 c = s[1];
74 s += 2;
75 base = 16;
76 }
77 if (base == 0)
78 base = c == '0' ? 8 : 10;
79
80 /*
81 * Compute the cutoff value between legal numbers and illegal
82 * numbers. That is the largest legal value, divided by the
83 * base. An input number that is greater than this value, if
84 * followed by a legal input character, is too big. One that
85 * is equal to this value may be valid or not; the limit
86 * between valid and invalid numbers is then based on the last
87 * digit. For instance, if the range for longs is
88 * [-2147483648..2147483647] and the input base is 10,
89 * cutoff will be set to 214748364 and cutlim to either
90 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
91 * a value > 214748364, or equal but the next digit is > 7 (or 8),
92 * the number is too big, and we will return a range error.
93 *
94 * Set any if any `digits' consumed; make it negative to indicate
95 * overflow.
96 */
97 cutoff = neg ? LONG_MIN : LONG_MAX;
98 cutlim = cutoff % base;
99 cutoff /= base;
100 if (neg) {
101 if (cutlim > 0) {
102 cutlim -= base;
103 cutoff += 1;
104 }
105 cutlim = -cutlim;
106 }
107 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
108 if (isdigit(c))
109 c -= '0';
110 else if (isalpha(c))
111 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
112 else
113 break;
114 if (c >= base)
115 break;
116 if (any < 0)
117 continue;
118 if (neg) {
119 if (acc < cutoff || acc == cutoff && c > cutlim) {
120 any = -1;
121 acc = LONG_MIN;
122 errno = ERANGE;
123 } else {
124 any = 1;
125 acc *= base;
126 acc -= c;
127 }
128 } else {
129 if (acc > cutoff || acc == cutoff && c > cutlim) {
130 any = -1;
131 acc = LONG_MAX;
132 errno = ERANGE;
133 } else {
134 any = 1;
135 acc *= base;
136 acc += c;
137 }
138 }
139 }
140 if (endptr != 0)
141 *endptr = (char *) (any ? s - 1 : nptr);
142 return (acc);
143}
diff --git a/src/lib/libc/stdlib/strtoll.c b/src/lib/libc/stdlib/strtoll.c
new file mode 100644
index 0000000000..fa4d30ef5a
--- /dev/null
+++ b/src/lib/libc/stdlib/strtoll.c
@@ -0,0 +1,156 @@
1/*-
2 * Copyright (c) 1992 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static const char rcsid[] = "$OpenBSD: strtoll.c,v 1.4 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35
36#include <ctype.h>
37#include <errno.h>
38#include <limits.h>
39#include <stdlib.h>
40
41/*
42 * Convert a string to a long long.
43 *
44 * Ignores `locale' stuff. Assumes that the upper and lower case
45 * alphabets and digits are each contiguous.
46 */
47long long
48strtoll(const char *nptr, char **endptr, int base)
49{
50 const char *s;
51 long long acc, cutoff;
52 int c;
53 int neg, any, cutlim;
54
55 /*
56 * Skip white space and pick up leading +/- sign if any.
57 * If base is 0, allow 0x for hex and 0 for octal, else
58 * assume decimal; if base is already 16, allow 0x.
59 */
60 s = nptr;
61 do {
62 c = (unsigned char) *s++;
63 } while (isspace(c));
64 if (c == '-') {
65 neg = 1;
66 c = *s++;
67 } else {
68 neg = 0;
69 if (c == '+')
70 c = *s++;
71 }
72 if ((base == 0 || base == 16) &&
73 c == '0' && (*s == 'x' || *s == 'X')) {
74 c = s[1];
75 s += 2;
76 base = 16;
77 }
78 if (base == 0)
79 base = c == '0' ? 8 : 10;
80
81 /*
82 * Compute the cutoff value between legal numbers and illegal
83 * numbers. That is the largest legal value, divided by the
84 * base. An input number that is greater than this value, if
85 * followed by a legal input character, is too big. One that
86 * is equal to this value may be valid or not; the limit
87 * between valid and invalid numbers is then based on the last
88 * digit. For instance, if the range for long longs is
89 * [-9223372036854775808..9223372036854775807] and the input base
90 * is 10, cutoff will be set to 922337203685477580 and cutlim to
91 * either 7 (neg==0) or 8 (neg==1), meaning that if we have
92 * accumulated a value > 922337203685477580, or equal but the
93 * next digit is > 7 (or 8), the number is too big, and we will
94 * return a range error.
95 *
96 * Set any if any `digits' consumed; make it negative to indicate
97 * overflow.
98 */
99 cutoff = neg ? LLONG_MIN : LLONG_MAX;
100 cutlim = cutoff % base;
101 cutoff /= base;
102 if (neg) {
103 if (cutlim > 0) {
104 cutlim -= base;
105 cutoff += 1;
106 }
107 cutlim = -cutlim;
108 }
109 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
110 if (isdigit(c))
111 c -= '0';
112 else if (isalpha(c))
113 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
114 else
115 break;
116 if (c >= base)
117 break;
118 if (any < 0)
119 continue;
120 if (neg) {
121 if (acc < cutoff || (acc == cutoff && c > cutlim)) {
122 any = -1;
123 acc = LLONG_MIN;
124 errno = ERANGE;
125 } else {
126 any = 1;
127 acc *= base;
128 acc -= c;
129 }
130 } else {
131 if (acc > cutoff || (acc == cutoff && c > cutlim)) {
132 any = -1;
133 acc = LLONG_MAX;
134 errno = ERANGE;
135 } else {
136 any = 1;
137 acc *= base;
138 acc += c;
139 }
140 }
141 }
142 if (endptr != 0)
143 *endptr = (char *) (any ? s - 1 : nptr);
144 return (acc);
145}
146
147#ifdef __weak_alias
148__weak_alias(strtoq, strtoll);
149#else
150quad_t
151strtoq(const char *nptr, char **endptr, int base)
152{
153
154 return ((quad_t)strtoll(nptr, endptr, base));
155}
156#endif
diff --git a/src/lib/libc/stdlib/strtonum.3 b/src/lib/libc/stdlib/strtonum.3
new file mode 100644
index 0000000000..11910a627c
--- /dev/null
+++ b/src/lib/libc/stdlib/strtonum.3
@@ -0,0 +1,151 @@
1.\" $OpenBSD: strtonum.3,v 1.11 2005/04/14 07:58:46 jmc Exp $
2.\"
3.\" Copyright (c) 2004 Ted Unangst
4.\"
5.\" Permission to use, copy, modify, and distribute this software for any
6.\" purpose with or without fee is hereby granted, provided that the above
7.\" copyright notice and this permission notice appear in all copies.
8.\"
9.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16.\"
17.Dd April 29, 2004
18.Dt STRTONUM 3
19.Os
20.Sh NAME
21.Nm strtonum
22.Nd "reliably convert string value to an integer"
23.Sh SYNOPSIS
24.Fd #include <stdlib.h>
25.Fd #include <limits.h>
26.Ft long long
27.Fo strtonum
28.Fa "const char *nptr"
29.Fa "long long minval"
30.Fa "long long maxval"
31.Fa "const char **errstr"
32.Fc
33.Sh DESCRIPTION
34The
35.Fn strtonum
36function converts the string in
37.Fa nptr
38to a
39.Li long long
40value.
41The
42.Fn strtonum
43function was designed to facilitate safe, robust programming
44and overcome the shortcomings of the
45.Xr atoi 3
46and
47.Xr strtol 3
48family of interfaces.
49.Pp
50The string may begin with an arbitrary amount of whitespace
51(as determined by
52.Xr isspace 3 )
53followed by a single optional
54.Ql +
55or
56.Ql -
57sign.
58.Pp
59The remainder of the string is converted to a
60.Li long long
61value according to base 10.
62.Pp
63The value obtained is then checked against the provided
64.Fa minval
65and
66.Fa maxval
67bounds.
68If
69.Fa errstr
70is non-null,
71.Fn strtonum
72stores an error string in
73.Fa *errstr
74indicating the failure.
75.Sh RETURN VALUES
76The
77.Fn strtonum
78function returns the result of the conversion,
79unless the value would exceed the provided bounds or is invalid.
80On error, 0 is returned and
81.Fa errstr
82will point to an error message.
83.Fa *errstr
84will be set to
85.Dv NULL
86on success;
87this fact can be used to differentiate
88a successful return of 0 from an error.
89.Sh EXAMPLES
90Using
91.Fn strtonum
92correctly is meant to be simpler than the alternative functions.
93.Bd -literal -offset indent
94int iterations;
95const char *errstr;
96
97iterations = strtonum(optarg, 1, 64, &errstr);
98if (errstr)
99 errx(1, "number of iterations is %s: %s", errstr, optarg);
100.Ed
101.Pp
102The above example will guarantee that the value of iterations is between
1031 and 64.
104.Sh ERRORS
105.Bl -tag -width Er
106.It Bq Er ERANGE
107The given string was out of range.
108.It Bq Er EINVAL
109The given string did not consist solely of digit characters.
110.It Bq Er EINVAL
111.Ar minval
112was larger than
113.Ar maxval .
114.El
115.Pp
116If an error occurs,
117.Fa errstr
118will be set to one of the following strings:
119.Pp
120.Bl -tag -width "too largeXX" -compact
121.It too large
122The result was larger than the provided maximum value.
123.It too small
124The result was smaller than the provided minimum value.
125.It invalid
126The string did not consist solely of digit characters.
127.El
128.Sh SEE ALSO
129.Xr atof 3 ,
130.Xr atoi 3 ,
131.Xr atol 3 ,
132.Xr atoll 3 ,
133.Xr sscanf 3 ,
134.Xr strtod 3 ,
135.Xr strtol 3 ,
136.Xr strtoul 3
137.Sh STANDARDS
138.Fn strtonum
139is an
140.Ox
141extension.
142The existing alternatives, such as
143.Xr atoi 3
144and
145.Xr strtol 3 ,
146are either impossible or difficult to use safely.
147.Sh HISTORY
148The
149.Fn strtonum
150function first appeared in
151.Ox 3.6 .
diff --git a/src/lib/libc/stdlib/strtonum.c b/src/lib/libc/stdlib/strtonum.c
new file mode 100644
index 0000000000..e426388ed0
--- /dev/null
+++ b/src/lib/libc/stdlib/strtonum.c
@@ -0,0 +1,65 @@
1/* $OpenBSD: strtonum.c,v 1.6 2004/08/03 19:38:01 millert Exp $ */
2
3/*
4 * Copyright (c) 2004 Ted Unangst and Todd Miller
5 * All rights reserved.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include <errno.h>
21#include <limits.h>
22#include <stdlib.h>
23
24#define INVALID 1
25#define TOOSMALL 2
26#define TOOLARGE 3
27
28long long
29strtonum(const char *numstr, long long minval, long long maxval,
30 const char **errstrp)
31{
32 long long ll = 0;
33 char *ep;
34 int error = 0;
35 struct errval {
36 const char *errstr;
37 int err;
38 } ev[4] = {
39 { NULL, 0 },
40 { "invalid", EINVAL },
41 { "too small", ERANGE },
42 { "too large", ERANGE },
43 };
44
45 ev[0].err = errno;
46 errno = 0;
47 if (minval > maxval)
48 error = INVALID;
49 else {
50 ll = strtoll(numstr, &ep, 10);
51 if (numstr == ep || *ep != '\0')
52 error = INVALID;
53 else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
54 error = TOOSMALL;
55 else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
56 error = TOOLARGE;
57 }
58 if (errstrp != NULL)
59 *errstrp = ev[error].errstr;
60 errno = ev[error].err;
61 if (error)
62 ll = 0;
63
64 return (ll);
65}
diff --git a/src/lib/libc/stdlib/strtoul.3 b/src/lib/libc/stdlib/strtoul.3
new file mode 100644
index 0000000000..4f6d6a51f9
--- /dev/null
+++ b/src/lib/libc/stdlib/strtoul.3
@@ -0,0 +1,231 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" Chris Torek and the American National Standards Committee X3,
6.\" on Information Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: strtoul.3,v 1.15 2003/06/02 20:18:38 millert Exp $
33.\"
34.Dd June 25, 1992
35.Dt STRTOUL 3
36.Os
37.Sh NAME
38.Nm strtoul ,
39.Nm strtoull ,
40.Nm strtouq
41.Nd "convert a string to an unsigned long or unsigned long long integer"
42.Sh SYNOPSIS
43.Fd #include <stdlib.h>
44.Fd #include <limits.h>
45.Ft unsigned long
46.Fn strtoul "const char *nptr" "char **endptr" "int base"
47.Pp
48.Fd #include <stdlib.h>
49.Fd #include <limits.h>
50.Ft unsigned long long
51.Fn strtoull "const char *nptr" "char **endptr" "int base"
52.Pp
53.Fd #include <sys/types.h>
54.Fd #include <stdlib.h>
55.Fd #include <limits.h>
56.Ft u_quad_t
57.Fn strtouq "const char *nptr" "char **endptr" "int base"
58.Sh DESCRIPTION
59The
60.Fn strtoul
61function converts the string in
62.Fa nptr
63to an
64.Li unsigned long
65value.
66The
67.Fn strtoull
68function converts the string in
69.Fa nptr
70to an
71.Li unsigned long long
72value.
73The
74.Fn strtouq
75function is a deprecated equivalent of
76.Fn strtoull
77and is provided for backwards compatibility with legacy programs.
78The conversion is done according to the given
79.Fa base ,
80which must be a number between 2 and 36 inclusive
81or the special value 0.
82If the string in
83.Fa nptr
84represents a negative number, it will be converted to its unsigned equivalent.
85This behavior is consistent with what happens when a signed integer type is
86cast to its unsigned counterpart.
87.Pp
88The string may begin with an arbitrary amount of whitespace
89(as determined by
90.Xr isspace 3 )
91followed by a single optional
92.Ql +
93or
94.Ql -
95sign.
96If
97.Fa base
98is zero or 16, the string may then include a
99.Ql 0x
100prefix, and the number will be read in base 16; otherwise, a zero
101.Fa base
102is taken as 10 (decimal) unless the next character is
103.Ql 0 ,
104in which case it is taken as 8 (octal).
105.Pp
106The remainder of the string is converted to an
107.Li unsigned long
108value in the obvious manner, stopping at the end of the string
109or at the first character that does not produce a valid digit
110in the given base.
111(In bases above 10, the letter
112.Ql A
113in either upper or lower case represents 10,
114.Ql B
115represents 11, and so forth, with
116.Ql Z
117representing 35.)
118.Pp
119If
120.Fa endptr
121is non-null,
122.Fn strtoul
123stores the address of the first invalid character in
124.Fa *endptr .
125If there were no digits at all, however,
126.Fn strtoul
127stores the original value of
128.Fa nptr
129in
130.Fa *endptr .
131(Thus, if
132.Fa *nptr
133is not
134.Ql \e0
135but
136.Fa **endptr
137is
138.Ql \e0
139on return, the entire string was valid.)
140.Sh RETURN VALUES
141The
142.Fn strtoul
143function returns the result of the conversion,
144unless the value would overflow, in which case
145.Dv ULONG_MAX
146is returned and
147.Va errno
148is set to
149.Er ERANGE .
150If there was a leading minus sign,
151.Fn strtoul
152returns the (unsigned) negation of the absolute value of the number, unless
153the absolute value would overflow.
154In this case,
155.Fn strtoul
156returns
157.Dv ULONG_MAX
158and sets the global variable
159.Va errno
160to
161.Er ERANGE .
162.Pp
163The
164.Fn strtoull
165function has identical return values except that
166.Dv ULLONG_MAX
167is used to indicate overflow.
168.Pp
169There is no way to determine if
170.Fn strtoul
171has processed a negative number (and returned an unsigned value) short of
172examining the string in
173.Fa nptr
174directly.
175.Sh EXAMPLES
176Ensuring that a string is a valid number (i.e., in range and containing no
177trailing characters) requires clearing
178.Va errno
179beforehand explicitly since
180.Va errno
181is not changed on a successful call to
182.Fn strtoul ,
183and the return value of
184.Fn strtoul
185cannot be used unambiguously to signal an error:
186.Bd -literal -offset indent
187char *ep;
188unsigned long ulval;
189
190\&...
191
192errno = 0;
193ulval = strtoul(buf, &ep, 10);
194if (buf[0] == '\e0' || *ep != '\e0')
195 goto not_a_number;
196if (errno == ERANGE && ulval == ULONG_MAX)
197 goto out_of_range;
198.Ed
199.Pp
200This example will accept
201.Dq 12
202but not
203.Dq 12foo
204or
205.Dq 12\en .
206If trailing whitespace is acceptable, further checks must be done on
207.Va *ep ;
208alternately, use
209.Xr sscanf 3 .
210.Sh ERRORS
211.Bl -tag -width Er
212.It Bq Er ERANGE
213The given string was out of range; the value converted has been clamped.
214.El
215.Sh SEE ALSO
216.Xr sscanf 3 ,
217.Xr strtol 3
218.Sh STANDARDS
219The
220.Fn strtoul
221and
222.Fn strtoull
223functions conform to
224.St -ansiC-99 .
225The
226.Fn strtouq
227function is a
228.Bx
229extension and is provided for backwards compatibility with legacy programs.
230.Sh BUGS
231Ignores the current locale.
diff --git a/src/lib/libc/stdlib/strtoul.c b/src/lib/libc/stdlib/strtoul.c
new file mode 100644
index 0000000000..1faa0abbd0
--- /dev/null
+++ b/src/lib/libc/stdlib/strtoul.c
@@ -0,0 +1,105 @@
1/*
2 * Copyright (c) 1990 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: strtoul.c,v 1.6 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <ctype.h>
35#include <errno.h>
36#include <limits.h>
37#include <stdlib.h>
38
39/*
40 * Convert a string to an unsigned long integer.
41 *
42 * Ignores `locale' stuff. Assumes that the upper and lower case
43 * alphabets and digits are each contiguous.
44 */
45unsigned long
46strtoul(const char *nptr, char **endptr, int base)
47{
48 const char *s;
49 unsigned long acc, cutoff;
50 int c;
51 int neg, any, cutlim;
52
53 /*
54 * See strtol for comments as to the logic used.
55 */
56 s = nptr;
57 do {
58 c = (unsigned char) *s++;
59 } while (isspace(c));
60 if (c == '-') {
61 neg = 1;
62 c = *s++;
63 } else {
64 neg = 0;
65 if (c == '+')
66 c = *s++;
67 }
68 if ((base == 0 || base == 16) &&
69 c == '0' && (*s == 'x' || *s == 'X')) {
70 c = s[1];
71 s += 2;
72 base = 16;
73 }
74 if (base == 0)
75 base = c == '0' ? 8 : 10;
76
77 cutoff = ULONG_MAX / (unsigned long)base;
78 cutlim = ULONG_MAX % (unsigned long)base;
79 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
80 if (isdigit(c))
81 c -= '0';
82 else if (isalpha(c))
83 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
84 else
85 break;
86 if (c >= base)
87 break;
88 if (any < 0)
89 continue;
90 if (acc > cutoff || acc == cutoff && c > cutlim) {
91 any = -1;
92 acc = ULONG_MAX;
93 errno = ERANGE;
94 } else {
95 any = 1;
96 acc *= (unsigned long)base;
97 acc += c;
98 }
99 }
100 if (neg && any > 0)
101 acc = -acc;
102 if (endptr != 0)
103 *endptr = (char *) (any ? s - 1 : nptr);
104 return (acc);
105}
diff --git a/src/lib/libc/stdlib/strtoull.c b/src/lib/libc/stdlib/strtoull.c
new file mode 100644
index 0000000000..5fa841fff7
--- /dev/null
+++ b/src/lib/libc/stdlib/strtoull.c
@@ -0,0 +1,118 @@
1/*-
2 * Copyright (c) 1992 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static const char rcsid[] = "$OpenBSD: strtoull.c,v 1.4 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35
36#include <ctype.h>
37#include <errno.h>
38#include <limits.h>
39#include <stdlib.h>
40
41/*
42 * Convert a string to an unsigned long long.
43 *
44 * Ignores `locale' stuff. Assumes that the upper and lower case
45 * alphabets and digits are each contiguous.
46 */
47unsigned long long
48strtoull(const char *nptr, char **endptr, int base)
49{
50 const char *s;
51 unsigned long long acc, cutoff;
52 int c;
53 int neg, any, cutlim;
54
55 /*
56 * See strtoq for comments as to the logic used.
57 */
58 s = nptr;
59 do {
60 c = (unsigned char) *s++;
61 } while (isspace(c));
62 if (c == '-') {
63 neg = 1;
64 c = *s++;
65 } else {
66 neg = 0;
67 if (c == '+')
68 c = *s++;
69 }
70 if ((base == 0 || base == 16) &&
71 c == '0' && (*s == 'x' || *s == 'X')) {
72 c = s[1];
73 s += 2;
74 base = 16;
75 }
76 if (base == 0)
77 base = c == '0' ? 8 : 10;
78
79 cutoff = ULLONG_MAX / (unsigned long long)base;
80 cutlim = ULLONG_MAX % (unsigned long long)base;
81 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
82 if (isdigit(c))
83 c -= '0';
84 else if (isalpha(c))
85 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
86 else
87 break;
88 if (c >= base)
89 break;
90 if (any < 0)
91 continue;
92 if (acc > cutoff || (acc == cutoff && c > cutlim)) {
93 any = -1;
94 acc = ULLONG_MAX;
95 errno = ERANGE;
96 } else {
97 any = 1;
98 acc *= (unsigned long long)base;
99 acc += c;
100 }
101 }
102 if (neg && any > 0)
103 acc = -acc;
104 if (endptr != 0)
105 *endptr = (char *) (any ? s - 1 : nptr);
106 return (acc);
107}
108
109#ifdef __weak_alias
110__weak_alias(strtouq, strtoull);
111#else
112u_quad_t
113strtouq(const char *nptr, char **endptr, int base)
114{
115
116 return ((u_quad_t)strtoull(nptr, endptr, base));
117}
118#endif
diff --git a/src/lib/libc/stdlib/system.3 b/src/lib/libc/stdlib/system.3
new file mode 100644
index 0000000000..1034b01066
--- /dev/null
+++ b/src/lib/libc/stdlib/system.3
@@ -0,0 +1,99 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information
6.\" Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: system.3,v 1.9 2003/06/02 20:18:38 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt SYSTEM 3
36.Os
37.Sh NAME
38.Nm system
39.Nd pass a command to the shell
40.Sh SYNOPSIS
41.Fd #include <stdlib.h>
42.Ft int
43.Fn system "const char *string"
44.Sh DESCRIPTION
45The
46.Fn system
47function hands the argument
48.Fa string
49to the command interpreter
50.Xr sh 1 .
51The calling process waits for the shell to finish executing the command,
52ignoring
53.Dv SIGINT
54and
55.Dv SIGQUIT ,
56and blocking
57.Dv SIGCHLD .
58.Pp
59If
60.Fa string
61is
62.Dv NULL ,
63.Fn system
64will return non-zero.
65Otherwise,
66.Fn system
67returns the termination status of the shell in the format specified by
68.Xr waitpid 2 .
69.Sh RETURN VALUES
70If a child process cannot be created, or the termination status of
71the shell cannot be obtained,
72.Fn system
73returns \-1 and sets
74.Va errno
75to indicate the error.
76If execution of the shell fails,
77.Fn system
78returns the termination status for a program that terminates with a call of
79.Fn exit 127 .
80.Sh SEE ALSO
81.Xr sh 1 ,
82.Xr execve 2 ,
83.Xr waitpid 2 ,
84.Xr popen 3
85.Sh STANDARDS
86The
87.Fn system
88function conforms to
89.St -ansiC
90and
91.St -p1003.2-92 .
92.Sh CAVEATS
93Never supply the
94.Fn system
95function with a command containing any part of an unsanitized user-supplied
96string.
97Shell meta-characters present will be honored by the
98.Xr sh 1
99command interpreter.
diff --git a/src/lib/libc/stdlib/system.c b/src/lib/libc/stdlib/system.c
new file mode 100644
index 0000000000..ebf5577674
--- /dev/null
+++ b/src/lib/libc/stdlib/system.c
@@ -0,0 +1,77 @@
1/*
2 * Copyright (c) 1988 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: system.c,v 1.7 2005/03/30 18:51:49 pat Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <sys/types.h>
35#include <sys/wait.h>
36#include <signal.h>
37#include <stdlib.h>
38#include <unistd.h>
39#include <paths.h>
40
41extern char **environ;
42
43int
44system(const char *command)
45{
46 pid_t pid;
47 sig_t intsave, quitsave;
48 sigset_t mask, omask;
49 int pstat;
50 char *argp[] = {"sh", "-c", NULL, NULL};
51
52 if (!command) /* just checking... */
53 return(1);
54
55 argp[2] = (char *)command;
56
57 sigemptyset(&mask);
58 sigaddset(&mask, SIGCHLD);
59 sigprocmask(SIG_BLOCK, &mask, &omask);
60 switch (pid = vfork()) {
61 case -1: /* error */
62 sigprocmask(SIG_SETMASK, &omask, NULL);
63 return(-1);
64 case 0: /* child */
65 sigprocmask(SIG_SETMASK, &omask, NULL);
66 execve(_PATH_BSHELL, argp, environ);
67 _exit(127);
68 }
69
70 intsave = signal(SIGINT, SIG_IGN);
71 quitsave = signal(SIGQUIT, SIG_IGN);
72 pid = waitpid(pid, (int *)&pstat, 0);
73 sigprocmask(SIG_SETMASK, &omask, NULL);
74 (void)signal(SIGINT, intsave);
75 (void)signal(SIGQUIT, quitsave);
76 return (pid == -1 ? -1 : pstat);
77}
diff --git a/src/lib/libc/stdlib/tfind.c b/src/lib/libc/stdlib/tfind.c
new file mode 100644
index 0000000000..ff6bcd742d
--- /dev/null
+++ b/src/lib/libc/stdlib/tfind.c
@@ -0,0 +1,41 @@
1/* $OpenBSD: tfind.c,v 1.5 2005/03/30 18:51:49 pat Exp $ */
2
3/*
4 * Tree search generalized from Knuth (6.2.2) Algorithm T just like
5 * the AT&T man page says.
6 *
7 * The node_t structure is for internal use only, lint doesn't grok it.
8 *
9 * Written by reading the System V Interface Definition, not the code.
10 *
11 * Totally public domain.
12 */
13/*LINTLIBRARY*/
14#include <search.h>
15
16typedef struct node_t
17{
18 char *key;
19 struct node_t *llink, *rlink;
20} node;
21
22/* find a node, or return 0 */
23void *
24tfind(const void *vkey, void * const *vrootp,
25 int (*compar)(const void *, const void *))
26{
27 char *key = (char *)vkey;
28 node **rootp = (node **)vrootp;
29
30 if (rootp == (struct node_t **)0)
31 return ((struct node_t *)0);
32 while (*rootp != (struct node_t *)0) { /* T1: */
33 int r;
34 if ((r = (*compar)(key, (*rootp)->key)) == 0) /* T2: */
35 return (*rootp); /* key found */
36 rootp = (r < 0) ?
37 &(*rootp)->llink : /* T3: follow left branch */
38 &(*rootp)->rlink; /* T4: follow right branch */
39 }
40 return (node *)0;
41}
diff --git a/src/lib/libc/stdlib/tsearch.3 b/src/lib/libc/stdlib/tsearch.3
new file mode 100644
index 0000000000..15d7b84a3a
--- /dev/null
+++ b/src/lib/libc/stdlib/tsearch.3
@@ -0,0 +1,116 @@
1.\" $OpenBSD: tsearch.3,v 1.12 2003/06/17 21:56:24 millert Exp $
2.\"
3.\" Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
4.\"
5.\" Permission to use, copy, modify, and distribute this software for any
6.\" purpose with or without fee is hereby granted, provided that the above
7.\" copyright notice and this permission notice appear in all copies.
8.\"
9.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16.\"
17.Dd June 15, 1997
18.Dt TSEARCH 3
19.Os
20.Sh NAME
21.Nm tsearch ,
22.Nm tfind ,
23.Nm tdelete ,
24.Nm twalk
25.Nd manipulate binary search trees
26.Sh SYNOPSIS
27.Fd #include <search.h>
28.Ft void *
29.Fn tdelete "const void *key" "void **rootp" "int (*compar) (const void *, const void *)"
30.Ft void *
31.Fn tfind "const void *key" "void * const *rootp" "int (*compar) (const void *, const void *)"
32.Ft void *
33.Fn tsearch "const void *key" "void **rootp" "int (*compar) (const void *, const void *)"
34.Ft void
35.Fn twalk "const void *root" "void (*action) (const void *, VISIT, int)"
36.Sh DESCRIPTION
37The
38.Fn tdelete ,
39.Fn tfind ,
40.Fn tsearch ,
41and
42.Fn twalk
43functions manage binary search trees based on algorithms T and D
44from Knuth (6.2.2).
45The comparison function passed in by
46the user has the same style of return values as
47.Xr strcmp 3 .
48.Pp
49.Fn tfind
50searches for the datum matched by the argument
51.Fa key
52in the binary tree rooted at
53.Fa rootp ,
54returning a pointer to the datum if it is found and
55.Dv NULL
56if it is not.
57.Pp
58.Fn tsearch
59is identical to
60.Fn tfind
61except that if no match is found,
62.Fa key
63is inserted into the tree and a pointer to it is returned.
64If
65.Fa rootp
66points to a null value a new binary search tree is created.
67.Pp
68.Fn tdelete
69deletes a node from the specified binary search tree and returns
70a pointer to the parent of the node to be deleted.
71It takes the same arguments as
72.Fn tfind
73and
74.Fn tsearch .
75If the node to be deleted is the root of the binary search tree,
76.Fa rootp
77will be adjusted.
78.Pp
79.Fn twalk
80walks the binary search tree rooted in
81.Fa root
82and calls the function
83.Fa action
84on each node.
85.Fa action
86is called with three arguments: a pointer to the current node,
87a value from the enum
88.Sy "typedef enum { preorder, postorder, endorder, leaf } VISIT;"
89specifying the traversal type, and a node level (where level
90zero is the root of the tree).
91.Sh RETURN VALUES
92The
93.Fn tsearch
94function returns
95.Dv NULL
96if allocation of a new node fails (usually
97due to a lack of free memory).
98.Pp
99.Fn tfind ,
100.Fn tsearch ,
101and
102.Fn tdelete
103return
104.Dv NULL
105if
106.Fa rootp
107is
108.Dv NULL
109or the datum cannot be found.
110.Pp
111The
112.Fn twalk
113function returns no value.
114.Sh SEE ALSO
115.Xr bsearch 3 ,
116.Xr lsearch 3
diff --git a/src/lib/libc/stdlib/tsearch.c b/src/lib/libc/stdlib/tsearch.c
new file mode 100644
index 0000000000..a5d0c2b9b3
--- /dev/null
+++ b/src/lib/libc/stdlib/tsearch.c
@@ -0,0 +1,119 @@
1/* $OpenBSD: tsearch.c,v 1.5 2005/03/30 18:51:49 pat Exp $ */
2
3/*
4 * Tree search generalized from Knuth (6.2.2) Algorithm T just like
5 * the AT&T man page says.
6 *
7 * The node_t structure is for internal use only, lint doesn't grok it.
8 *
9 * Written by reading the System V Interface Definition, not the code.
10 *
11 * Totally public domain.
12 */
13/*LINTLIBRARY*/
14
15#include <search.h>
16#include <stdlib.h>
17
18typedef struct node_t {
19 char *key;
20 struct node_t *left, *right;
21} node;
22
23/* find or insert datum into search tree */
24void *
25tsearch(const void *vkey, void **vrootp,
26 int (*compar)(const void *, const void *))
27{
28 node *q;
29 char *key = (char *)vkey;
30 node **rootp = (node **)vrootp;
31
32 if (rootp == (struct node_t **)0)
33 return ((void *)0);
34 while (*rootp != (struct node_t *)0) { /* Knuth's T1: */
35 int r;
36
37 if ((r = (*compar)(key, (*rootp)->key)) == 0) /* T2: */
38 return ((void *)*rootp); /* we found it! */
39 rootp = (r < 0) ?
40 &(*rootp)->left : /* T3: follow left branch */
41 &(*rootp)->right; /* T4: follow right branch */
42 }
43 q = (node *) malloc(sizeof(node)); /* T5: key not found */
44 if (q != (struct node_t *)0) { /* make new node */
45 *rootp = q; /* link new node to old */
46 q->key = key; /* initialize new node */
47 q->left = q->right = (struct node_t *)0;
48 }
49 return ((void *)q);
50}
51
52/* delete node with given key */
53void *
54tdelete(const void *vkey, void **vrootp,
55 int (*compar)(const void *, const void *))
56{
57 node **rootp = (node **)vrootp;
58 char *key = (char *)vkey;
59 node *p;
60 node *q;
61 node *r;
62 int cmp;
63
64 if (rootp == (struct node_t **)0 || (p = *rootp) == (struct node_t *)0)
65 return ((struct node_t *)0);
66 while ((cmp = (*compar)(key, (*rootp)->key)) != 0) {
67 p = *rootp;
68 rootp = (cmp < 0) ?
69 &(*rootp)->left : /* follow left branch */
70 &(*rootp)->right; /* follow right branch */
71 if (*rootp == (struct node_t *)0)
72 return ((void *)0); /* key not found */
73 }
74 r = (*rootp)->right; /* D1: */
75 if ((q = (*rootp)->left) == (struct node_t *)0) /* Left (struct node_t *)0? */
76 q = r;
77 else if (r != (struct node_t *)0) { /* Right link is null? */
78 if (r->left == (struct node_t *)0) { /* D2: Find successor */
79 r->left = q;
80 q = r;
81 } else { /* D3: Find (struct node_t *)0 link */
82 for (q = r->left; q->left != (struct node_t *)0; q = r->left)
83 r = q;
84 r->left = q->right;
85 q->left = (*rootp)->left;
86 q->right = (*rootp)->right;
87 }
88 }
89 free((struct node_t *) *rootp); /* D4: Free node */
90 *rootp = q; /* link parent to new node */
91 return(p);
92}
93
94/* Walk the nodes of a tree */
95static void
96trecurse(node *root, void (*action)(const void *, VISIT, int), int level)
97{
98 if (root->left == (struct node_t *)0 && root->right == (struct node_t *)0)
99 (*action)(root, leaf, level);
100 else {
101 (*action)(root, preorder, level);
102 if (root->left != (struct node_t *)0)
103 trecurse(root->left, action, level + 1);
104 (*action)(root, postorder, level);
105 if (root->right != (struct node_t *)0)
106 trecurse(root->right, action, level + 1);
107 (*action)(root, endorder, level);
108 }
109}
110
111/* Walk the nodes of a tree */
112void
113twalk(const void *vroot, void (*action)(const void *, VISIT, int))
114{
115 node *root = (node *)vroot;
116
117 if (root != (node *)0 && action != (void (*)(const void *, VISIT, int))0)
118 trecurse(root, action, 0);
119}