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.inc68
-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.c46
-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.c41
-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.c135
-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.c41
-rw-r--r--src/lib/libc/stdlib/atoi.381
-rw-r--r--src/lib/libc/stdlib/atoi.c41
-rw-r--r--src/lib/libc/stdlib/atol.370
-rw-r--r--src/lib/libc/stdlib/atol.c41
-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.c75
-rw-r--r--src/lib/libc/stdlib/calloc.c55
-rw-r--r--src/lib/libc/stdlib/cfree.c45
-rw-r--r--src/lib/libc/stdlib/div.363
-rw-r--r--src/lib/libc/stdlib/div.c75
-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.389
-rw-r--r--src/lib/libc/stdlib/exit.c73
-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.c84
-rw-r--r--src/lib/libc/stdlib/getopt.3340
-rw-r--r--src/lib/libc/stdlib/getopt.c116
-rw-r--r--src/lib/libc/stdlib/getopt_long.3366
-rw-r--r--src/lib/libc/stdlib/getopt_long.c545
-rw-r--r--src/lib/libc/stdlib/getsubopt.3143
-rw-r--r--src/lib/libc/stdlib/getsubopt.c102
-rw-r--r--src/lib/libc/stdlib/heapsort.c179
-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.c46
-rw-r--r--src/lib/libc/stdlib/labs.368
-rw-r--r--src/lib/libc/stdlib/labs.c41
-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.c54
-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.3103
-rw-r--r--src/lib/libc/stdlib/lsearch.c86
-rw-r--r--src/lib/libc/stdlib/malloc.3426
-rw-r--r--src/lib/libc/stdlib/malloc.c1317
-rw-r--r--src/lib/libc/stdlib/memory.365
-rw-r--r--src/lib/libc/stdlib/merge.c343
-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.c54
-rw-r--r--src/lib/libc/stdlib/qabs.356
-rw-r--r--src/lib/libc/stdlib/qabs.c41
-rw-r--r--src/lib/libc/stdlib/qdiv.360
-rw-r--r--src/lib/libc/stdlib/qdiv.c54
-rw-r--r--src/lib/libc/stdlib/qsort.3233
-rw-r--r--src/lib/libc/stdlib/qsort.c171
-rw-r--r--src/lib/libc/stdlib/radixsort.3155
-rw-r--r--src/lib/libc/stdlib/radixsort.c313
-rw-r--r--src/lib/libc/stdlib/rand.398
-rw-r--r--src/lib/libc/stdlib/rand.c61
-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.c430
-rw-r--r--src/lib/libc/stdlib/realpath.3120
-rw-r--r--src/lib/libc/stdlib/realpath.c162
-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.c118
-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.c2528
-rw-r--r--src/lib/libc/stdlib/strtol.3247
-rw-r--r--src/lib/libc/stdlib/strtol.c146
-rw-r--r--src/lib/libc/stdlib/strtoll.c162
-rw-r--r--src/lib/libc/stdlib/strtoul.3231
-rw-r--r--src/lib/libc/stdlib/strtoul.c108
-rw-r--r--src/lib/libc/stdlib/strtoull.c124
-rw-r--r--src/lib/libc/stdlib/system.399
-rw-r--r--src/lib/libc/stdlib/system.c78
-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.c126
96 files changed, 14140 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..ad46094309
--- /dev/null
+++ b/src/lib/libc/stdlib/Makefile.inc
@@ -0,0 +1,68 @@
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 heapsort.c l64a.c llabs.c lsearch.c malloc.c merge.c \
9 multibyte.c putenv.c qsort.c radixsort.c rand.c random.c realpath.c \
10 setenv.c strtod.c strtol.c strtoll.c strtoul.c strtoull.c system.c \
11 tfind.c tsearch.c _rand48.c drand48.c erand48.c jrand48.c lcong48.c \
12 lrand48.c mrand48.c nrand48.c seed48.c srand48.c qabs.c qdiv.c
13
14.if (${MACHINE_ARCH} == "m68k")
15SRCS+= abs.S div.c labs.c ldiv.c
16LSRCS+= abs.c
17.elif (${MACHINE_ARCH} == "i386")
18SRCS+= abs.S div.S labs.S ldiv.S
19LSRCS+= abs.c div.c labs.c ldiv.c
20.elif (${MACHINE_ARCH} == "ns32k")
21SRCS+= abs.S div.c labs.c ldiv.c
22LSRCS+= abs.c
23.elif (${MACHINE_ARCH} == "tahoe")
24SRCS+= abs.S div.c labs.c ldiv.c
25LSRCS+= abs.c
26.elif (${MACHINE_ARCH} == "vax")
27SRCS+= abs.c div.c labs.c ldiv.c
28.elif (${MACHINE_ARCH} == "alpha")
29# XXX should be .S's
30SRCS+= abs.c div.c labs.c ldiv.c
31.else
32SRCS+= abs.c div.c labs.c ldiv.c
33.endif
34
35.if (${MACHINE_ARCH} == "vax") || (${MACHINE_ARCH} == "m68k")
36SRCS+= insque.S remque.S
37.else
38SRCS+= insque.c remque.c
39.endif
40
41MAN+= a64l.3 abort.3 abs.3 alloca.3 atexit.3 atof.3 atoi.3 atol.3 atoll.3 \
42 bsearch.3 div.3 ecvt.3 exit.3 getenv.3 getopt.3 getopt_long.3 \
43 getsubopt.3 insque.3 labs.3 ldiv.3 lsearch.3 malloc.3 memory.3 qabs.3 \
44 qdiv.3 qsort.3 radixsort.3 rand48.3 rand.3 random.3 realpath.3 \
45 strtod.3 strtol.3 strtoul.3 system.3 tsearch.3
46
47MLINKS+=ecvt.3 fcvt.3 ecvt.3 gcvt.3
48MLINKS+=getenv.3 setenv.3 getenv.3 unsetenv.3 getenv.3 putenv.3
49MLINKS+=getopt_long.3 getopt_long_only.3
50MLINKS+=insque.3 remque.3
51MLINKS+=labs.3 llabs.3
52MLINKS+=lsearch.3 lfind.3
53MLINKS+=malloc.3 free.3 malloc.3 realloc.3 malloc.3 calloc.3
54MLINKS+=malloc.3 cfree.3 malloc.3 malloc.conf.5
55MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3
56MLINKS+=radixsort.3 sradixsort.3
57MLINKS+=rand.3 srand.3 rand.3 rand_r.3
58MLINKS+=random.3 initstate.3 random.3 setstate.3
59MLINKS+=random.3 srandom.3 random.3 srandomdev.3
60MLINKS+=rand48.3 drand48.3 rand48.3 erand48.3 rand48.3 lrand48.3
61MLINKS+=rand48.3 mrand48.3 rand48.3 nrand48.3 rand48.3 jrand48.3
62MLINKS+=rand48.3 srand48.3 rand48.3 seed48.3 rand48.3 lcong48.3
63MLINKS+=strtol.3 strtoll.3 strtol.3 strtoq.3
64MLINKS+=strtoul.3 strtoull.3 strtoul.3 strtouq.3
65MLINKS+=tsearch.3 tfind.3
66MLINKS+=tsearch.3 tdelete.3
67MLINKS+=tsearch.3 twalk.3
68MLINKS+=a64l.3 l64a.3
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..de70d0af71
--- /dev/null
+++ b/src/lib/libc/stdlib/a64l.3
@@ -0,0 +1,133 @@
1.\" $OpenBSD: a64l.3,v 1.8 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 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 null-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..a68f0a6dcd
--- /dev/null
+++ b/src/lib/libc/stdlib/a64l.c
@@ -0,0 +1,46 @@
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.3 1997/08/17 22:58:34 millert Exp $";
8#endif /* LIBC_SCCS and not lint */
9
10#include <errno.h>
11#include <stdlib.h>
12
13long
14a64l(s)
15 const char *s;
16{
17 long value, digit, shift;
18 int i;
19
20 if (s == NULL) {
21 errno = EINVAL;
22 return(-1L);
23 }
24
25 value = 0;
26 shift = 0;
27 for (i = 0; *s && i < 6; i++, s++) {
28 if (*s >= '.' && *s <= '/')
29 digit = *s - '.';
30 else if (*s >= '0' && *s <= '9')
31 digit = *s - '0' + 2;
32 else if (*s >= 'A' && *s <= 'Z')
33 digit = *s - 'A' + 12;
34 else if (*s >= 'a' && *s <= 'z')
35 digit = *s - 'a' + 38;
36 else {
37 errno = EINVAL;
38 return(-1L);
39 }
40
41 value |= digit << shift;
42 shift += 6;
43 }
44
45 return(value);
46}
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..3f32dc5dc1
--- /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.12 2003/06/02 20:18:37 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()
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..c67ad9494f
--- /dev/null
+++ b/src/lib/libc/stdlib/abs.c
@@ -0,0 +1,41 @@
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.3 2003/06/02 20:18:37 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35
36int
37abs(j)
38 int j;
39{
40 return(j < 0 ? -j : j);
41}
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..98564d0dd3
--- /dev/null
+++ b/src/lib/libc/stdlib/atexit.c
@@ -0,0 +1,135 @@
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.7 2002/09/14 22:03:14 dhartmei 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(fn)
63 void (*fn)();
64{
65 register struct atexit *p = __atexit;
66 register int pgsize = getpagesize();
67
68 if (pgsize < sizeof(*p))
69 return (-1);
70 if (p != NULL) {
71 if (p->ind + 1 >= p->max)
72 p = NULL;
73 else if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
74 return (-1);
75 }
76 if (p == NULL) {
77 if (__atexit_invalid) {
78 free(malloc(1));
79 __atexit_invalid = 0;
80 }
81 p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
82 MAP_ANON | MAP_PRIVATE, -1, 0);
83 if (p == MAP_FAILED)
84 return (-1);
85 if (__atexit == NULL) {
86 p->fns[0] = NULL;
87 p->ind = 1;
88 } else
89 p->ind = 0;
90 p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
91 sizeof(p->fns[0]);
92 p->next = __atexit;
93 __atexit = p;
94 }
95 p->fns[p->ind++] = fn;
96 if (mprotect(p, pgsize, PROT_READ))
97 return (-1);
98 return (0);
99}
100
101/*
102 * Register the cleanup function
103 */
104void
105__atexit_register_cleanup(fn)
106 void (*fn)();
107{
108 register struct atexit *p = __atexit;
109 register int pgsize = getpagesize();
110
111 if (pgsize < sizeof(*p))
112 return;
113 while (p != NULL && p->next != NULL)
114 p = p->next;
115 if (p == NULL) {
116 if (__atexit_invalid) {
117 free(malloc(1));
118 __atexit_invalid = 0;
119 }
120 p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
121 MAP_ANON | MAP_PRIVATE, -1, 0);
122 if (p == MAP_FAILED)
123 return;
124 p->ind = 1;
125 p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
126 sizeof(p->fns[0]);
127 p->next = NULL;
128 __atexit = p;
129 } else {
130 if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
131 return;
132 }
133 p->fns[0] = fn;
134 mprotect(p, pgsize, PROT_READ);
135}
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..dad2b77bfd
--- /dev/null
+++ b/src/lib/libc/stdlib/atof.c
@@ -0,0 +1,41 @@
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.3 2003/06/02 20:18:37 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35
36double
37atof(ascii)
38 const char *ascii;
39{
40 return(strtod(ascii, (char **)NULL));
41}
diff --git a/src/lib/libc/stdlib/atoi.3 b/src/lib/libc/stdlib/atoi.3
new file mode 100644
index 0000000000..070344a810
--- /dev/null
+++ b/src/lib/libc/stdlib/atoi.3
@@ -0,0 +1,81 @@
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.7 2003/06/02 20:18:37 millert 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 strtoul 3
65.Sh STANDARDS
66The
67.Fn atoi
68function conforms to
69.St -ansiC .
70.Sh CAVEATS
71.Nm
72does no overflow checking, handles unsigned numbers poorly,
73and handles strings containing trailing extra characters
74(like
75.Dq "123abc" )
76poorly.
77Careful use of
78.Xr strtol 3
79and
80.Xr strtoul 3
81can alleviate these problems.
diff --git a/src/lib/libc/stdlib/atoi.c b/src/lib/libc/stdlib/atoi.c
new file mode 100644
index 0000000000..b1fe789fd5
--- /dev/null
+++ b/src/lib/libc/stdlib/atoi.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: atoi.c,v 1.3 2003/06/02 20:18:37 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35
36int
37atoi(str)
38 const char *str;
39{
40 return((int)strtol(str, (char **)NULL, 10));
41}
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..83adad3eae
--- /dev/null
+++ b/src/lib/libc/stdlib/atol.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: atol.c,v 1.3 2003/06/02 20:18:37 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35
36long
37atol(str)
38 const char *str;
39{
40 return(strtol(str, (char **)NULL, 10));
41}
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..9bfbf64256
--- /dev/null
+++ b/src/lib/libc/stdlib/bsearch.c
@@ -0,0 +1,75 @@
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.4 2003/06/02 20:18:37 millert 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(key, base0, nmemb, size, compar)
54 register const void *key;
55 const void *base0;
56 size_t nmemb;
57 register size_t size;
58 register int (*compar)(const void *, const void *);
59{
60 register const char *base = base0;
61 register int lim, cmp;
62 register const void *p;
63
64 for (lim = nmemb; lim != 0; lim >>= 1) {
65 p = base + (lim >> 1) * size;
66 cmp = (*compar)(key, p);
67 if (cmp == 0)
68 return ((void *)p);
69 if (cmp > 0) { /* key > p: move right */
70 base = (char *)p + size;
71 lim--;
72 } /* else move left */
73 }
74 return (NULL);
75}
diff --git a/src/lib/libc/stdlib/calloc.c b/src/lib/libc/stdlib/calloc.c
new file mode 100644
index 0000000000..b0703cc884
--- /dev/null
+++ b/src/lib/libc/stdlib/calloc.c
@@ -0,0 +1,55 @@
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.8 2003/06/02 20:18:37 millert 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(num, size)
41 size_t num;
42 register size_t size;
43{
44 register void *p;
45
46 if (num && size && SIZE_T_MAX / num < size) {
47 errno = ENOMEM;
48 return NULL;
49 }
50 size *= num;
51 p = malloc(size);
52 if (p)
53 memset(p, 0, size);
54 return(p);
55}
diff --git a/src/lib/libc/stdlib/cfree.c b/src/lib/libc/stdlib/cfree.c
new file mode 100644
index 0000000000..ecbc11d6c3
--- /dev/null
+++ b/src/lib/libc/stdlib/cfree.c
@@ -0,0 +1,45 @@
1/* $OpenBSD: cfree.c,v 1.3 2003/07/18 23:05:13 david 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.3 2003/07/18 23:05:13 david 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(p)
41 void *p;
42{
43 free(p);
44}
45#endif
diff --git a/src/lib/libc/stdlib/div.3 b/src/lib/libc/stdlib/div.3
new file mode 100644
index 0000000000..460ab53137
--- /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.6 2003/06/02 20:18:37 millert 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 No / 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..9e070dcd64
--- /dev/null
+++ b/src/lib/libc/stdlib/div.c
@@ -0,0 +1,75 @@
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.3 2003/06/02 20:18:37 millert Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37#include <stdlib.h> /* div_t */
38
39div_t
40div(num, denom)
41 int num, denom;
42{
43 div_t r;
44
45 r.quot = num / denom;
46 r.rem = num % denom;
47 /*
48 * The ANSI standard says that |r.quot| <= |n/d|, where
49 * n/d is to be computed in infinite precision. In other
50 * words, we should always truncate the quotient towards
51 * 0, never -infinity.
52 *
53 * Machine division and remainer may work either way when
54 * one or both of n or d is negative. If only one is
55 * negative and r.quot has been truncated towards -inf,
56 * r.rem will have the same sign as denom and the opposite
57 * sign of num; if both are negative and r.quot has been
58 * truncated towards -inf, r.rem will be positive (will
59 * have the opposite sign of num). These are considered
60 * `wrong'.
61 *
62 * If both are num and denom are positive, r will always
63 * be positive.
64 *
65 * This all boils down to:
66 * if num >= 0, but r.rem < 0, we got the wrong answer.
67 * In that case, to get the right answer, add 1 to r.quot and
68 * subtract denom from r.rem.
69 */
70 if (num >= 0 && r.rem < 0) {
71 r.quot++;
72 r.rem -= denom;
73 }
74 return (r);
75}
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..da48a33957
--- /dev/null
+++ b/src/lib/libc/stdlib/ecvt.3
@@ -0,0 +1,165 @@
1.\" $OpenBSD: ecvt.3,v 1.6 2003/06/17 21:56:24 millert 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-01 .
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..8c4b2eed2c
--- /dev/null
+++ b/src/lib/libc/stdlib/exit.3
@@ -0,0 +1,89 @@
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.9 2003/06/02 20:18:37 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt EXIT 3
36.Os
37.Sh NAME
38.Nm exit
39.Nd perform normal program termination
40.Sh SYNOPSIS
41.Fd #include <stdlib.h>
42.Ft void
43.Fn exit "int status"
44.Sh DESCRIPTION
45The
46.Fn exit
47function terminates a process.
48.Pp
49Before termination it performs the following functions in the
50order listed:
51.Bl -enum -offset indent
52.It
53Call the functions registered with the
54.Xr atexit 3
55function, in the reverse order of their registration.
56.It
57Flush all open output streams.
58.It
59Close all open streams.
60.It
61Unlink all files created with the
62.Xr tmpfile 3
63function.
64.El
65.Pp
66Following this,
67.Fn exit
68calls
69.Xr _exit 2 .
70Note that typically
71.Xr _exit 2
72only passes the lower 8 bits of
73.Fa status
74on to the parent, thus negative values have less meaning.
75.Sh RETURN VALUES
76The
77.Fn exit
78function never returns.
79.Sh SEE ALSO
80.Xr _exit 2 ,
81.Xr atexit 3 ,
82.Xr intro 3 ,
83.Xr sysexits 3 ,
84.Xr tmpfile 3
85.Sh STANDARDS
86The
87.Fn exit
88function conforms to
89.St -ansiC .
diff --git a/src/lib/libc/stdlib/exit.c b/src/lib/libc/stdlib/exit.c
new file mode 100644
index 0000000000..a75b32abeb
--- /dev/null
+++ b/src/lib/libc/stdlib/exit.c
@@ -0,0 +1,73 @@
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.9 2003/06/02 20:18:37 millert 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(status)
55 int status;
56{
57 register struct atexit *p, *q;
58 register int n, pgsize = getpagesize();
59
60 if (!__atexit_invalid) {
61 p = __atexit;
62 while (p != NULL) {
63 for (n = p->ind; --n >= 0;)
64 if (p->fns[n] != NULL)
65 (*p->fns[n])();
66 q = p;
67 p = p->next;
68 munmap(q, pgsize);
69 }
70 }
71 /* cleanup, if registered, was called through fns[0] in the last page */
72 _exit(status);
73}
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..25c325307d
--- /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.8 2003/06/02 20:18:37 millert 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 No = 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..c597e468a9
--- /dev/null
+++ b/src/lib/libc/stdlib/getenv.c
@@ -0,0 +1,84 @@
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.6 2003/06/02 20:18:37 millert 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 register int len, i;
53 register const char *np;
54 register 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(name)
79 const char *name;
80{
81 int offset;
82
83 return (__findenv(name, &offset));
84}
diff --git a/src/lib/libc/stdlib/getopt.3 b/src/lib/libc/stdlib/getopt.3
new file mode 100644
index 0000000000..d210852c6b
--- /dev/null
+++ b/src/lib/libc/stdlib/getopt.3
@@ -0,0 +1,340 @@
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.28 2003/09/22 23:47:26 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 optind;
40.Vt extern int optopt;
41.Vt extern int opterr;
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
66.Px .
67For example, an option string
68.Qq x
69recognizes an option
70.Fl x ,
71and an option string
72.Qq Li x:
73recognizes an option and argument
74.Fl x Ar argument .
75It does not matter to
76.Fn getopt
77if a following argument has leading whitespace.
78.Pp
79On return from
80.Fn getopt ,
81.Va optarg
82points to an option argument, if it is anticipated,
83and the variable
84.Va optind
85contains the index to the next
86.Fa argv
87argument for a subsequent call
88to
89.Fn getopt .
90.Pp
91The variables
92.Va opterr
93and
94.Va optind
95are both initialized to 1.
96The
97.Va optind
98variable may be set to another value before a set of calls to
99.Fn getopt
100in order to skip over more or less argv entries.
101.Pp
102In order to use
103.Fn getopt
104to evaluate multiple sets of arguments, or to evaluate a single set of
105arguments multiple times,
106the variable
107.Va optreset
108must be set to 1 before the second and each additional set of calls to
109.Fn getopt ,
110and the variable
111.Va optind
112must be reinitialized.
113.Pp
114The
115.Fn getopt
116function returns \-1 when the argument list is exhausted.
117The interpretation of options in the argument list may be cancelled
118by the option
119.Ql --
120(double dash) which causes
121.Fn getopt
122to signal the end of argument processing and return \-1.
123When all options have been processed (i.e., up to the first non-option
124argument),
125.Fn getopt
126returns \-1.
127.Sh RETURN VALUES
128The
129.Fn getopt
130function returns the next known option character in
131.Fa optstring .
132If
133.Fn getopt
134encounters a character not found in
135.Fa optstring
136or if it detects a missing option argument,
137it returns
138.Sq \&?
139(question mark).
140If
141.Fa optstring
142has a leading
143.Sq \&:
144then a missing option argument causes
145.Sq \&:
146to be returned instead of
147.Sq \&? .
148In either case, the variable
149.Va optopt
150is set to the character that caused the error.
151The
152.Fn getopt
153function returns \-1 when the argument list is exhausted.
154.Sh ENVIRONMENT
155.Bl -tag -width POSIXLY_CORRECTXX
156.It Ev POSIXLY_CORRECT
157If set, a leading
158.Sq -
159in
160.Ar optstring
161is ignored.
162.El
163.Sh EXAMPLES
164.Bd -literal -compact
165extern char *optarg;
166extern int optind;
167int bflag, ch, fd;
168
169bflag = 0;
170while ((ch = getopt(argc, argv, "bf:")) != -1) {
171 switch (ch) {
172 case 'b':
173 bflag = 1;
174 break;
175 case 'f':
176 if ((fd = open(optarg, O_RDONLY, 0)) < 0) {
177 (void)fprintf(stderr,
178 "myname: %s: %s\en", optarg, strerror(errno));
179 exit(1);
180 }
181 break;
182 case '?':
183 default:
184 usage();
185 }
186}
187argc -= optind;
188argv += optind;
189.Ed
190.Sh DIAGNOSTICS
191If the
192.Fn getopt
193function encounters a character not found in the string
194.Fa optstring
195or detects
196a missing option argument it writes an error message to
197.Em stderr
198and returns
199.Ql \&? .
200Setting
201.Va opterr
202to a zero will disable these error messages.
203If
204.Fa optstring
205has a leading
206.Ql \&:
207then a missing option argument causes a
208.Ql \&:
209to be returned in addition to suppressing any error messages.
210.Pp
211Option arguments are allowed to begin with
212.Ql - ;
213this is reasonable but reduces the amount of error checking possible.
214.Sh SEE ALSO
215.Xr getopt 1 ,
216.Xr getopt_long 3 ,
217.Xr getsubopt 3
218.Sh STANDARDS
219The
220.Fn getopt
221function implements a superset of the functionality specified by
222.St -p1003.1 .
223.Pp
224The following extensions are supported:
225.Bl -tag -width "xxx"
226.It Li o
227The
228.Va optreset
229variable was added to make it possible to call the
230.Fn getopt
231function multiple times.
232.It Li o
233If the first character of
234.Fa optstring
235is a plus sign
236.Pq Ql + ,
237it will be ignored.
238This is for compatibility with
239.Tn GNU
240.Fn getopt .
241.It Li o
242If the first character of
243.Fa optstring
244is a dash
245.Pq Ql - ,
246non-options will be returned as arguments to the option character
247.Ql \e1 .
248This is for compatibility with
249.Tn GNU
250.Fn getopt .
251.It Li o
252A single dash
253.Pq Ql -
254may be specified as a character in
255.Fa optstring ,
256however it should
257.Em never
258have an argument associated with it.
259This allows
260.Fn getopt
261to be used with programs that expect
262.Ql -
263as an option flag.
264This practice is wrong, and should not be used in any current development.
265It is provided for backward compatibility
266.Em only .
267Care should be taken not to use
268.Ql -
269as the first character in
270.Fa optstring
271to avoid a semantic conflict with
272.Tn GNU
273.Fn getopt
274semantics (see above).
275By default, a single dash causes
276.Fn getopt
277to return \-1.
278.El
279.Pp
280Unlike
281.Tn GNU
282.Fn getopt ,
283.Ox
284does not permute the argument vector to allow non-options to be
285interspersed with options on the command line.
286Programs requiring this behavior should use
287.Xr getopt_long 3
288instead.
289Because of this (and unlike
290.Tn GNU ) ,
291the
292.Ox
293.Fn getopt
294supports optional arguments separated by whitespace.
295.Sh HISTORY
296The
297.Fn getopt
298function appeared in
299.Bx 4.3 .
300.Sh BUGS
301The
302.Fn getopt
303function was once specified to return
304.Dv EOF
305instead of \-1.
306This was changed by
307.St -p1003.2-92
308to decouple
309.Fn getopt
310from
311.Aq Pa stdio.h .
312.Pp
313It is possible to handle digits as option letters.
314This allows
315.Fn getopt
316to be used with programs that expect a number
317.Pq Dq Li \-3
318as an option.
319This practice is wrong, and should not be used in any current development.
320It is provided for backward compatibility
321.Em only .
322The following code fragment works in most cases.
323.Bd -literal -offset indent
324int ch;
325long length;
326char *p;
327
328while ((ch = getopt(argc, argv, "0123456789")) != -1) {
329 switch (ch) {
330 case '0': case '1': case '2': case '3': case '4':
331 case '5': case '6': case '7': case '8': case '9':
332 p = argv[optind - 1];
333 if (p[0] == '-' && p[1] == ch && !p[2])
334 length = ch - '0';
335 else
336 length = strtol(argv[optind] + 1, NULL, 10);
337 break;
338 }
339}
340.Ed
diff --git a/src/lib/libc/stdlib/getopt.c b/src/lib/libc/stdlib/getopt.c
new file mode 100644
index 0000000000..ee75f9d2ef
--- /dev/null
+++ b/src/lib/libc/stdlib/getopt.c
@@ -0,0 +1,116 @@
1/*
2 * Copyright (c) 1987, 1993, 1994
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: getopt.c,v 1.5 2003/06/02 20:18:37 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37
38int opterr = 1, /* if error message should be printed */
39 optind = 1, /* index into parent argv vector */
40 optopt, /* character checked for validity */
41 optreset; /* reset getopt */
42char *optarg; /* argument associated with option */
43
44#define BADCH (int)'?'
45#define BADARG (int)':'
46#define EMSG ""
47
48/*
49 * getopt --
50 * Parse argc/argv argument vector.
51 */
52int
53getopt(nargc, nargv, ostr)
54 int nargc;
55 char * const *nargv;
56 const char *ostr;
57{
58 extern char *__progname;
59 static char *place = EMSG; /* option letter processing */
60 char *oli; /* option letter list index */
61
62 if (ostr == NULL)
63 return (-1);
64
65 if (optreset || !*place) { /* update scanning pointer */
66 optreset = 0;
67 if (optind >= nargc || *(place = nargv[optind]) != '-') {
68 place = EMSG;
69 return (-1);
70 }
71 if (place[1] && *++place == '-') { /* found "--" */
72 ++optind;
73 place = EMSG;
74 return (-1);
75 }
76 } /* option letter okay? */
77 if ((optopt = (int)*place++) == (int)':' ||
78 !(oli = strchr(ostr, optopt))) {
79 /*
80 * if the user didn't specify '-' as an option,
81 * assume it means -1.
82 */
83 if (optopt == (int)'-')
84 return (-1);
85 if (!*place)
86 ++optind;
87 if (opterr && *ostr != ':')
88 (void)fprintf(stderr,
89 "%s: illegal option -- %c\n", __progname, optopt);
90 return (BADCH);
91 }
92 if (*++oli != ':') { /* don't need argument */
93 optarg = NULL;
94 if (!*place)
95 ++optind;
96 }
97 else { /* need an argument */
98 if (*place) /* no white space */
99 optarg = place;
100 else if (nargc <= ++optind) { /* no arg */
101 place = EMSG;
102 if (*ostr == ':')
103 return (BADARG);
104 if (opterr)
105 (void)fprintf(stderr,
106 "%s: option requires an argument -- %c\n",
107 __progname, optopt);
108 return (BADCH);
109 }
110 else /* white space */
111 optarg = nargv[optind];
112 place = EMSG;
113 ++optind;
114 }
115 return (optopt); /* dump back option letter */
116}
diff --git a/src/lib/libc/stdlib/getopt_long.3 b/src/lib/libc/stdlib/getopt_long.3
new file mode 100644
index 0000000000..6226dfe99f
--- /dev/null
+++ b/src/lib/libc/stdlib/getopt_long.3
@@ -0,0 +1,366 @@
1.\" $OpenBSD: getopt_long.3,v 1.9 2003/09/02 18:24:21 jmc 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 *index"
49.Ft int
50.Fn getopt_long_only "int argc" "char * const *argv" "const char *optstring" "const struct option *longopts" "int *index"
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
150The
151.Fn getopt_long_only
152function behaves identically to
153.Fn getopt_long
154with the exception that long options may start with
155.Sq -
156in addition to
157.Sq -- .
158If an option starting with
159.Sq -
160does not match a long option but does match a single-character option,
161the single-character option is returned.
162.Sh RETURN VALUES
163If the
164.Fa flag
165field in
166.Li struct option
167is
168.Dv NULL ,
169.Fn getopt_long
170and
171.Fn getopt_long_only
172return the value specified in the
173.Fa val
174field, which is usually just the corresponding short option.
175If
176.Fa flag
177is not
178.Dv NULL ,
179these functions return 0 and store
180.Fa val
181in the location pointed to by
182.Fa flag .
183These functions return
184.Sq \:
185if there was a missing option argument,
186.Sq \&?
187if the user specified an unknown or ambiguous option, and
188\-1 when the argument list has been exhausted.
189.Sh EXAMPLES
190.Bd -literal -compact
191int bflag, ch, fd;
192int daggerset;
193
194/* options descriptor */
195static struct option longopts[] = {
196 { "buffy", no_argument, 0, 'b' },
197 { "fluoride", required_argument, 0, 'f' },
198 { "daggerset", no_argument, &daggerset, 1 },
199 { 0, 0, 0, 0 }
200};
201
202bflag = 0;
203while ((ch = getopt_long(argc, argv, "bf:", longopts, NULL)) != -1)
204 switch(ch) {
205 case 'b':
206 bflag = 1;
207 break;
208 case 'f':
209 if ((fd = open(optarg, O_RDONLY, 0)) == -1)
210 err(1, "unable to open %s", optarg);
211 break;
212 case 0:
213 if (daggerset) {
214 fprintf(stderr,"Buffy will use her dagger to "
215 "apply fluoride to dracula's teeth\en");
216 }
217 break;
218 case '?':
219 default:
220 usage();
221}
222argc -= optind;
223argv += optind;
224.Ed
225.Sh IMPLEMENTATION DIFFERENCES
226This section describes differences to the GNU implementation
227found in glibc-2.1.3:
228.Bl -tag -width "xxx"
229.It Li o
230handling of - as first char of option string in presence of
231environment variable POSIXLY_CORRECT:
232.Bl -tag -width "OpenBSD"
233.It Li GNU
234ignores POSIXLY_CORRECT and returns non-options as
235arguments to option '\e1'.
236.It Li OpenBSD
237honors POSIXLY_CORRECT and stops at the first non-option.
238.El
239.It Li o
240handling of - within the option string (not the first character):
241.Bl -tag -width "OpenBSD"
242.It Li GNU
243treats a
244.Ql -
245on the command line as a non-argument.
246.It Li OpenBSD
247a
248.Ql -
249within the option string matches a
250.Ql -
251(single dash) on the command line.
252This functionality is provided for backward compatibility with
253programs, such as
254.Xr su 1 ,
255that use
256.Ql -
257as an option flag.
258This practice is wrong, and should not be used in any current development.
259.El
260.It Li o
261handling of :: in options string in presence of POSIXLY_CORRECT:
262.Bl -tag -width "OpenBSD"
263.It Li Both
264GNU and OpenBSD ignore POSIXLY_CORRECT here and take :: to
265mean the preceding option takes an optional argument.
266.El
267.It Li o
268return value in case of missing argument if first character
269(after + or -) in option string is not ':':
270.Bl -tag -width "OpenBSD"
271.It Li GNU
272returns '?'
273.It OpenBSD
274returns ':' (since OpenBSD's getopt does).
275.El
276.It Li o
277handling of --a in getopt:
278.Bl -tag -width "OpenBSD"
279.It Li GNU
280parses this as option '-', option 'a'.
281.It Li OpenBSD
282parses this as '--', and returns \-1 (ignoring the a).
283(Because the original getopt does.)
284.El
285.It Li o
286setting of optopt for long options with flag !=
287.Dv NULL :
288.Bl -tag -width "OpenBSD"
289.It Li GNU
290sets optopt to val.
291.It Li OpenBSD
292sets optopt to 0 (since val would never be returned).
293.El
294.It Li o
295handling of -W with W; in option string in getopt (not getopt_long):
296.Bl -tag -width "OpenBSD"
297.It Li GNU
298causes a segfault.
299.It Li OpenBSD
300no special handling is done;
301.Dq W;
302is interpreted as two separate options, neither of which take an argument.
303.El
304.It Li o
305setting of optarg for long options without an argument that are
306invoked via -W (W; in option string):
307.Bl -tag -width "OpenBSD"
308.It Li GNU
309sets optarg to the option name (the argument of -W).
310.It Li OpenBSD
311sets optarg to
312.Dv NULL
313(the argument of the long option).
314.El
315.It Li o
316handling of -W with an argument that is not (a prefix to) a known
317long option (W; in option string):
318.Bl -tag -width "OpenBSD"
319.It Li GNU
320returns -W with optarg set to the unknown option.
321.It Li OpenBSD
322treats this as an error (unknown option) and returns '?' with
323optopt set to 0 and optarg set to
324.Dv NULL
325(as GNU's man page documents).
326.El
327.It Li o
328The error messages are different.
329.It Li o
330OpenBSD does not permute the argument vector at the same points in
331the calling sequence as GNU does.
332The aspects normally used by the caller
333(ordering after \-1 is returned, value of optind relative
334to current positions) are the same, though.
335(We do fewer variable swaps.)
336.El
337.Sh ENVIRONMENT
338.Bl -tag -width POSIXLY_CORRECT
339.It Ev POSIXLY_CORRECT
340If set, option processing stops when the first non-option is found and
341a leading
342.Sq -
343or
344.Sq +
345in the
346.Ar optstring
347is ignored.
348.El
349.Sh SEE ALSO
350.Xr getopt 3
351.Sh HISTORY
352The
353.Fn getopt_long
354and
355.Fn getopt_long_only
356functions first appeared in GNU libiberty.
357This implementation first appeared in
358.Ox 3.3 .
359.Sh BUGS
360The
361.Ar argv
362argument is not really
363.Dv const
364as its elements may be permuted (unless
365.Ev POSIXLY_CORRECT
366is 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..1f7f5baa8b
--- /dev/null
+++ b/src/lib/libc/stdlib/getopt_long.c
@@ -0,0 +1,545 @@
1/* $OpenBSD: getopt_long.c,v 1.15 2003/09/22 23:45:22 millert 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.15 2003/09/22 23:45:22 millert 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 * Check for "--" or "--foo" with no long options
383 * but if place is simply "-" leave it unmolested.
384 */
385 if (place[1] != '\0' && *++place == '-' &&
386 (place[1] == '\0' || long_options == NULL)) {
387 optind++;
388 place = EMSG;
389 /*
390 * We found an option (--), so if we skipped
391 * non-options, we have to permute.
392 */
393 if (nonopt_end != -1) {
394 permute_args(nonopt_start, nonopt_end,
395 optind, nargv);
396 optind -= nonopt_end - nonopt_start;
397 }
398 nonopt_start = nonopt_end = -1;
399 return (-1);
400 }
401 }
402
403 /*
404 * Check long options if:
405 * 1) we were passed some
406 * 2) the arg is not just "-"
407 * 3) either the arg starts with -- we are getopt_long_only()
408 */
409 if (long_options != NULL && place != nargv[optind] &&
410 (*place == '-' || (flags & FLAG_LONGONLY))) {
411 short_too = 0;
412 if (*place == '-')
413 place++; /* --foo long option */
414 else if (*place != ':' && strchr(options, *place) != NULL)
415 short_too = 1; /* could be short option too */
416
417 optchar = parse_long_options(nargv, options, long_options,
418 idx, short_too);
419 if (optchar != -1) {
420 place = EMSG;
421 return (optchar);
422 }
423 }
424
425 if ((optchar = (int)*place++) == (int)':' ||
426 (oli = strchr(options, optchar)) == NULL) {
427 /*
428 * If the user didn't specify '-' as an option,
429 * assume it means -1 as POSIX specifies.
430 */
431 if (optchar == (int)'-')
432 return (-1);
433 /* option letter unknown or ':' */
434 if (!*place)
435 ++optind;
436 if (PRINT_ERROR)
437 warnx(illoptchar, optchar);
438 optopt = optchar;
439 return (BADCH);
440 }
441 if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
442 /* -W long-option */
443 if (*place) /* no space */
444 /* NOTHING */;
445 else if (++optind >= nargc) { /* no arg */
446 place = EMSG;
447 if (PRINT_ERROR)
448 warnx(recargchar, optchar);
449 optopt = optchar;
450 return (BADARG);
451 } else /* white space */
452 place = nargv[optind];
453 optchar = parse_long_options(nargv, options, long_options,
454 idx, 0);
455 place = EMSG;
456 return (optchar);
457 }
458 if (*++oli != ':') { /* doesn't take argument */
459 if (!*place)
460 ++optind;
461 } else { /* takes (optional) argument */
462 optarg = NULL;
463 if (*place) /* no white space */
464 optarg = place;
465 /* XXX: disable test for :: if PC? (GNU doesn't) */
466 else if (oli[1] != ':') { /* arg not optional */
467 if (++optind >= nargc) { /* no arg */
468 place = EMSG;
469 if (PRINT_ERROR)
470 warnx(recargchar, optchar);
471 optopt = optchar;
472 return (BADARG);
473 } else
474 optarg = nargv[optind];
475 } else if (!(flags & FLAG_PERMUTE)) {
476 /*
477 * If permutation is disabled, we can accept an
478 * optional arg separated by whitespace.
479 */
480 if (optind + 1 < nargc)
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(nargc, nargv, options, long_options, idx)
519 int nargc;
520 char * const *nargv;
521 const char *options;
522 const struct option *long_options;
523 int *idx;
524{
525
526 return (getopt_internal(nargc, nargv, options, long_options, idx,
527 FLAG_PERMUTE));
528}
529
530/*
531 * getopt_long_only --
532 * Parse argc/argv argument vector.
533 */
534int
535getopt_long_only(nargc, nargv, options, long_options, idx)
536 int nargc;
537 char * const *nargv;
538 const char *options;
539 const struct option *long_options;
540 int *idx;
541{
542
543 return (getopt_internal(nargc, nargv, options, long_options, idx,
544 FLAG_PERMUTE|FLAG_LONGONLY));
545}
diff --git a/src/lib/libc/stdlib/getsubopt.3 b/src/lib/libc/stdlib/getsubopt.3
new file mode 100644
index 0000000000..83530653d2
--- /dev/null
+++ b/src/lib/libc/stdlib/getsubopt.3
@@ -0,0 +1,143 @@
1.\" $OpenBSD: getsubopt.3,v 1.7 2003/06/02 20:18:37 millert 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 No = 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 null 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..308458ea75
--- /dev/null
+++ b/src/lib/libc/stdlib/getsubopt.c
@@ -0,0 +1,102 @@
1/* $OpenBSD: getsubopt.c,v 1.2 2003/06/02 20:18:37 millert 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.2 2003/06/02 20:18:37 millert 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(optionp, tokens, valuep)
54 register char **optionp, **valuep;
55 register char * const *tokens;
56{
57 register int cnt;
58 register char *p;
59
60 suboptarg = *valuep = NULL;
61
62 if (!optionp || !*optionp)
63 return(-1);
64
65 /* skip leading white-space, commas */
66 for (p = *optionp; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p);
67
68 if (!*p) {
69 *optionp = p;
70 return(-1);
71 }
72
73 /* save the start of the token, and skip the rest of the token. */
74 for (suboptarg = p;
75 *++p && *p != ',' && *p != '=' && *p != ' ' && *p != '\t';);
76
77 if (*p) {
78 /*
79 * If there's an equals sign, set the value pointer, and
80 * skip over the value part of the token. Terminate the
81 * token.
82 */
83 if (*p == '=') {
84 *p = '\0';
85 for (*valuep = ++p;
86 *p && *p != ',' && *p != ' ' && *p != '\t'; ++p);
87 if (*p)
88 *p++ = '\0';
89 } else
90 *p++ = '\0';
91 /* Skip any whitespace or commas after this token. */
92 for (; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p);
93 }
94
95 /* set optionp for next round. */
96 *optionp = p;
97
98 for (cnt = 0; *tokens; ++tokens, ++cnt)
99 if (!strcmp(suboptarg, *tokens))
100 return(cnt);
101 return(-1);
102}
diff --git a/src/lib/libc/stdlib/heapsort.c b/src/lib/libc/stdlib/heapsort.c
new file mode 100644
index 0000000000..f4aeeef7a3
--- /dev/null
+++ b/src/lib/libc/stdlib/heapsort.c
@@ -0,0 +1,179 @@
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.6 2003/09/08 16:24:05 deraadt 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(vbase, nmemb, size, compar)
138 void *vbase;
139 size_t nmemb, size;
140 int (*compar)(const void *, const void *);
141{
142 register int cnt, i, j, l;
143 register char tmp, *tmp1, *tmp2;
144 char *base, *k, *p, *t;
145
146 if (nmemb <= 1)
147 return (0);
148
149 if (!size) {
150 errno = EINVAL;
151 return (-1);
152 }
153
154 if ((k = malloc(size)) == NULL)
155 return (-1);
156
157 /*
158 * Items are numbered from 1 to nmemb, so offset from size bytes
159 * below the starting address.
160 */
161 base = (char *)vbase - size;
162
163 for (l = nmemb / 2 + 1; --l;)
164 CREATE(l, nmemb, i, j, t, p, size, cnt, tmp);
165
166 /*
167 * For each element of the heap, save the largest element into its
168 * final slot, save the displaced element (k), then recreate the
169 * heap.
170 */
171 while (nmemb > 1) {
172 COPY(k, base + nmemb * size, cnt, size, tmp1, tmp2);
173 COPY(base + nmemb * size, base + size, cnt, size, tmp1, tmp2);
174 --nmemb;
175 SELECT(i, j, nmemb, t, p, size, k, cnt, tmp1, tmp2);
176 }
177 free(k);
178 return (0);
179}
diff --git a/src/lib/libc/stdlib/insque.3 b/src/lib/libc/stdlib/insque.3
new file mode 100644
index 0000000000..b09f1fdc04
--- /dev/null
+++ b/src/lib/libc/stdlib/insque.3
@@ -0,0 +1,100 @@
1.\" $OpenBSD: insque.3,v 1.2 2003/06/01 19:27:27 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-01
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..4e99391254
--- /dev/null
+++ b/src/lib/libc/stdlib/l64a.c
@@ -0,0 +1,46 @@
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.3 1997/08/17 22:58:34 millert Exp $";
8#endif /* LIBC_SCCS and not lint */
9
10#include <errno.h>
11#include <stdlib.h>
12
13char *
14l64a(value)
15 long value;
16{
17 static char buf[8];
18 char *s = buf;
19 int digit;
20 int i;
21
22 if (value < 0) {
23 errno = EINVAL;
24 return(NULL);
25 }
26
27 for (i = 0; value != 0 && i < 6; i++) {
28 digit = value & 0x3f;
29
30 if (digit < 2)
31 *s = digit + '.';
32 else if (digit < 12)
33 *s = digit + '0' - 2;
34 else if (digit < 38)
35 *s = digit + 'A' - 12;
36 else
37 *s = digit + 'a' - 38;
38
39 value >>= 6;
40 s++;
41 }
42
43 *s = '\0';
44
45 return(buf);
46}
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..51ef490d97
--- /dev/null
+++ b/src/lib/libc/stdlib/labs.c
@@ -0,0 +1,41 @@
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.3 2003/06/02 20:18:37 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35
36long
37labs(j)
38 long j;
39{
40 return(j < 0 ? -j : j);
41}
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..f4b5a5fa45
--- /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.6 2003/06/02 20:18:37 millert 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 No / 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..e005ff77de
--- /dev/null
+++ b/src/lib/libc/stdlib/ldiv.c
@@ -0,0 +1,54 @@
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.3 2003/06/02 20:18:37 millert Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37#include <stdlib.h> /* ldiv_t */
38
39ldiv_t
40ldiv(num, denom)
41 long num, denom;
42{
43 ldiv_t r;
44
45 /* see div.c for comments */
46
47 r.quot = num / denom;
48 r.rem = num % denom;
49 if (num >= 0 && r.rem < 0) {
50 r.quot++;
51 r.rem -= denom;
52 }
53 return (r);
54}
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..2bef4c9aad
--- /dev/null
+++ b/src/lib/libc/stdlib/lsearch.3
@@ -0,0 +1,103 @@
1.\" Copyright (c) 1989, 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.\" @(#)lsearch.3 8.1 (Berkeley) 6/4/93
29.\"
30.Dd June 4, 1993
31.Dt LSEARCH 3
32.Os
33.Sh NAME
34.Nm lsearch ,
35.Nm lfind
36.Nd linear searching routines
37.Sh SYNOPSIS
38.Ft char *
39.Fn lsearch "const void *key" "const void *base" "size_t *nelp" "size_t width" "int (*compar)(void *, void *)"
40.Ft char *
41.Fn lfind "const void *key" "const void *base" "size_t *nelp" "size_t width" "int (*compar)(void *, void *)"
42.Sh DESCRIPTION
43The functions
44.Fn lsearch ,
45and
46.Fn lfind
47provide basic linear searching functionality.
48.Pp
49.Fa base
50is the pointer to the beginning of an array.
51The argument
52.Fa nelp
53is the current number of elements in the array, where each element
54is
55.Fa width
56bytes long.
57The
58.Fa compar
59function
60is a comparison routine which is used to compare two elements.
61It takes two arguments which point to the
62.Fa key
63object and to an array member, in that order, and must return an integer
64less than, equivalent to, or greater than zero if the
65.Fa key
66object is considered, respectively, to be less than, equal to, or greater
67than the array member.
68.Pp
69The
70.Fn lsearch
71and
72.Fn lfind
73functions
74return a pointer into the array referenced by
75.Fa base
76where
77.Fa key
78is located.
79If
80.Fa key
81does not exist,
82.Fn lfind
83will return a null pointer and
84.Fn lsearch
85will add it to the array.
86When an element is added to the array by
87.Fn lsearch
88the location referenced by the argument
89.Fa nelp
90is incremented by one.
91.Sh SEE ALSO
92.Xr bsearch 3 ,
93.Xr db 3
94.Sh STANDARDS
95The
96.Fn lsearch
97and
98.Fn lfind
99functions conform to the
100.St -p1003.1-01
101and
102.St -xpg4.3 .
103specifications.
diff --git a/src/lib/libc/stdlib/lsearch.c b/src/lib/libc/stdlib/lsearch.c
new file mode 100644
index 0000000000..82483d1c82
--- /dev/null
+++ b/src/lib/libc/stdlib/lsearch.c
@@ -0,0 +1,86 @@
1/*
2 * Copyright (c) 1989, 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 * Roger L. Snyder.
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 sccsid[] = "@(#)lsearch.c 8.1 (Berkeley) 6/4/93";
35#endif /* LIBC_SCCS and not lint */
36
37#include <sys/types.h>
38#include <string.h>
39#include <search.h>
40
41typedef int (*cmp_fn_t)(const void *, const void *);
42static void *linear_base(const void *, const void *, size_t *, size_t,
43 cmp_fn_t, int);
44
45void *
46lsearch(const void *key, const void *base, size_t *nelp, size_t width,
47 cmp_fn_t compar)
48{
49
50 return(linear_base(key, base, nelp, width, compar, 1));
51}
52
53void *
54lfind(const void *key, const void *base, size_t *nelp, size_t width,
55 cmp_fn_t compar)
56{
57 return(linear_base(key, base, nelp, width, compar, 0));
58}
59
60static void *
61linear_base(const void *key, const void *base, size_t *nelp, size_t width,
62 cmp_fn_t compar, int add_flag)
63{
64 const char *element, *end;
65
66 end = (const char *)base + *nelp * width;
67 for (element = base; element < end; element += width)
68 if (!compar(key, element)) /* key found */
69 return((void *)element);
70
71 if (!add_flag) /* key not found */
72 return(NULL);
73
74 /*
75 * The UNIX System User's Manual, 1986 edition claims that
76 * a NULL pointer is returned by lsearch with errno set
77 * appropriately, if there is not enough room in the table
78 * to add a new item. This can't be done as none of these
79 * routines have any method of determining the size of the
80 * table. This comment isn't in the 1986-87 System V
81 * manual.
82 */
83 ++*nelp;
84 memcpy((void *)end, key, width);
85 return((void *)end);
86}
diff --git a/src/lib/libc/stdlib/malloc.3 b/src/lib/libc/stdlib/malloc.3
new file mode 100644
index 0000000000..2af8900656
--- /dev/null
+++ b/src/lib/libc/stdlib/malloc.3
@@ -0,0 +1,426 @@
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.32 2003/10/16 17:05:04 tedu 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.Pp
145.Bd -literal -offset indent
146size += 50;
147if ((p = realloc(p, size)) == NULL)
148 return (NULL);
149.Ed
150.Pp
151Do not adjust the variable describing how much memory has been allocated
152until one knows the allocation has been successful.
153This can cause aberrant program behavior if the incorrect size value is used.
154In most cases, the above sample will also result in a leak of memory.
155As stated earlier, a return value of
156.Dv NULL
157indicates that the old object still remains allocated.
158Better code looks like this:
159.Bd -literal -offset indent
160newsize = size + 50;
161if ((newp = realloc(p, newsize)) == NULL) {
162 free(p);
163 p = NULL;
164 size = 0;
165 return (NULL);
166}
167p = newp;
168size = newsize;
169.Ed
170.Pp
171Malloc will first look for a symbolic link called
172.Pa /etc/malloc.conf
173and next check the environment for a variable called
174.Ev MALLOC_OPTIONS
175and finally for the global variable
176.Va malloc_options
177and scan them for flags in that order.
178Flags are single letters, uppercase means on, lowercase means off.
179.Bl -tag -width indent
180.It Cm A
181.Dq Abort .
182.Fn malloc
183will coredump the process, rather than tolerate failure.
184This is a very handy debugging aid, since the core file will represent the
185time of failure, rather than when the null pointer was accessed.
186.Pp
187.It Cm D
188.Dq Dump .
189.Fn malloc
190will dump statistics in a file called
191.Pa malloc.out
192at exit.
193This option requires the library to have been compiled with -DMALLOC_STATS in
194order to have any effect.
195.Pp
196.It Cm G
197Enable guard pages and chunk randomization.
198Each page size or larger allocation is followed by a guard page that will
199cause a segmentation fault upon any access.
200Smaller than page size chunks are returned in a random order.
201.Pp
202.It Cm J
203.Dq Junk .
204Fill some junk into the area allocated.
205Currently junk is bytes of 0xd0; this is pronounced
206.Dq Duh .
207\&:-)
208.Pp
209.It Cm H
210.Dq Hint .
211Pass a hint to the kernel about pages we don't use.
212If the machine is paging a lot this may help a bit.
213.Pp
214.It Cm N
215Do not output warning messages when encountering possible corruption
216or bad pointers.
217.Pp
218.It Cm R
219.Dq realloc .
220Always reallocate when
221.Fn realloc
222is called, even if the initial allocation was big enough.
223This can substantially aid in compacting memory.
224.\".Pp
225.\".It Cm U
226.\".Dq utrace .
227.\"Generate entries for
228.\".Xr ktrace 1
229.\"for all operations.
230.\"Consult the source for this one.
231.Pp
232.It Cm X
233.Dq xmalloc .
234Rather than return failure,
235.Xr abort 3
236the program with a diagnostic message on stderr.
237It is the intention that this option be set at compile time by
238including in the source:
239.Bd -literal -offset indent
240extern char *malloc_options;
241malloc_options = "X";
242.Ed
243.Pp
244.It Cm Z
245.Dq Zero .
246Fill some junk into the area allocated (see
247.Cm J ) ,
248except for the exact length the user asked for, which is zeroed.
249.Pp
250.It Cm <
251.Dq Half the cache size .
252Reduce the size of the cache by a factor of two.
253.Pp
254.It Cm >
255.Dq Double the cache size .
256Double the size of the cache by a factor of two.
257.El
258.Pp
259So to set a systemwide reduction of cache size and coredumps on problems
260one would:
261.Li ln -s 'A<' /etc/malloc.conf
262.Pp
263The
264.Cm J
265and
266.Cm Z
267flags are mostly for testing and debugging.
268If a program changes behavior if either of these options are used,
269it is buggy.
270.Pp
271The default cache size is 16 pages.
272.Sh RETURN VALUES
273The
274.Fn malloc
275and
276.Fn calloc
277functions return a pointer to the allocated space if successful; otherwise,
278a null pointer is returned and
279.Va errno
280is set to
281.Er ENOMEM .
282.Pp
283The
284.Fn free
285and
286.Fn cfree
287functions return no value.
288.Pp
289The
290.Fn realloc
291function returns a pointer to the (possibly moved) allocated space
292if successful; otherwise, a null pointer is returned and
293.Va errno
294is set to
295.Er ENOMEM .
296.Sh ENVIRONMENT
297See above.
298.Sh FILES
299.Bl -tag -width "/etc/malloc.conf"
300.It Pa /etc/malloc.conf
301symbolic link to filename containing option flags
302.El
303.Sh DIAGNOSTICS
304If
305.Fn malloc ,
306.Fn calloc ,
307.Fn realloc ,
308or
309.Fn free
310detect an error or warning condition,
311a message will be printed to file descriptor
3122 (not using stdio).
313Errors will always result in the process being
314.Xr abort 3 'ed.
315If the
316.Cm A
317option has been specified, warnings will also
318.Xr abort 3
319the process.
320.Pp
321Here is a brief description of the error messages and what they mean:
322.Bl -tag -width Fl
323.It Dq (ES): mumble mumble mumble
324.Fn malloc
325has been compiled with
326.Dv \&-DEXTRA_SANITY
327and something looks fishy in there.
328Consult sources and/or wizards.
329.It Dq allocation failed
330If the
331.Cm A
332option is specified it is an error for
333.Fn malloc ,
334.Fn calloc ,
335or
336.Fn realloc
337to return
338.Dv NULL .
339.It Dq mmap(2) failed, check limits.
340This is a rather weird condition that is most likely to indicate a
341seriously overloaded system or a
342.Xr ulimit 1
343restriction.
344.It Dq freelist is destroyed.
345.Fn malloc Ns 's
346internal freelist has been stomped on.
347.El
348.Pp
349Here is a brief description of the warning messages and what they mean:
350.Bl -tag -width Fl
351.It Dq chunk/page is already free.
352A pointer to a free chunk is attempted freed again.
353.It Dq junk pointer, too high to make sense.
354The pointer doesn't make sense.
355It's above the area of memory that
356.Fn malloc
357knows something about.
358This could be a pointer from some
359.Xr mmap 2 'ed
360memory.
361.It Dq junk pointer, too low to make sense.
362The pointer doesn't make sense.
363It's below the area of memory that
364.Fn malloc
365knows something about.
366This pointer probably came from your data or bss segments.
367.It Dq malloc() has never been called.
368Nothing has ever been allocated, yet something is being freed or
369realloc'ed.
370.It Dq modified (chunk-/page-) pointer.
371The pointer passed to free or realloc has been modified.
372.It Dq pointer to wrong page.
373The pointer that
374.Fn malloc
375is trying to free is not pointing to
376a sensible page.
377.It Dq recursive call.
378An attempt was made to call recursively into these functions, i.e., from a
379signal handler.
380This behavior is not supported.
381In particular, signal handlers should
382.Em not
383use any of the
384.Fn malloc
385functions nor utilize any other functions which may call
386.Fn malloc
387(e.g.,
388.Xr stdio 3
389routines).
390.It Dq unknown char in MALLOC_OPTIONS
391We found something we didn't understand.
392.El
393.Sh SEE ALSO
394.Xr brk 2 ,
395.Xr alloca 3 ,
396.Xr getpagesize 3 ,
397.Xr memory 3
398.Sh STANDARDS
399The
400.Fn malloc
401function conforms to
402.St -ansiC .
403.Sh HISTORY
404The present implementation of
405.Fn malloc
406started out as a filesystem on a drum
407attached to a 20-bit binary challenged computer built with discrete germanium
408transistors, and it has since graduated to handle primary storage rather than
409secondary.
410.Pp
411The main difference from other
412.Fn malloc
413implementations are believed to be that
414the free pages are not accessed until allocated.
415Most
416.Fn malloc
417implementations will store a data structure containing a,
418possibly double-, linked list in the free chunks of memory, used to tie
419all the free memory together.
420That is a quite suboptimal thing to do.
421Every time the free-list is traversed, all the otherwise unused, and very
422likely paged out, pages get faulted into primary memory, just to see what
423lies after them in the list.
424.Pp
425On systems which are paging, this can make a factor five in difference on the
426page-faults of a process.
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c
new file mode 100644
index 0000000000..689fa8996a
--- /dev/null
+++ b/src/lib/libc/stdlib/malloc.c
@@ -0,0 +1,1317 @@
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.64 2003/10/16 17:05:05 tedu 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/param.h>
42#include <sys/mman.h>
43#include <sys/uio.h>
44#include <stdio.h>
45#include <stdlib.h>
46#include <string.h>
47#include <unistd.h>
48#include <fcntl.h>
49#include <limits.h>
50#include <errno.h>
51
52#include "thread_private.h"
53
54/*
55 * The basic parameters you can tweak.
56 *
57 * malloc_pageshift pagesize = 1 << malloc_pageshift
58 * It's probably best if this is the native
59 * page size, but it shouldn't have to be.
60 *
61 * malloc_minsize minimum size of an allocation in bytes.
62 * If this is too small it's too much work
63 * to manage them. This is also the smallest
64 * unit of alignment used for the storage
65 * returned by malloc/realloc.
66 *
67 */
68
69#if defined(__OpenBSD__) && defined(__sparc__)
70# define malloc_pageshift 13U
71#endif /* __OpenBSD__ */
72
73/*
74 * No user serviceable parts behind this point.
75 *
76 * This structure describes a page worth of chunks.
77 */
78
79struct pginfo {
80 struct pginfo *next; /* next on the free list */
81 void *page; /* Pointer to the page */
82 u_short size; /* size of this page's chunks */
83 u_short shift; /* How far to shift for this size chunks */
84 u_short free; /* How many free chunks */
85 u_short total; /* How many chunk */
86 u_long bits[1]; /* Which chunks are free */
87};
88
89/*
90 * This structure describes a number of free pages.
91 */
92
93struct pgfree {
94 struct pgfree *next; /* next run of free pages */
95 struct pgfree *prev; /* prev run of free pages */
96 void *page; /* pointer to free pages */
97 void *end; /* pointer to end of free pages */
98 u_long size; /* number of bytes free */
99};
100
101/*
102 * How many bits per u_long in the bitmap.
103 * Change only if not 8 bits/byte
104 */
105#define MALLOC_BITS (8*sizeof(u_long))
106
107/*
108 * Magic values to put in the page_directory
109 */
110#define MALLOC_NOT_MINE ((struct pginfo*) 0)
111#define MALLOC_FREE ((struct pginfo*) 1)
112#define MALLOC_FIRST ((struct pginfo*) 2)
113#define MALLOC_FOLLOW ((struct pginfo*) 3)
114#define MALLOC_MAGIC ((struct pginfo*) 4)
115
116#ifndef malloc_pageshift
117#define malloc_pageshift (PGSHIFT)
118#endif
119
120#ifndef malloc_minsize
121#define malloc_minsize 16U
122#endif
123
124#ifndef malloc_pageshift
125#error "malloc_pageshift undefined"
126#endif
127
128#if !defined(malloc_pagesize)
129#define malloc_pagesize (1UL<<malloc_pageshift)
130#endif
131
132#if ((1UL<<malloc_pageshift) != malloc_pagesize)
133#error "(1UL<<malloc_pageshift) != malloc_pagesize"
134#endif
135
136#ifndef malloc_maxsize
137#define malloc_maxsize ((malloc_pagesize)>>1)
138#endif
139
140/* A mask for the offset inside a page. */
141#define malloc_pagemask ((malloc_pagesize)-1)
142
143#define pageround(foo) (((foo) + (malloc_pagemask))&(~(malloc_pagemask)))
144#define ptr2index(foo) (((u_long)(foo) >> malloc_pageshift)-malloc_origo)
145
146/* fd of /dev/zero */
147#ifdef USE_DEV_ZERO
148static int fdzero;
149#define MMAP_FD fdzero
150#define INIT_MMAP() \
151 { if ((fdzero=open("/dev/zero", O_RDWR, 0000)) == -1) \
152 wrterror("open of /dev/zero\n"); }
153#else
154#define MMAP_FD (-1)
155#define INIT_MMAP()
156#endif
157
158/* Set when initialization has been done */
159static unsigned int malloc_started;
160
161/* Number of free pages we cache */
162static unsigned int malloc_cache = 16;
163
164/* The offset from pagenumber to index into the page directory */
165static u_long malloc_origo;
166
167/* The last index in the page directory we care about */
168static u_long last_index;
169
170/* Pointer to page directory. Allocated "as if with" malloc */
171static struct pginfo **page_dir;
172
173/* How many slots in the page directory */
174static size_t malloc_ninfo;
175
176/* Free pages line up here */
177static struct pgfree free_list;
178
179/* Abort(), user doesn't handle problems. */
180static int malloc_abort = 2;
181
182/* Are we trying to die ? */
183static int suicide;
184
185#ifdef MALLOC_STATS
186/* dump statistics */
187static int malloc_stats;
188#endif
189
190/* avoid outputting warnings? */
191static int malloc_silent;
192
193/* always realloc ? */
194static int malloc_realloc;
195
196/* mprotect free pages PROT_NONE? */
197static int malloc_freeprot;
198
199/* use guard pages after allocations? */
200static int malloc_guard = 0;
201
202#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
203/* pass the kernel a hint on free pages ? */
204static int malloc_hint;
205#endif
206
207/* xmalloc behaviour ? */
208static int malloc_xmalloc;
209
210/* zero fill ? */
211static int malloc_zero;
212
213/* junk fill ? */
214static int malloc_junk;
215
216#ifdef __FreeBSD__
217/* utrace ? */
218static int malloc_utrace;
219
220struct ut { void *p; size_t s; void *r; };
221
222void utrace(struct ut *, int);
223
224#define UTRACE(a, b, c) \
225 if (malloc_utrace) \
226 {struct ut u; u.p=a; u.s = b; u.r=c; utrace(&u, sizeof u);}
227#else /* !__FreeBSD__ */
228#define UTRACE(a,b,c)
229#endif
230
231/* my last break. */
232static void *malloc_brk;
233
234/* one location cache for free-list holders */
235static struct pgfree *px;
236
237/* compile-time options */
238char *malloc_options;
239
240/* Name of the current public function */
241static char *malloc_func;
242
243/* Macro for mmap */
244#define MMAP(size) \
245 mmap((void *)0, (size), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, \
246 MMAP_FD, (off_t)0)
247
248/*
249 * Necessary function declarations
250 */
251static int extend_pgdir(u_long index);
252static void *imalloc(size_t size);
253static void ifree(void *ptr);
254static void *irealloc(void *ptr, size_t size);
255static void *malloc_bytes(size_t size);
256
257#ifdef MALLOC_STATS
258void
259malloc_dump(FILE *fd)
260{
261 struct pginfo **pd;
262 struct pgfree *pf;
263 int j;
264
265 pd = page_dir;
266
267 /* print out all the pages */
268 for(j=0;j<=last_index;j++) {
269 fprintf(fd, "%08lx %5d ", (j+malloc_origo) << malloc_pageshift, j);
270 if (pd[j] == MALLOC_NOT_MINE) {
271 for(j++;j<=last_index && pd[j] == MALLOC_NOT_MINE;j++)
272 ;
273 j--;
274 fprintf(fd, ".. %5d not mine\n", j);
275 } else if (pd[j] == MALLOC_FREE) {
276 for(j++;j<=last_index && pd[j] == MALLOC_FREE;j++)
277 ;
278 j--;
279 fprintf(fd, ".. %5d free\n", j);
280 } else if (pd[j] == MALLOC_FIRST) {
281 for(j++;j<=last_index && pd[j] == MALLOC_FOLLOW;j++)
282 ;
283 j--;
284 fprintf(fd, ".. %5d in use\n", j);
285 } else if (pd[j] < MALLOC_MAGIC) {
286 fprintf(fd, "(%p)\n", pd[j]);
287 } else {
288 fprintf(fd, "%p %d (of %d) x %d @ %p --> %p\n",
289 pd[j], pd[j]->free, pd[j]->total,
290 pd[j]->size, pd[j]->page, pd[j]->next);
291 }
292 }
293
294 for(pf=free_list.next; pf; pf=pf->next) {
295 fprintf(fd, "Free: @%p [%p...%p[ %ld ->%p <-%p\n",
296 pf, pf->page, pf->end, pf->size, pf->prev, pf->next);
297 if (pf == pf->next) {
298 fprintf(fd, "Free_list loops\n");
299 break;
300 }
301 }
302
303 /* print out various info */
304 fprintf(fd, "Minsize\t%d\n", malloc_minsize);
305 fprintf(fd, "Maxsize\t%d\n", malloc_maxsize);
306 fprintf(fd, "Pagesize\t%lu\n", (u_long)malloc_pagesize);
307 fprintf(fd, "Pageshift\t%d\n", malloc_pageshift);
308 fprintf(fd, "FirstPage\t%ld\n", malloc_origo);
309 fprintf(fd, "LastPage\t%ld %lx\n", last_index+malloc_pageshift,
310 (last_index + malloc_pageshift) << malloc_pageshift);
311 fprintf(fd, "Break\t%ld\n", (u_long)sbrk(0) >> malloc_pageshift);
312}
313#endif /* MALLOC_STATS */
314
315extern char *__progname;
316
317static void
318wrterror(char *p)
319{
320 char *q = " error: ";
321 struct iovec iov[4];
322
323 iov[0].iov_base = __progname;
324 iov[0].iov_len = strlen(__progname);
325 iov[1].iov_base = malloc_func;
326 iov[1].iov_len = strlen(malloc_func);
327 iov[2].iov_base = q;
328 iov[2].iov_len = strlen(q);
329 iov[3].iov_base = p;
330 iov[3].iov_len = strlen(p);
331 writev(STDERR_FILENO, iov, 4);
332
333 suicide = 1;
334#ifdef MALLOC_STATS
335 if (malloc_stats)
336 malloc_dump(stderr);
337#endif /* MALLOC_STATS */
338 abort();
339}
340
341static void
342wrtwarning(char *p)
343{
344 char *q = " warning: ";
345 struct iovec iov[4];
346
347 if (malloc_abort)
348 wrterror(p);
349 else if (malloc_silent)
350 return;
351
352 iov[0].iov_base = __progname;
353 iov[0].iov_len = strlen(__progname);
354 iov[1].iov_base = malloc_func;
355 iov[1].iov_len = strlen(malloc_func);
356 iov[2].iov_base = q;
357 iov[2].iov_len = strlen(q);
358 iov[3].iov_base = p;
359 iov[3].iov_len = strlen(p);
360 writev(STDERR_FILENO, iov, 4);
361}
362
363#ifdef MALLOC_STATS
364static void
365malloc_exit(void)
366{
367 FILE *fd = fopen("malloc.out", "a");
368 char *q = "malloc() warning: Couldn't dump stats\n";
369 if (fd != NULL) {
370 malloc_dump(fd);
371 fclose(fd);
372 } else
373 write(STDERR_FILENO, q, strlen(q));
374}
375#endif /* MALLOC_STATS */
376
377
378/*
379 * Allocate a number of pages from the OS
380 */
381static void *
382map_pages(size_t pages)
383{
384 caddr_t result, tail;
385
386 result = (caddr_t)pageround((u_long)sbrk(0));
387 pages <<= malloc_pageshift;
388 if (pages > SIZE_T_MAX - (size_t)result) {
389#ifdef MALLOC_EXTRA_SANITY
390 wrtwarning("(ES): overflow in map_pages fails\n");
391#endif /* MALLOC_EXTRA_SANITY */
392 errno = ENOMEM;
393 return (NULL);
394 }
395 tail = result + pages + malloc_guard;
396
397 if (brk(tail) == (char *)-1) {
398#ifdef MALLOC_EXTRA_SANITY
399 wrtwarning("(ES): map_pages fails\n");
400#endif /* MALLOC_EXTRA_SANITY */
401 return (NULL);
402 }
403 if (malloc_guard)
404 mprotect(result + pages, malloc_pagesize, PROT_NONE);
405
406 last_index = ptr2index(tail) - 1;
407 malloc_brk = tail;
408
409 if ((last_index+1) >= malloc_ninfo && !extend_pgdir(last_index))
410 return (NULL);
411
412 return (result);
413}
414
415/*
416 * Extend page directory
417 */
418static int
419extend_pgdir(u_long index)
420{
421 struct pginfo **new, **old;
422 size_t i, oldlen;
423
424 /* Make it this many pages */
425 i = index * sizeof *page_dir;
426 i /= malloc_pagesize;
427 i += 2;
428
429 /* remember the old mapping size */
430 oldlen = malloc_ninfo * sizeof *page_dir;
431
432 /*
433 * NOTE: we allocate new pages and copy the directory rather than tempt
434 * fate by trying to "grow" the region.. There is nothing to prevent
435 * us from accidently re-mapping space that's been allocated by our caller
436 * via dlopen() or other mmap().
437 *
438 * The copy problem is not too bad, as there is 4K of page index per
439 * 4MB of malloc arena.
440 *
441 * We can totally avoid the copy if we open a file descriptor to associate
442 * the anon mappings with. Then, when we remap the pages at the new
443 * address, the old pages will be "magically" remapped.. But this means
444 * keeping open a "secret" file descriptor.....
445 */
446
447 /* Get new pages */
448 new = (struct pginfo**) MMAP(i * malloc_pagesize);
449 if (new == MAP_FAILED)
450 return (0);
451
452 /* Copy the old stuff */
453 memcpy(new, page_dir,
454 malloc_ninfo * sizeof *page_dir);
455
456 /* register the new size */
457 malloc_ninfo = i * malloc_pagesize / sizeof *page_dir;
458
459 /* swap the pointers */
460 old = page_dir;
461 page_dir = new;
462
463 /* Now free the old stuff */
464 munmap(old, oldlen);
465 return (1);
466}
467
468/*
469 * Initialize the world
470 */
471static void
472malloc_init(void)
473{
474 char *p, b[64];
475 int i, j;
476 int save_errno = errno;
477
478 _MALLOC_LOCK_INIT();
479
480 INIT_MMAP();
481
482#ifdef MALLOC_EXTRA_SANITY
483 malloc_junk = 1;
484#endif /* MALLOC_EXTRA_SANITY */
485
486 for (i = 0; i < 3; i++) {
487 if (i == 0) {
488 j = readlink("/etc/malloc.conf", b, sizeof b - 1);
489 if (j <= 0)
490 continue;
491 b[j] = '\0';
492 p = b;
493 } else if (i == 1) {
494 if (issetugid() == 0)
495 p = getenv("MALLOC_OPTIONS");
496 else
497 continue;
498 } else if (i == 2) {
499 p = malloc_options;
500 }
501 for (; p != NULL && *p != '\0'; p++) {
502 switch (*p) {
503 case '>': malloc_cache <<= 1; break;
504 case '<': malloc_cache >>= 1; break;
505 case 'a': malloc_abort = 0; break;
506 case 'A': malloc_abort = 1; break;
507#ifdef MALLOC_STATS
508 case 'd': malloc_stats = 0; break;
509 case 'D': malloc_stats = 1; break;
510#endif /* MALLOC_STATS */
511 case 'f': malloc_freeprot = 0; break;
512 case 'F': malloc_freeprot = 1; break;
513 case 'g': malloc_guard = 0; break;
514 case 'G': malloc_guard = malloc_pagesize; break;
515#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
516 case 'h': malloc_hint = 0; break;
517 case 'H': malloc_hint = 1; break;
518#endif /* __FreeBSD__ */
519 case 'r': malloc_realloc = 0; break;
520 case 'R': malloc_realloc = 1; break;
521 case 'j': malloc_junk = 0; break;
522 case 'J': malloc_junk = 1; break;
523 case 'n': malloc_silent = 0; break;
524 case 'N': malloc_silent = 1; break;
525#ifdef __FreeBSD__
526 case 'u': malloc_utrace = 0; break;
527 case 'U': malloc_utrace = 1; break;
528#endif /* __FreeBSD__ */
529 case 'x': malloc_xmalloc = 0; break;
530 case 'X': malloc_xmalloc = 1; break;
531 case 'z': malloc_zero = 0; break;
532 case 'Z': malloc_zero = 1; break;
533 default:
534 j = malloc_abort;
535 malloc_abort = 0;
536 wrtwarning("unknown char in MALLOC_OPTIONS\n");
537 malloc_abort = j;
538 break;
539 }
540 }
541 }
542
543 UTRACE(0, 0, 0);
544
545 /*
546 * We want junk in the entire allocation, and zero only in the part
547 * the user asked for.
548 */
549 if (malloc_zero)
550 malloc_junk=1;
551
552#ifdef MALLOC_STATS
553 if (malloc_stats && (atexit(malloc_exit) == -1))
554 wrtwarning("atexit(2) failed. Will not be able to dump malloc stats on exit\n");
555#endif /* MALLOC_STATS */
556
557 /* Allocate one page for the page directory */
558 page_dir = (struct pginfo **) MMAP(malloc_pagesize);
559
560 if (page_dir == MAP_FAILED)
561 wrterror("mmap(2) failed, check limits\n");
562
563 /*
564 * We need a maximum of malloc_pageshift buckets, steal these from the
565 * front of the page_directory;
566 */
567 malloc_origo = ((u_long)pageround((u_long)sbrk(0))) >> malloc_pageshift;
568 malloc_origo -= malloc_pageshift;
569
570 malloc_ninfo = malloc_pagesize / sizeof *page_dir;
571
572 /* Been here, done that */
573 malloc_started++;
574
575 /* Recalculate the cache size in bytes, and make sure it's nonzero */
576
577 if (!malloc_cache)
578 malloc_cache++;
579
580 malloc_cache <<= malloc_pageshift;
581
582 /*
583 * This is a nice hack from Kaleb Keithly (kaleb@x.org).
584 * We can sbrk(2) further back when we keep this on a low address.
585 */
586 px = (struct pgfree *) imalloc (sizeof *px);
587 errno = save_errno;
588}
589
590/*
591 * Allocate a number of complete pages
592 */
593static void *
594malloc_pages(size_t size)
595{
596 void *p, *delay_free = NULL;
597 int i;
598 struct pgfree *pf;
599 u_long index;
600
601 size = pageround(size) + malloc_guard;
602
603 p = NULL;
604 /* Look for free pages before asking for more */
605 for(pf = free_list.next; pf; pf = pf->next) {
606
607#ifdef MALLOC_EXTRA_SANITY
608 if (pf->size & malloc_pagemask)
609 wrterror("(ES): junk length entry on free_list\n");
610 if (!pf->size)
611 wrterror("(ES): zero length entry on free_list\n");
612 if (pf->page == pf->end)
613 wrterror("(ES): zero entry on free_list\n");
614 if (pf->page > pf->end)
615 wrterror("(ES): sick entry on free_list\n");
616 if ((void*)pf->page >= (void*)sbrk(0))
617 wrterror("(ES): entry on free_list past brk\n");
618 if (page_dir[ptr2index(pf->page)] != MALLOC_FREE)
619 wrterror("(ES): non-free first page on free-list\n");
620 if (page_dir[ptr2index(pf->end)-1] != MALLOC_FREE)
621 wrterror("(ES): non-free last page on free-list\n");
622#endif /* MALLOC_EXTRA_SANITY */
623
624 if (pf->size < size)
625 continue;
626
627 if (pf->size == size) {
628 p = pf->page;
629 if (pf->next != NULL)
630 pf->next->prev = pf->prev;
631 pf->prev->next = pf->next;
632 delay_free = pf;
633 break;
634 }
635
636 p = pf->page;
637 pf->page = (char *)pf->page + size;
638 pf->size -= size;
639 break;
640 }
641
642 size -= malloc_guard;
643
644#ifdef MALLOC_EXTRA_SANITY
645 if (p != NULL && page_dir[ptr2index(p)] != MALLOC_FREE)
646 wrterror("(ES): allocated non-free page on free-list\n");
647#endif /* MALLOC_EXTRA_SANITY */
648
649 if ((malloc_guard || malloc_freeprot) && p != NULL)
650 mprotect(p, size, PROT_READ|PROT_WRITE);
651
652 size >>= malloc_pageshift;
653
654 /* Map new pages */
655 if (p == NULL)
656 p = map_pages(size);
657
658 if (p != NULL) {
659
660 index = ptr2index(p);
661 page_dir[index] = MALLOC_FIRST;
662 for (i=1;i<size;i++)
663 page_dir[index+i] = MALLOC_FOLLOW;
664
665 if (malloc_junk)
666 memset(p, SOME_JUNK, size << malloc_pageshift);
667 }
668
669 if (delay_free) {
670 if (px == NULL)
671 px = delay_free;
672 else
673 ifree(delay_free);
674 }
675
676 return (p);
677}
678
679/*
680 * Allocate a page of fragments
681 */
682
683static __inline__ int
684malloc_make_chunks(int bits)
685{
686 struct pginfo *bp;
687 void *pp;
688 int i, k, l;
689
690 /* Allocate a new bucket */
691 pp = malloc_pages((size_t)malloc_pagesize);
692 if (pp == NULL)
693 return (0);
694
695 /* Find length of admin structure */
696 l = sizeof *bp - sizeof(u_long);
697 l += sizeof(u_long) *
698 (((malloc_pagesize >> bits)+MALLOC_BITS-1) / MALLOC_BITS);
699
700 /* Don't waste more than two chunks on this */
701 /*
702 * If we are to allocate a memory protected page for the malloc(0)
703 * case (when bits=0), it must be from a different page than the
704 * pginfo page.
705 * --> Treat it like the big chunk alloc, get a second data page.
706 */
707 if (bits != 0 && (1UL<<(bits)) <= l+l) {
708 bp = (struct pginfo *)pp;
709 } else {
710 bp = (struct pginfo *)imalloc(l);
711 if (bp == NULL) {
712 ifree(pp);
713 return (0);
714 }
715 }
716
717 /* memory protect the page allocated in the malloc(0) case */
718 if (bits == 0) {
719
720 bp->size = 0;
721 bp->shift = 1;
722 i = malloc_minsize-1;
723 while (i >>= 1)
724 bp->shift++;
725 bp->total = bp->free = malloc_pagesize >> bp->shift;
726 bp->page = pp;
727
728 k = mprotect(pp, malloc_pagesize, PROT_NONE);
729 if (k < 0) {
730 ifree(pp);
731 ifree(bp);
732 return (0);
733 }
734 } else {
735 bp->size = (1UL<<bits);
736 bp->shift = bits;
737 bp->total = bp->free = malloc_pagesize >> bits;
738 bp->page = pp;
739 }
740
741 /* set all valid bits in the bitmap */
742 k = bp->total;
743 i = 0;
744
745 /* Do a bunch at a time */
746 for(;k-i >= MALLOC_BITS; i += MALLOC_BITS)
747 bp->bits[i / MALLOC_BITS] = ~0UL;
748
749 for(; i < k; i++)
750 bp->bits[i/MALLOC_BITS] |= 1UL<<(i%MALLOC_BITS);
751
752 if (bp == bp->page) {
753 /* Mark the ones we stole for ourselves */
754 for(i=0;l > 0;i++) {
755 bp->bits[i/MALLOC_BITS] &= ~(1UL<<(i%MALLOC_BITS));
756 bp->free--;
757 bp->total--;
758 l -= (1 << bits);
759 }
760 }
761
762 /* MALLOC_LOCK */
763
764 page_dir[ptr2index(pp)] = bp;
765
766 bp->next = page_dir[bits];
767 page_dir[bits] = bp;
768
769 /* MALLOC_UNLOCK */
770
771 return (1);
772}
773
774/*
775 * Allocate a fragment
776 */
777static void *
778malloc_bytes(size_t size)
779{
780 int i,j;
781 u_long u;
782 struct pginfo *bp;
783 int k;
784 u_long *lp;
785
786 /* Don't bother with anything less than this */
787 /* unless we have a malloc(0) requests */
788 if (size != 0 && size < malloc_minsize)
789 size = malloc_minsize;
790
791 /* Find the right bucket */
792 if (size == 0)
793 j=0;
794 else {
795 j = 1;
796 i = size-1;
797 while (i >>= 1)
798 j++;
799 }
800
801 /* If it's empty, make a page more of that size chunks */
802 if (page_dir[j] == NULL && !malloc_make_chunks(j))
803 return (NULL);
804
805 bp = page_dir[j];
806
807 /* Find first word of bitmap which isn't empty */
808 for (lp = bp->bits; !*lp; lp++)
809 ;
810
811 /* Find that bit, and tweak it */
812 u = 1;
813 k = 0;
814 while (!(*lp & u)) {
815 u += u;
816 k++;
817 }
818
819 if (malloc_guard) {
820 /* Walk to a random position. */
821 i = arc4random() % bp->free;
822 while (i > 0) {
823 u += u;
824 k++;
825 if (k >= MALLOC_BITS) {
826 lp++;
827 u = 1;
828 k = 0;
829 }
830#ifdef MALLOC_EXTRA_SANITY
831 if (lp - bp->bits > (bp->total - 1) / MALLOC_BITS)
832 wrterror("chunk overflow\n");
833#endif /* MALLOC_EXTRA_SANITY */
834 if (*lp & u)
835 i--;
836 }
837 }
838 *lp ^= u;
839
840 /* If there are no more free, remove from free-list */
841 if (!--bp->free) {
842 page_dir[j] = bp->next;
843 bp->next = NULL;
844 }
845
846 /* Adjust to the real offset of that chunk */
847 k += (lp-bp->bits)*MALLOC_BITS;
848 k <<= bp->shift;
849
850 if (malloc_junk && bp->size != 0)
851 memset((char *)bp->page + k, SOME_JUNK, bp->size);
852
853 return ((u_char *)bp->page + k);
854}
855
856/*
857 * Allocate a piece of memory
858 */
859static void *
860imalloc(size_t size)
861{
862 void *result;
863
864 if (!malloc_started)
865 malloc_init();
866
867 if (suicide)
868 abort();
869
870 if ((size + malloc_pagesize) < size) { /* Check for overflow */
871 result = NULL;
872 errno = ENOMEM;
873 }
874 else if (size <= malloc_maxsize)
875 result = malloc_bytes(size);
876 else
877 result = malloc_pages(size);
878
879 if (malloc_abort == 1 && result == NULL)
880 wrterror("allocation failed\n");
881
882 if (malloc_zero && result != NULL)
883 memset(result, 0, size);
884
885 return (result);
886}
887
888/*
889 * Change the size of an allocation.
890 */
891static void *
892irealloc(void *ptr, size_t size)
893{
894 void *p;
895 u_long osize, index;
896 struct pginfo **mp;
897 int i;
898
899 if (suicide)
900 abort();
901
902 if (!malloc_started) {
903 wrtwarning("malloc() has never been called\n");
904 return (NULL);
905 }
906
907 index = ptr2index(ptr);
908
909 if (index < malloc_pageshift) {
910 wrtwarning("junk pointer, too low to make sense\n");
911 return (NULL);
912 }
913
914 if (index > last_index) {
915 wrtwarning("junk pointer, too high to make sense\n");
916 return (NULL);
917 }
918
919 mp = &page_dir[index];
920
921 if (*mp == MALLOC_FIRST) { /* Page allocation */
922
923 /* Check the pointer */
924 if ((u_long)ptr & malloc_pagemask) {
925 wrtwarning("modified (page-) pointer\n");
926 return (NULL);
927 }
928
929 /* Find the size in bytes */
930 for (osize = malloc_pagesize; *(++mp) == MALLOC_FOLLOW;)
931 osize += malloc_pagesize;
932
933 if (!malloc_realloc && /* Unless we have to, */
934 size <= osize && /* .. or are too small, */
935 size > (osize - malloc_pagesize)) { /* .. or can free a page, */
936 if (malloc_junk)
937 memset((char *)ptr + size, SOME_JUNK, osize-size);
938 return (ptr); /* ..don't do anything else. */
939 }
940
941 } else if (*mp >= MALLOC_MAGIC) { /* Chunk allocation */
942
943 /* Check the pointer for sane values */
944 if ((u_long)ptr & ((1UL<<((*mp)->shift))-1)) {
945 wrtwarning("modified (chunk-) pointer\n");
946 return (NULL);
947 }
948
949 /* Find the chunk index in the page */
950 i = ((u_long)ptr & malloc_pagemask) >> (*mp)->shift;
951
952 /* Verify that it isn't a free chunk already */
953 if ((*mp)->bits[i/MALLOC_BITS] & (1UL<<(i%MALLOC_BITS))) {
954 wrtwarning("chunk is already free\n");
955 return (NULL);
956 }
957
958 osize = (*mp)->size;
959
960 if (!malloc_realloc && /* Unless we have to, */
961 size <= osize && /* ..or are too small, */
962 (size > osize/2 || /* ..or could use a smaller size, */
963 osize == malloc_minsize)) { /* ..(if there is one) */
964 if (malloc_junk)
965 memset((char *)ptr + size, SOME_JUNK, osize-size);
966 return (ptr); /* ..don't do anything else. */
967 }
968
969 } else {
970 wrtwarning("pointer to wrong page\n");
971 return (NULL);
972 }
973
974 p = imalloc(size);
975
976 if (p != NULL) {
977 /* copy the lesser of the two sizes, and free the old one */
978 /* Don't move from/to 0 sized region !!! */
979 if (osize != 0 && size != 0) {
980 if (osize < size)
981 memcpy(p, ptr, osize);
982 else
983 memcpy(p, ptr, size);
984 }
985 ifree(ptr);
986 }
987 return (p);
988}
989
990/*
991 * Free a sequence of pages
992 */
993
994static __inline__ void
995free_pages(void *ptr, int index, struct pginfo *info)
996{
997 int i;
998 struct pgfree *pf, *pt=NULL;
999 u_long l;
1000 void *tail;
1001
1002 if (info == MALLOC_FREE) {
1003 wrtwarning("page is already free\n");
1004 return;
1005 }
1006
1007 if (info != MALLOC_FIRST) {
1008 wrtwarning("pointer to wrong page\n");
1009 return;
1010 }
1011
1012 if ((u_long)ptr & malloc_pagemask) {
1013 wrtwarning("modified (page-) pointer\n");
1014 return;
1015 }
1016
1017 /* Count how many pages and mark them free at the same time */
1018 page_dir[index] = MALLOC_FREE;
1019 for (i = 1; page_dir[index+i] == MALLOC_FOLLOW; i++)
1020 page_dir[index + i] = MALLOC_FREE;
1021
1022 l = i << malloc_pageshift;
1023
1024 if (malloc_junk)
1025 memset(ptr, SOME_JUNK, l);
1026
1027#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
1028 if (malloc_hint)
1029 madvise(ptr, l, MADV_FREE);
1030#endif
1031
1032 l += malloc_guard;
1033 tail = (char *)ptr+l;
1034
1035 if (malloc_freeprot)
1036 mprotect(ptr, tail - ptr, PROT_NONE);
1037
1038 /* add to free-list */
1039 if (px == NULL)
1040 px = imalloc(sizeof *px); /* This cannot fail... */
1041 px->page = ptr;
1042 px->end = tail;
1043 px->size = l;
1044
1045 if (free_list.next == NULL) {
1046
1047 /* Nothing on free list, put this at head */
1048 px->next = free_list.next;
1049 px->prev = &free_list;
1050 free_list.next = px;
1051 pf = px;
1052 px = NULL;
1053
1054 } else {
1055
1056 /* Find the right spot, leave pf pointing to the modified entry. */
1057
1058 for(pf = free_list.next; pf->end < ptr && pf->next != NULL;
1059 pf = pf->next)
1060 ; /* Race ahead here */
1061
1062 if (pf->page > tail) {
1063 /* Insert before entry */
1064 px->next = pf;
1065 px->prev = pf->prev;
1066 pf->prev = px;
1067 px->prev->next = px;
1068 pf = px;
1069 px = NULL;
1070 } else if (pf->end == ptr ) {
1071 /* Append to the previous entry */
1072 pf->end = (char *)pf->end + l;
1073 pf->size += l;
1074 if (pf->next != NULL && pf->end == pf->next->page ) {
1075 /* And collapse the next too. */
1076 pt = pf->next;
1077 pf->end = pt->end;
1078 pf->size += pt->size;
1079 pf->next = pt->next;
1080 if (pf->next != NULL)
1081 pf->next->prev = pf;
1082 }
1083 } else if (pf->page == tail) {
1084 /* Prepend to entry */
1085 pf->size += l;
1086 pf->page = ptr;
1087 } else if (pf->next == NULL) {
1088 /* Append at tail of chain */
1089 px->next = NULL;
1090 px->prev = pf;
1091 pf->next = px;
1092 pf = px;
1093 px = NULL;
1094 } else {
1095 wrterror("freelist is destroyed\n");
1096 }
1097 }
1098
1099 /* Return something to OS ? */
1100 if (pf->next == NULL && /* If we're the last one, */
1101 pf->size > malloc_cache && /* ..and the cache is full, */
1102 pf->end == malloc_brk && /* ..and none behind us, */
1103 malloc_brk == sbrk(0)) { /* ..and it's OK to do... */
1104
1105 /*
1106 * Keep the cache intact. Notice that the '>' above guarantees that
1107 * the pf will always have at least one page afterwards.
1108 */
1109 pf->end = (char *)pf->page + malloc_cache;
1110 pf->size = malloc_cache;
1111
1112 brk(pf->end);
1113 malloc_brk = pf->end;
1114
1115 index = ptr2index(pf->end);
1116
1117 for(i=index;i <= last_index;)
1118 page_dir[i++] = MALLOC_NOT_MINE;
1119
1120 last_index = index - 1;
1121
1122 /* XXX: We could realloc/shrink the pagedir here I guess. */
1123 }
1124 if (pt != NULL)
1125 ifree(pt);
1126}
1127
1128/*
1129 * Free a chunk, and possibly the page it's on, if the page becomes empty.
1130 */
1131
1132/* ARGSUSED */
1133static __inline__ void
1134free_bytes(void *ptr, int index, struct pginfo *info)
1135{
1136 int i;
1137 struct pginfo **mp;
1138 void *vp;
1139
1140 /* Find the chunk number on the page */
1141 i = ((u_long)ptr & malloc_pagemask) >> info->shift;
1142
1143 if ((u_long)ptr & ((1UL<<(info->shift))-1)) {
1144 wrtwarning("modified (chunk-) pointer\n");
1145 return;
1146 }
1147
1148 if (info->bits[i/MALLOC_BITS] & (1UL<<(i%MALLOC_BITS))) {
1149 wrtwarning("chunk is already free\n");
1150 return;
1151 }
1152
1153 if (malloc_junk && info->size != 0)
1154 memset(ptr, SOME_JUNK, info->size);
1155
1156 info->bits[i/MALLOC_BITS] |= 1UL<<(i%MALLOC_BITS);
1157 info->free++;
1158
1159 if (info->size != 0)
1160 mp = page_dir + info->shift;
1161 else
1162 mp = page_dir;
1163
1164 if (info->free == 1) {
1165
1166 /* Page became non-full */
1167
1168 /* Insert in address order */
1169 while (*mp && (*mp)->next && (*mp)->next->page < info->page)
1170 mp = &(*mp)->next;
1171 info->next = *mp;
1172 *mp = info;
1173 return;
1174 }
1175
1176 if (info->free != info->total)
1177 return;
1178
1179 /* Find & remove this page in the queue */
1180 while (*mp != info) {
1181 mp = &((*mp)->next);
1182#ifdef MALLOC_EXTRA_SANITY
1183 if (!*mp)
1184 wrterror("(ES): Not on queue\n");
1185#endif /* MALLOC_EXTRA_SANITY */
1186 }
1187 *mp = info->next;
1188
1189 /* Free the page & the info structure if need be */
1190 page_dir[ptr2index(info->page)] = MALLOC_FIRST;
1191
1192 /* If the page was mprotected, unprotect it before releasing it */
1193 if (info->size == 0) {
1194 mprotect(info->page, malloc_pagesize, PROT_READ|PROT_WRITE);
1195 /* Do we have to care if mprotect succeeds here ? */
1196 }
1197
1198 vp = info->page; /* Order is important ! */
1199 if(vp != (void*)info)
1200 ifree(info);
1201 ifree(vp);
1202}
1203
1204static void
1205ifree(void *ptr)
1206{
1207 struct pginfo *info;
1208 int index;
1209
1210 /* This is legal */
1211 if (ptr == NULL)
1212 return;
1213
1214 if (!malloc_started) {
1215 wrtwarning("malloc() has never been called\n");
1216 return;
1217 }
1218
1219 /* If we're already sinking, don't make matters any worse. */
1220 if (suicide)
1221 return;
1222
1223 index = ptr2index(ptr);
1224
1225 if (index < malloc_pageshift) {
1226 wrtwarning("junk pointer, too low to make sense\n");
1227 return;
1228 }
1229
1230 if (index > last_index) {
1231 wrtwarning("junk pointer, too high to make sense\n");
1232 return;
1233 }
1234
1235 info = page_dir[index];
1236
1237 if (info < MALLOC_MAGIC)
1238 free_pages(ptr, index, info);
1239 else
1240 free_bytes(ptr, index, info);
1241 return;
1242}
1243
1244/*
1245 * These are the public exported interface routines.
1246 */
1247
1248static int malloc_active;
1249
1250void *
1251malloc(size_t size)
1252{
1253 void *r;
1254
1255 _MALLOC_LOCK();
1256 malloc_func = " in malloc():";
1257 if (malloc_active++) {
1258 wrtwarning("recursive call\n");
1259 malloc_active--;
1260 _MALLOC_UNLOCK();
1261 errno = EDEADLK;
1262 return (NULL);
1263 }
1264 r = imalloc(size);
1265 UTRACE(0, size, r);
1266 malloc_active--;
1267 _MALLOC_UNLOCK();
1268 if (malloc_xmalloc && r == NULL)
1269 wrterror("out of memory\n");
1270 return (r);
1271}
1272
1273void
1274free(void *ptr)
1275{
1276 _MALLOC_LOCK();
1277 malloc_func = " in free():";
1278 if (malloc_active++) {
1279 wrtwarning("recursive call\n");
1280 malloc_active--;
1281 _MALLOC_UNLOCK();
1282 errno = EDEADLK;
1283 return;
1284 }
1285 ifree(ptr);
1286 UTRACE(ptr, 0, 0);
1287 malloc_active--;
1288 _MALLOC_UNLOCK();
1289 return;
1290}
1291
1292void *
1293realloc(void *ptr, size_t size)
1294{
1295 void *r;
1296
1297 _MALLOC_LOCK();
1298 malloc_func = " in realloc():";
1299 if (malloc_active++) {
1300 wrtwarning("recursive call\n");
1301 malloc_active--;
1302 _MALLOC_UNLOCK();
1303 errno = EDEADLK;
1304 return (NULL);
1305 }
1306 if (ptr == NULL) {
1307 r = imalloc(size);
1308 } else {
1309 r = irealloc(ptr, size);
1310 }
1311 UTRACE(ptr, size, r);
1312 malloc_active--;
1313 _MALLOC_UNLOCK();
1314 if (malloc_xmalloc && r == NULL)
1315 wrterror("out of memory\n");
1316 return (r);
1317}
diff --git a/src/lib/libc/stdlib/memory.3 b/src/lib/libc/stdlib/memory.3
new file mode 100644
index 0000000000..84996f76c3
--- /dev/null
+++ b/src/lib/libc/stdlib/memory.3
@@ -0,0 +1,65 @@
1.\" Copyright (c) 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: memory.3,v 1.6 2003/06/02 20:18:38 millert Exp $
29.\"
30.Dd May 2, 1991
31.Dt MEMORY 3
32.Os
33.Sh NAME
34.Nm malloc ,
35.Nm free ,
36.Nm realloc ,
37.Nm calloc ,
38.Nm alloca
39.Nd general memory allocation operations
40.Sh SYNOPSIS
41.Fd #include <stdlib.h>
42.Ft void *
43.Fn malloc "size_t size"
44.Ft void
45.Fn free "void *ptr"
46.Ft void *
47.Fn realloc "void *ptr" "size_t size"
48.Ft void *
49.Fn calloc "size_t nelem" "size_t elsize"
50.Ft void *
51.Fn alloca "size_t size"
52.Sh DESCRIPTION
53These functions allocate and free memory for the calling process.
54They are described in the individual man pages.
55.Sh SEE ALSO
56.Xr alloca 3 ,
57.Xr calloc 3 ,
58.Xr free 3 ,
59.Xr malloc 3 ,
60.Xr realloc 3
61.Sh STANDARDS
62These functions, with the exception of
63.Fn alloca ,
64conform to
65.St -ansiC .
diff --git a/src/lib/libc/stdlib/merge.c b/src/lib/libc/stdlib/merge.c
new file mode 100644
index 0000000000..1826acc369
--- /dev/null
+++ b/src/lib/libc/stdlib/merge.c
@@ -0,0 +1,343 @@
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.6 2003/06/02 20:18:38 millert 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(base, nmemb, size, cmp)
95 void *base;
96 size_t nmemb;
97 register size_t size;
98 int (*cmp)(const void *, const void *);
99{
100 register int i, sense;
101 int big, iflag;
102 register u_char *f1, *f2, *t, *b, *tp2, *q, *l1, *l2;
103 u_char *list2, *list1, *p2, *p, *last, **p1;
104
105 if (size < PSIZE / 2) { /* Pointers must fit into 2 * size. */
106 errno = EINVAL;
107 return (-1);
108 }
109
110 /*
111 * XXX
112 * Stupid subtraction for the Cray.
113 */
114 iflag = 0;
115 if (!(size % ISIZE) && !(((char *)base - (char *)0) % ISIZE))
116 iflag = 1;
117
118 if ((list2 = malloc(nmemb * size + PSIZE)) == NULL)
119 return (-1);
120
121 list1 = base;
122 setup(list1, list2, nmemb, size, cmp);
123 last = list2 + nmemb * size;
124 i = big = 0;
125 while (*EVAL(list2) != last) {
126 l2 = list1;
127 p1 = EVAL(list1);
128 for (tp2 = p2 = list2; p2 != last; p1 = EVAL(l2)) {
129 p2 = *EVAL(p2);
130 f1 = l2;
131 f2 = l1 = list1 + (p2 - list2);
132 if (p2 != last)
133 p2 = *EVAL(p2);
134 l2 = list1 + (p2 - list2);
135 while (f1 < l1 && f2 < l2) {
136 if ((*cmp)(f1, f2) <= 0) {
137 q = f2;
138 b = f1, t = l1;
139 sense = -1;
140 } else {
141 q = f1;
142 b = f2, t = l2;
143 sense = 0;
144 }
145 if (!big) { /* here i = 0 */
146 while ((b += size) < t && cmp(q, b) >sense)
147 if (++i == 6) {
148 big = 1;
149 goto EXPONENTIAL;
150 }
151 } else {
152EXPONENTIAL: for (i = size; ; i <<= 1)
153 if ((p = (b + i)) >= t) {
154 if ((p = t - size) > b &&
155 (*cmp)(q, p) <= sense)
156 t = p;
157 else
158 b = p;
159 break;
160 } else if ((*cmp)(q, p) <= sense) {
161 t = p;
162 if (i == size)
163 big = 0;
164 goto FASTCASE;
165 } else
166 b = p;
167 while (t > b+size) {
168 i = (((t - b) / size) >> 1) * size;
169 if ((*cmp)(q, p = b + i) <= sense)
170 t = p;
171 else
172 b = p;
173 }
174 goto COPY;
175FASTCASE: while (i > size)
176 if ((*cmp)(q,
177 p = b + (i >>= 1)) <= sense)
178 t = p;
179 else
180 b = p;
181COPY: b = t;
182 }
183 i = size;
184 if (q == f1) {
185 if (iflag) {
186 ICOPY_LIST(f2, tp2, b);
187 ICOPY_ELT(f1, tp2, i);
188 } else {
189 CCOPY_LIST(f2, tp2, b);
190 CCOPY_ELT(f1, tp2, i);
191 }
192 } else {
193 if (iflag) {
194 ICOPY_LIST(f1, tp2, b);
195 ICOPY_ELT(f2, tp2, i);
196 } else {
197 CCOPY_LIST(f1, tp2, b);
198 CCOPY_ELT(f2, tp2, i);
199 }
200 }
201 }
202 if (f2 < l2) {
203 if (iflag)
204 ICOPY_LIST(f2, tp2, l2);
205 else
206 CCOPY_LIST(f2, tp2, l2);
207 } else if (f1 < l1) {
208 if (iflag)
209 ICOPY_LIST(f1, tp2, l1);
210 else
211 CCOPY_LIST(f1, tp2, l1);
212 }
213 *p1 = l2;
214 }
215 tp2 = list1; /* swap list1, list2 */
216 list1 = list2;
217 list2 = tp2;
218 last = list2 + nmemb*size;
219 }
220 if (base == list2) {
221 memmove(list2, list1, nmemb*size);
222 list2 = list1;
223 }
224 free(list2);
225 return (0);
226}
227
228#define swap(a, b) { \
229 s = b; \
230 i = size; \
231 do { \
232 tmp = *a; *a++ = *s; *s++ = tmp; \
233 } while (--i); \
234 a -= size; \
235 }
236#define reverse(bot, top) { \
237 s = top; \
238 do { \
239 i = size; \
240 do { \
241 tmp = *bot; *bot++ = *s; *s++ = tmp; \
242 } while (--i); \
243 s -= size2; \
244 } while(bot < s); \
245}
246
247/*
248 * Optional hybrid natural/pairwise first pass. Eats up list1 in runs of
249 * increasing order, list2 in a corresponding linked list. Checks for runs
250 * when THRESHOLD/2 pairs compare with same sense. (Only used when NATURAL
251 * is defined. Otherwise simple pairwise merging is used.)
252 */
253void
254setup(list1, list2, n, size, cmp)
255 size_t n, size;
256 int (*cmp)(const void *, const void *);
257 u_char *list1, *list2;
258{
259 int i, length, size2, tmp, sense;
260 u_char *f1, *f2, *s, *l2, *last, *p2;
261
262 size2 = size*2;
263 if (n <= 5) {
264 insertionsort(list1, n, size, cmp);
265 *EVAL(list2) = (u_char*) list2 + n*size;
266 return;
267 }
268 /*
269 * Avoid running pointers out of bounds; limit n to evens
270 * for simplicity.
271 */
272 i = 4 + (n & 1);
273 insertionsort(list1 + (n - i) * size, i, size, cmp);
274 last = list1 + size * (n - i);
275 *EVAL(list2 + (last - list1)) = list2 + n * size;
276
277#ifdef NATURAL
278 p2 = list2;
279 f1 = list1;
280 sense = (cmp(f1, f1 + size) > 0);
281 for (; f1 < last; sense = !sense) {
282 length = 2;
283 /* Find pairs with same sense. */
284 for (f2 = f1 + size2; f2 < last; f2 += size2) {
285 if ((cmp(f2, f2+ size) > 0) != sense)
286 break;
287 length += 2;
288 }
289 if (length < THRESHOLD) { /* Pairwise merge */
290 do {
291 p2 = *EVAL(p2) = f1 + size2 - list1 + list2;
292 if (sense > 0)
293 swap (f1, f1 + size);
294 } while ((f1 += size2) < f2);
295 } else { /* Natural merge */
296 l2 = f2;
297 for (f2 = f1 + size2; f2 < l2; f2 += size2) {
298 if ((cmp(f2-size, f2) > 0) != sense) {
299 p2 = *EVAL(p2) = f2 - list1 + list2;
300 if (sense > 0)
301 reverse(f1, f2-size);
302 f1 = f2;
303 }
304 }
305 if (sense > 0)
306 reverse (f1, f2-size);
307 f1 = f2;
308 if (f2 < last || cmp(f2 - size, f2) > 0)
309 p2 = *EVAL(p2) = f2 - list1 + list2;
310 else
311 p2 = *EVAL(p2) = list2 + n*size;
312 }
313 }
314#else /* pairwise merge only. */
315 for (f1 = list1, p2 = list2; f1 < last; f1 += size2) {
316 p2 = *EVAL(p2) = p2 + size2;
317 if (cmp (f1, f1 + size) > 0)
318 swap(f1, f1 + size);
319 }
320#endif /* NATURAL */
321}
322
323/*
324 * This is to avoid out-of-bounds addresses in sorting the
325 * last 4 elements.
326 */
327static void
328insertionsort(a, n, size, cmp)
329 u_char *a;
330 size_t n, size;
331 int (*cmp)(const void *, const void *);
332{
333 u_char *ai, *s, *t, *u, tmp;
334 int i;
335
336 for (ai = a+size; --n >= 1; ai += size)
337 for (t = ai; t > a; t -= size) {
338 u = t - size;
339 if (cmp(u, t) <= 0)
340 break;
341 swap(u, t);
342 }
343}
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..1789e686ef
--- /dev/null
+++ b/src/lib/libc/stdlib/putenv.c
@@ -0,0 +1,54 @@
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.3 2003/06/02 20:18:38 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35#include <string.h>
36
37int
38putenv(str)
39 const char *str;
40{
41 char *p, *equal;
42 int rval;
43
44 if ((p = strdup(str)) == NULL)
45 return (-1);
46 if ((equal = strchr(p, '=')) == NULL) {
47 (void)free(p);
48 return (-1);
49 }
50 *equal = '\0';
51 rval = setenv(p, equal + 1, 1);
52 (void)free(p);
53 return (rval);
54}
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..296d2d4742
--- /dev/null
+++ b/src/lib/libc/stdlib/qabs.c
@@ -0,0 +1,41 @@
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.3 2003/06/02 20:18:38 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <stdlib.h>
35
36quad_t
37qabs(j)
38 quad_t j;
39{
40 return(j < 0 ? -j : j);
41}
diff --git a/src/lib/libc/stdlib/qdiv.3 b/src/lib/libc/stdlib/qdiv.3
new file mode 100644
index 0000000000..597f951a99
--- /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.5 2003/06/02 20:18:38 millert 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 No / 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..6688ccb712
--- /dev/null
+++ b/src/lib/libc/stdlib/qdiv.c
@@ -0,0 +1,54 @@
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.3 2003/06/02 20:18:38 millert Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37#include <stdlib.h> /* qdiv_t */
38
39qdiv_t
40qdiv(num, denom)
41 quad_t num, denom;
42{
43 qdiv_t r;
44
45 /* see div.c for comments */
46
47 r.quot = num / denom;
48 r.rem = num % denom;
49 if (num >= 0 && r.rem < 0) {
50 r.quot++;
51 r.rem -= denom;
52 }
53 return (r);
54}
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..2a972c0eb0
--- /dev/null
+++ b/src/lib/libc/stdlib/qsort.c
@@ -0,0 +1,171 @@
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.8 2003/06/02 20:18:38 millert 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 (*)());
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 register TYPE *pi = (TYPE *) (parmi); \
48 register TYPE *pj = (TYPE *) (parmj); \
49 do { \
50 register 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(a, b, n, swaptype)
61 char *a, *b;
62 int n, swaptype;
63{
64 if (swaptype <= 1)
65 swapcode(long, a, b, n)
66 else
67 swapcode(char, a, b, n)
68}
69
70#define swap(a, b) \
71 if (swaptype == 0) { \
72 long t = *(long *)(a); \
73 *(long *)(a) = *(long *)(b); \
74 *(long *)(b) = t; \
75 } else \
76 swapfunc(a, b, es, swaptype)
77
78#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
79
80static __inline char *
81med3(a, b, c, cmp)
82 char *a, *b, *c;
83 int (*cmp)();
84{
85 return cmp(a, b) < 0 ?
86 (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))
87 :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ));
88}
89
90void
91qsort(aa, n, es, cmp)
92 void *aa;
93 size_t n, es;
94 int (*cmp)();
95{
96 char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
97 int d, r, swaptype, swap_cnt;
98 register char *a = aa;
99
100loop: SWAPINIT(a, es);
101 swap_cnt = 0;
102 if (n < 7) {
103 for (pm = (char *)a + es; pm < (char *) a + n * es; pm += es)
104 for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
105 pl -= es)
106 swap(pl, pl - es);
107 return;
108 }
109 pm = (char *)a + (n / 2) * es;
110 if (n > 7) {
111 pl = (char *)a;
112 pn = (char *)a + (n - 1) * es;
113 if (n > 40) {
114 d = (n / 8) * es;
115 pl = med3(pl, pl + d, pl + 2 * d, cmp);
116 pm = med3(pm - d, pm, pm + d, cmp);
117 pn = med3(pn - 2 * d, pn - d, pn, cmp);
118 }
119 pm = med3(pl, pm, pn, cmp);
120 }
121 swap(a, pm);
122 pa = pb = (char *)a + es;
123
124 pc = pd = (char *)a + (n - 1) * es;
125 for (;;) {
126 while (pb <= pc && (r = cmp(pb, a)) <= 0) {
127 if (r == 0) {
128 swap_cnt = 1;
129 swap(pa, pb);
130 pa += es;
131 }
132 pb += es;
133 }
134 while (pb <= pc && (r = cmp(pc, a)) >= 0) {
135 if (r == 0) {
136 swap_cnt = 1;
137 swap(pc, pd);
138 pd -= es;
139 }
140 pc -= es;
141 }
142 if (pb > pc)
143 break;
144 swap(pb, pc);
145 swap_cnt = 1;
146 pb += es;
147 pc -= es;
148 }
149 if (swap_cnt == 0) { /* Switch to insertion sort */
150 for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
151 for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
152 pl -= es)
153 swap(pl, pl - es);
154 return;
155 }
156
157 pn = (char *)a + n * es;
158 r = min(pa - (char *)a, pb - pa);
159 vecswap(a, pb - r, r);
160 r = min(pd - pc, pn - pd - es);
161 vecswap(pb, pn - r, r);
162 if ((r = pb - pa) > es)
163 qsort(a, r / es, es, cmp);
164 if ((r = pd - pc) > es) {
165 /* Iterate rather than recurse to save stack space */
166 a = pn - r;
167 n = r / es;
168 goto loop;
169 }
170/* qsort(pn - r, r / es, es, cmp);*/
171}
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..1ff30416d9
--- /dev/null
+++ b/src/lib/libc/stdlib/radixsort.c
@@ -0,0 +1,313 @@
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.6 2003/06/02 20:18:38 millert 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(a, n, tab, endch)
89 const u_char **a, *tab;
90 int n;
91 u_int endch;
92{
93 const u_char *tr;
94 int c;
95 u_char tr0[256];
96
97 SETUP;
98 r_sort_a(a, n, 0, tr, endch);
99 return (0);
100}
101
102int
103sradixsort(a, n, tab, endch)
104 const u_char **a, *tab;
105 int n;
106 u_int endch;
107{
108 const u_char *tr, **ta;
109 int c;
110 u_char tr0[256];
111
112 SETUP;
113 if (n < THRESHOLD)
114 simplesort(a, n, 0, tr, endch);
115 else {
116 if ((ta = malloc(n * sizeof(a))) == NULL)
117 return (-1);
118 r_sort_b(a, ta, n, 0, tr, endch);
119 free(ta);
120 }
121 return (0);
122}
123
124#define empty(s) (s >= sp)
125#define pop(a, n, i) a = (--sp)->sa, n = sp->sn, i = sp->si
126#define push(a, n, i) sp->sa = a, sp->sn = n, (sp++)->si = i
127#define swap(a, b, t) t = a, a = b, b = t
128
129/* Unstable, in-place sort. */
130void
131r_sort_a(a, n, i, tr, endch)
132 const u_char **a;
133 int n, i;
134 const u_char *tr;
135 u_int endch;
136{
137 static int count[256], nc, bmin;
138 register int c;
139 register const u_char **ak, *r;
140 stack s[SIZE], *sp, *sp0, *sp1, temp;
141 int *cp, bigc;
142 const u_char **an, *t, **aj, **top[256];
143
144 /* Set up stack. */
145 sp = s;
146 push(a, n, i);
147 while (!empty(s)) {
148 pop(a, n, i);
149 if (n < THRESHOLD) {
150 simplesort(a, n, i, tr, endch);
151 continue;
152 }
153 an = a + n;
154
155 /* Make character histogram. */
156 if (nc == 0) {
157 bmin = 255; /* First occupied bin, excluding eos. */
158 for (ak = a; ak < an;) {
159 c = tr[(*ak++)[i]];
160 if (++count[c] == 1 && c != endch) {
161 if (c < bmin)
162 bmin = c;
163 nc++;
164 }
165 }
166 if (sp + nc > s + SIZE) { /* Get more stack. */
167 r_sort_a(a, n, i, tr, endch);
168 continue;
169 }
170 }
171
172 /*
173 * Set top[]; push incompletely sorted bins onto stack.
174 * top[] = pointers to last out-of-place element in bins.
175 * count[] = counts of elements in bins.
176 * Before permuting: top[c-1] + count[c] = top[c];
177 * during deal: top[c] counts down to top[c-1].
178 */
179 sp0 = sp1 = sp; /* Stack position of biggest bin. */
180 bigc = 2; /* Size of biggest bin. */
181 if (endch == 0) /* Special case: set top[eos]. */
182 top[0] = ak = a + count[0];
183 else {
184 ak = a;
185 top[255] = an;
186 }
187 for (cp = count + bmin; nc > 0; cp++) {
188 while (*cp == 0) /* Find next non-empty pile. */
189 cp++;
190 if (*cp > 1) {
191 if (*cp > bigc) {
192 bigc = *cp;
193 sp1 = sp;
194 }
195 push(ak, *cp, i+1);
196 }
197 top[cp-count] = ak += *cp;
198 nc--;
199 }
200 swap(*sp0, *sp1, temp); /* Play it safe -- biggest bin last. */
201
202 /*
203 * Permute misplacements home. Already home: everything
204 * before aj, and in bin[c], items from top[c] on.
205 * Inner loop:
206 * r = next element to put in place;
207 * ak = top[r[i]] = location to put the next element.
208 * aj = bottom of 1st disordered bin.
209 * Outer loop:
210 * Once the 1st disordered bin is done, ie. aj >= ak,
211 * aj<-aj + count[c] connects the bins in a linked list;
212 * reset count[c].
213 */
214 for (aj = a; aj < an; *aj = r, aj += count[c], count[c] = 0)
215 for (r = *aj; aj < (ak = --top[c = tr[r[i]]]);)
216 swap(*ak, r, t);
217 }
218}
219
220/* Stable sort, requiring additional memory. */
221void
222r_sort_b(a, ta, n, i, tr, endch)
223 const u_char **a, **ta;
224 int n, i;
225 const u_char *tr;
226 u_int endch;
227{
228 static int count[256], nc, bmin;
229 register int c;
230 register const u_char **ak, **ai;
231 stack s[512], *sp, *sp0, *sp1, temp;
232 const u_char **top[256];
233 int *cp, bigc;
234
235 sp = s;
236 push(a, n, i);
237 while (!empty(s)) {
238 pop(a, n, i);
239 if (n < THRESHOLD) {
240 simplesort(a, n, i, tr, endch);
241 continue;
242 }
243
244 if (nc == 0) {
245 bmin = 255;
246 for (ak = a + n; --ak >= a;) {
247 c = tr[(*ak)[i]];
248 if (++count[c] == 1 && c != endch) {
249 if (c < bmin)
250 bmin = c;
251 nc++;
252 }
253 }
254 if (sp + nc > s + SIZE) {
255 r_sort_b(a, ta, n, i, tr, endch);
256 continue;
257 }
258 }
259
260 sp0 = sp1 = sp;
261 bigc = 2;
262 if (endch == 0) {
263 top[0] = ak = a + count[0];
264 count[0] = 0;
265 } else {
266 ak = a;
267 top[255] = a + n;
268 count[255] = 0;
269 }
270 for (cp = count + bmin; nc > 0; cp++) {
271 while (*cp == 0)
272 cp++;
273 if ((c = *cp) > 1) {
274 if (c > bigc) {
275 bigc = c;
276 sp1 = sp;
277 }
278 push(ak, c, i+1);
279 }
280 top[cp-count] = ak += c;
281 *cp = 0; /* Reset count[]. */
282 nc--;
283 }
284 swap(*sp0, *sp1, temp);
285
286 for (ak = ta + n, ai = a+n; ak > ta;) /* Copy to temp. */
287 *--ak = *--ai;
288 for (ak = ta+n; --ak >= ta;) /* Deal to piles. */
289 *--top[tr[(*ak)[i]]] = *ak;
290 }
291}
292
293static __inline void
294simplesort(a, n, b, tr, endch) /* insertion sort */
295 register const u_char **a;
296 int n, b;
297 register const u_char *tr;
298 u_int endch;
299{
300 register u_char ch;
301 const u_char **ak, **ai, *s, *t;
302
303 for (ak = a+1; --n >= 1; ak++)
304 for (ai = ak; ai > a; ai--) {
305 for (s = ai[0] + b, t = ai[-1] + b;
306 (ch = tr[*s]) != endch; s++, t++)
307 if (ch != tr[*t])
308 break;
309 if (ch >= tr[*t])
310 break;
311 swap(ai[0], ai[-1], s);
312 }
313}
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..d58d040ad5
--- /dev/null
+++ b/src/lib/libc/stdlib/rand.c
@@ -0,0 +1,61 @@
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.7 2003/06/02 20:18:38 millert 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(seed)
41u_int *seed;
42{
43
44 *seed = *seed * 1103515245 + 12345;
45 return (*seed % ((u_int)RAND_MAX + 1));
46}
47
48int
49rand()
50{
51
52 return (rand_r(&next));
53}
54
55void
56srand(seed)
57u_int seed;
58{
59
60 next = seed;
61}
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..4807d2f27d
--- /dev/null
+++ b/src/lib/libc/stdlib/random.c
@@ -0,0 +1,430 @@
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.12 2003/06/02 20:18:38 millert 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(x)
194 unsigned int x;
195{
196 int i;
197 int32_t test;
198 div_t val;
199
200 if (rand_type == TYPE_0)
201 state[0] = x;
202 else {
203 state[0] = x;
204 for (i = 1; i < rand_deg; i++) {
205 /*
206 * Implement the following, without overflowing 31 bits:
207 *
208 * state[i] = (16807 * state[i - 1]) % 2147483647;
209 *
210 * 2^31-1 (prime) = 2147483647 = 127773*16807+2836
211 */
212 val = div(state[i-1], 127773);
213 test = 16807 * val.rem - 2836 * val.quot;
214 state[i] = test + (test < 0 ? 2147483647 : 0);
215 }
216 fptr = &state[rand_sep];
217 rptr = &state[0];
218 for (i = 0; i < 10 * rand_deg; i++)
219 (void)random();
220 }
221}
222
223/*
224 * srandomdev:
225 *
226 * Many programs choose the seed value in a totally predictable manner.
227 * This often causes problems. We seed the generator using the much more
228 * secure arandom(4) interface. Note that this particular seeding
229 * procedure can generate states which are impossible to reproduce by
230 * calling srandom() with any value, since the succeeding terms in the
231 * state buffer are no longer derived from the LC algorithm applied to
232 * a fixed seed.
233 */
234void
235srandomdev()
236{
237 int fd, i, mib[2], n;
238 size_t len;
239
240 if (rand_type == TYPE_0)
241 len = sizeof(state[0]);
242 else
243 len = rand_deg * sizeof(state[0]);
244
245 /*
246 * To get seed data, first try reading from /dev/arandom.
247 * If that fails, try the KERN_ARND sysctl() (one int at a time).
248 * As a last resort, call srandom().
249 */
250 if ((fd = open("/dev/arandom", O_RDONLY, 0)) != -1 &&
251 read(fd, (void *) state, len) == (ssize_t) len) {
252 close(fd);
253 } else {
254 if (fd != -1)
255 close(fd);
256 mib[0] = CTL_KERN;
257 mib[1] = KERN_ARND;
258 n = len / sizeof(int);
259 len = sizeof(int);
260 for (i = 0; i < n; i++) {
261 if (sysctl(mib, 2, (char *)((int *)state + i), &len,
262 NULL, 0) == -1)
263 break;
264 }
265 if (i != n) {
266 struct timeval tv;
267 u_int junk;
268
269 /* XXX - this could be better */
270 gettimeofday(&tv, NULL);
271 srandom(getpid() ^ tv.tv_sec ^ tv.tv_usec ^ junk);
272 return;
273 }
274 }
275
276 if (rand_type != TYPE_0) {
277 fptr = &state[rand_sep];
278 rptr = &state[0];
279 }
280}
281
282/*
283 * initstate:
284 *
285 * Initialize the state information in the given array of n bytes for future
286 * random number generation. Based on the number of bytes we are given, and
287 * the break values for the different R.N.G.'s, we choose the best (largest)
288 * one we can and set things up for it. srandom() is then called to
289 * initialize the state information.
290 *
291 * Note that on return from srandom(), we set state[-1] to be the type
292 * multiplexed with the current value of the rear pointer; this is so
293 * successive calls to initstate() won't lose this information and will be
294 * able to restart with setstate().
295 *
296 * Note: the first thing we do is save the current state, if any, just like
297 * setstate() so that it doesn't matter when initstate is called.
298 *
299 * Returns a pointer to the old state.
300 */
301char *
302initstate(seed, arg_state, n)
303 u_int seed; /* seed for R.N.G. */
304 char *arg_state; /* pointer to state array */
305 size_t n; /* # bytes of state info */
306{
307 char *ostate = (char *)(&state[-1]);
308
309 if (rand_type == TYPE_0)
310 state[-1] = rand_type;
311 else
312 state[-1] = MAX_TYPES * (rptr - state) + rand_type;
313 if (n < BREAK_0)
314 return(NULL);
315 if (n < BREAK_1) {
316 rand_type = TYPE_0;
317 rand_deg = DEG_0;
318 rand_sep = SEP_0;
319 } else if (n < BREAK_2) {
320 rand_type = TYPE_1;
321 rand_deg = DEG_1;
322 rand_sep = SEP_1;
323 } else if (n < BREAK_3) {
324 rand_type = TYPE_2;
325 rand_deg = DEG_2;
326 rand_sep = SEP_2;
327 } else if (n < BREAK_4) {
328 rand_type = TYPE_3;
329 rand_deg = DEG_3;
330 rand_sep = SEP_3;
331 } else {
332 rand_type = TYPE_4;
333 rand_deg = DEG_4;
334 rand_sep = SEP_4;
335 }
336 state = &(((int32_t *)arg_state)[1]); /* first location */
337 end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */
338 srandom(seed);
339 if (rand_type == TYPE_0)
340 state[-1] = rand_type;
341 else
342 state[-1] = MAX_TYPES*(rptr - state) + rand_type;
343 return(ostate);
344}
345
346/*
347 * setstate:
348 *
349 * Restore the state from the given state array.
350 *
351 * Note: it is important that we also remember the locations of the pointers
352 * in the current state information, and restore the locations of the pointers
353 * from the old state information. This is done by multiplexing the pointer
354 * location into the zeroeth word of the state information.
355 *
356 * Note that due to the order in which things are done, it is OK to call
357 * setstate() with the same state as the current state.
358 *
359 * Returns a pointer to the old state information.
360 */
361char *
362setstate(arg_state)
363 const char *arg_state;
364{
365 int32_t *new_state = (int32_t *)arg_state;
366 int32_t type = new_state[0] % MAX_TYPES;
367 int32_t rear = new_state[0] / MAX_TYPES;
368 char *ostate = (char *)(&state[-1]);
369
370 if (rand_type == TYPE_0)
371 state[-1] = rand_type;
372 else
373 state[-1] = MAX_TYPES * (rptr - state) + rand_type;
374 switch(type) {
375 case TYPE_0:
376 case TYPE_1:
377 case TYPE_2:
378 case TYPE_3:
379 case TYPE_4:
380 rand_type = type;
381 rand_deg = degrees[type];
382 rand_sep = seps[type];
383 break;
384 default:
385 return(NULL);
386 }
387 state = &new_state[1];
388 if (rand_type != TYPE_0) {
389 rptr = &state[rear];
390 fptr = &state[(rear + rand_sep) % rand_deg];
391 }
392 end_ptr = &state[rand_deg]; /* set end_ptr too */
393 return(ostate);
394}
395
396/*
397 * random:
398 *
399 * If we are using the trivial TYPE_0 R.N.G., just do the old linear
400 * congruential bit. Otherwise, we do our fancy trinomial stuff, which is
401 * the same in all the other cases due to all the global variables that have
402 * been set up. The basic operation is to add the number at the rear pointer
403 * into the one at the front pointer. Then both pointers are advanced to
404 * the next location cyclically in the table. The value returned is the sum
405 * generated, reduced to 31 bits by throwing away the "least random" low bit.
406 *
407 * Note: the code takes advantage of the fact that both the front and
408 * rear pointers can't wrap on the same call by not testing the rear
409 * pointer if the front one has wrapped.
410 *
411 * Returns a 31-bit random number.
412 */
413long
414random()
415{
416 int32_t i;
417
418 if (rand_type == TYPE_0)
419 i = state[0] = (state[0] * 1103515245 + 12345) & 0x7fffffff;
420 else {
421 *fptr += *rptr;
422 i = (*fptr >> 1) & 0x7fffffff; /* chucking least random bit */
423 if (++fptr >= end_ptr) {
424 fptr = state;
425 ++rptr;
426 } else if (++rptr >= end_ptr)
427 rptr = state;
428 }
429 return((long)i);
430}
diff --git a/src/lib/libc/stdlib/realpath.3 b/src/lib/libc/stdlib/realpath.3
new file mode 100644
index 0000000000..b8093b51e1
--- /dev/null
+++ b/src/lib/libc/stdlib/realpath.3
@@ -0,0 +1,120 @@
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.10 2003/06/02 20:18:38 millert 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 resolvedname[MAXPATHLEN]"
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 resolvedname .
57The
58.Fa resolvedname
59argument
60.Em must
61refer to a buffer capable of storing at least
62.Dv MAXPATHLEN
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 resolvedname
80on success.
81If an error occurs,
82.Fn realpath
83returns
84.Dv NULL ,
85and
86.Fa resolvedname
87contains the pathname which caused the problem.
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 chdir 2 ,
95.Xr close 2 ,
96.Xr fchdir 2 ,
97.Xr lstat 2 ,
98.Xr open 2 ,
99.Xr readlink 2 ,
100and
101.Xr getcwd 3 .
102.Sh SEE ALSO
103.Xr getcwd 3
104.Sh HISTORY
105The
106.Fn realpath
107function call first appeared in
108.Bx 4.4 .
109.Sh CAVEATS
110This implementation of
111.Fn realpath
112differs slightly from the Solaris implementation.
113The
114.Bx 4.4
115version always returns absolute pathnames,
116whereas the Solaris implementation will,
117under certain circumstances, return a relative
118.Fa resolvedname
119when given a relative
120.Fa pathname .
diff --git a/src/lib/libc/stdlib/realpath.c b/src/lib/libc/stdlib/realpath.c
new file mode 100644
index 0000000000..1525d0372f
--- /dev/null
+++ b/src/lib/libc/stdlib/realpath.c
@@ -0,0 +1,162 @@
1/*
2 * Copyright (c) 1994
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Jan-Simon Pendry.
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: realpath.c,v 1.10 2003/08/01 21:04:59 millert Exp $";
35#endif /* LIBC_SCCS and not lint */
36
37#include <sys/param.h>
38#include <sys/stat.h>
39
40#include <errno.h>
41#include <fcntl.h>
42#include <stdlib.h>
43#include <string.h>
44#include <unistd.h>
45
46/*
47 * char *realpath(const char *path, char resolved_path[MAXPATHLEN]);
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(path, resolved)
55 const char *path;
56 char *resolved;
57{
58 struct stat sb;
59 int fd, n, needslash, serrno;
60 char *p, *q, wbuf[MAXPATHLEN];
61 int symlinks = 0;
62
63 /* Save the starting point. */
64 if ((fd = open(".", O_RDONLY)) < 0) {
65 (void)strlcpy(resolved, ".", MAXPATHLEN);
66 return (NULL);
67 }
68
69 /* Convert "." -> "" to optimize away a needless lstat() and chdir() */
70 if (path[0] == '.' && path[1] == '\0')
71 path = "";
72
73 /*
74 * Find the dirname and basename from the path to be resolved.
75 * Change directory to the dirname component.
76 * lstat the basename part.
77 * if it is a symlink, read in the value and loop.
78 * if it is a directory, then change to that directory.
79 * get the current directory name and append the basename.
80 */
81 strlcpy(resolved, path, MAXPATHLEN);
82loop:
83 q = strrchr(resolved, '/');
84 if (q != NULL) {
85 p = q + 1;
86 if (q == resolved)
87 q = "/";
88 else {
89 do {
90 --q;
91 } while (q > resolved && *q == '/');
92 q[1] = '\0';
93 q = resolved;
94 }
95 if (chdir(q) < 0)
96 goto err1;
97 } else
98 p = resolved;
99
100 /* Deal with the last component. */
101 if (*p != '\0' && lstat(p, &sb) == 0) {
102 if (S_ISLNK(sb.st_mode)) {
103 if (++symlinks > MAXSYMLINKS) {
104 errno = ELOOP;
105 goto err1;
106 }
107 n = readlink(p, resolved, MAXPATHLEN-1);
108 if (n < 0)
109 goto err1;
110 resolved[n] = '\0';
111 goto loop;
112 }
113 if (S_ISDIR(sb.st_mode)) {
114 if (chdir(p) < 0)
115 goto err1;
116 p = "";
117 }
118 }
119
120 /*
121 * Save the last component name and get the full pathname of
122 * the current directory.
123 */
124 (void)strlcpy(wbuf, p, sizeof wbuf);
125 if (getcwd(resolved, MAXPATHLEN) == 0)
126 goto err1;
127
128 /*
129 * Join the two strings together, ensuring that the right thing
130 * happens if the last component is empty, or the dirname is root.
131 */
132 if (resolved[0] == '/' && resolved[1] == '\0')
133 needslash = 0;
134 else
135 needslash = 1;
136
137 if (*wbuf) {
138 if (strlen(resolved) + strlen(wbuf) + needslash >= MAXPATHLEN) {
139 errno = ENAMETOOLONG;
140 goto err1;
141 }
142 if (needslash)
143 strlcat(resolved, "/", MAXPATHLEN);
144 strlcat(resolved, wbuf, MAXPATHLEN);
145 }
146
147 /* Go back to where we came from. */
148 if (fchdir(fd) < 0) {
149 serrno = errno;
150 goto err2;
151 }
152
153 /* It's okay if the close fails, what's an fd more or less? */
154 (void)close(fd);
155 return (resolved);
156
157err1: serrno = errno;
158 (void)fchdir(fd);
159err2: (void)close(fd);
160 errno = serrno;
161 return (NULL);
162}
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..2ba072b65c
--- /dev/null
+++ b/src/lib/libc/stdlib/setenv.c
@@ -0,0 +1,118 @@
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.6 2003/06/02 20:18:38 millert 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 * setenv --
41 * Set the value of the environmental variable "name" to be
42 * "value". If rewrite is set, replace any current value.
43 */
44int
45setenv(name, value, rewrite)
46 register const char *name;
47 register const char *value;
48 int rewrite;
49{
50 extern char **environ;
51 static int alloced; /* if allocated space before */
52 register char *C;
53 int l_value, offset;
54
55 if (*value == '=') /* no `=' in value */
56 ++value;
57 l_value = strlen(value);
58 if ((C = __findenv(name, &offset))) { /* find if already exists */
59 if (!rewrite)
60 return (0);
61 if (strlen(C) >= l_value) { /* old larger; copy over */
62 while ((*C++ = *value++))
63 ;
64 return (0);
65 }
66 } else { /* create new slot */
67 register int cnt;
68 register char **P;
69
70 for (P = environ, cnt = 0; *P; ++P, ++cnt);
71 if (alloced) { /* just increase size */
72 P = (char **)realloc((void *)environ,
73 (size_t)(sizeof(char *) * (cnt + 2)));
74 if (!P)
75 return (-1);
76 environ = P;
77 }
78 else { /* get new space */
79 alloced = 1; /* copy old entries into it */
80 P = (char **)malloc((size_t)(sizeof(char *) *
81 (cnt + 2)));
82 if (!P)
83 return (-1);
84 bcopy(environ, P, cnt * sizeof(char *));
85 environ = P;
86 }
87 environ[cnt + 1] = NULL;
88 offset = cnt;
89 }
90 for (C = (char *)name; *C && *C != '='; ++C); /* no `=' in name */
91 if (!(environ[offset] = /* name + `=' + value */
92 malloc((size_t)((int)(C - name) + l_value + 2))))
93 return (-1);
94 for (C = environ[offset]; (*C = *name++) && *C != '='; ++C)
95 ;
96 for (*C++ = '='; (*C++ = *value++); )
97 ;
98 return (0);
99}
100
101/*
102 * unsetenv(name) --
103 * Delete environmental variable "name".
104 */
105void
106unsetenv(name)
107 const char *name;
108{
109 extern char **environ;
110 register char **P;
111 int offset;
112 char *__findenv();
113
114 while (__findenv(name, &offset)) /* if set multiple times */
115 for (P = &environ[offset];; ++P)
116 if (!(*P = *(P + 1)))
117 break;
118}
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..17d26a1dc3
--- /dev/null
+++ b/src/lib/libc/stdlib/strtod.c
@@ -0,0 +1,2528 @@
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 KR_headers for old-style C function headers.
83 * #define Bad_float_h if your system lacks a float.h or if it does not
84 * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP,
85 * FLT_RADIX, FLT_ROUNDS, and DBL_MAX.
86 * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n)
87 * if memory is available and otherwise does something you deem
88 * appropriate. If MALLOC is undefined, malloc will be invoked
89 * directly -- and assumed always to succeed.
90 */
91
92#if defined(LIBC_SCCS) && !defined(lint)
93static char *rcsid = "$OpenBSD: strtod.c,v 1.16 2002/12/02 15:38:54 millert Exp $";
94#endif /* LIBC_SCCS and not lint */
95
96#if defined(__m68k__) || defined(__sparc__) || defined(__i386__) || \
97 defined(__mips__) || defined(__ns32k__) || defined(__alpha__) || \
98 defined(__powerpc__) || defined(__m88k__) || defined(__hppa__)
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#ifdef __arm32__
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#ifndef KR_headers
133#include "stdlib.h"
134#include "string.h"
135#include "locale.h"
136#else
137#include "malloc.h"
138#include "memory.h"
139#endif
140#endif
141
142#ifdef MALLOC
143#ifdef KR_headers
144extern char *MALLOC();
145#else
146extern void *MALLOC(size_t);
147#endif
148#else
149#define MALLOC malloc
150#endif
151
152#include "ctype.h"
153#include "errno.h"
154
155#ifdef Bad_float_h
156#ifdef IEEE_BIG_ENDIAN
157#define IEEE_ARITHMETIC
158#endif
159#ifdef IEEE_LITTLE_ENDIAN
160#define IEEE_ARITHMETIC
161#endif
162
163#ifdef IEEE_ARITHMETIC
164#define DBL_DIG 15
165#define DBL_MAX_10_EXP 308
166#define DBL_MAX_EXP 1024
167#define FLT_RADIX 2
168#define FLT_ROUNDS 1
169#define DBL_MAX 1.7976931348623157e+308
170#endif
171
172#ifdef IBM
173#define DBL_DIG 16
174#define DBL_MAX_10_EXP 75
175#define DBL_MAX_EXP 63
176#define FLT_RADIX 16
177#define FLT_ROUNDS 0
178#define DBL_MAX 7.2370055773322621e+75
179#endif
180
181#ifdef VAX
182#define DBL_DIG 16
183#define DBL_MAX_10_EXP 38
184#define DBL_MAX_EXP 127
185#define FLT_RADIX 2
186#define FLT_ROUNDS 1
187#define DBL_MAX 1.7014118346046923e+38
188#endif
189
190#ifndef LONG_MAX
191#define LONG_MAX 2147483647
192#endif
193#else
194#include "float.h"
195#endif
196#ifndef __MATH_H__
197#include "math.h"
198#endif
199
200#ifdef __cplusplus
201extern "C" {
202#endif
203
204#ifndef CONST
205#ifdef KR_headers
206#define CONST /* blank */
207#else
208#define CONST const
209#endif
210#endif
211
212#ifdef Unsigned_Shifts
213#define Sign_Extend(a,b) if (b < 0) a |= 0xffff0000;
214#else
215#define Sign_Extend(a,b) /*no-op*/
216#endif
217
218#if defined(IEEE_LITTLE_ENDIAN) + defined(IEEE_BIG_ENDIAN) + defined(VAX) + \
219 defined(IBM) != 1
220Exactly one of IEEE_LITTLE_ENDIAN IEEE_BIG_ENDIAN, VAX, or
221IBM should be defined.
222#endif
223
224typedef union {
225 double d;
226 ULong ul[2];
227} _double;
228#define value(x) ((x).d)
229#ifdef IEEE_LITTLE_ENDIAN
230#define word0(x) ((x).ul[1])
231#define word1(x) ((x).ul[0])
232#else
233#define word0(x) ((x).ul[0])
234#define word1(x) ((x).ul[1])
235#endif
236
237/* The following definition of Storeinc is appropriate for MIPS processors.
238 * An alternative that might be better on some machines is
239 * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff)
240 */
241#if defined(IEEE_LITTLE_ENDIAN) + defined(VAX) + defined(__arm32__)
242#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \
243((unsigned short *)a)[0] = (unsigned short)c, a++)
244#else
245#define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \
246((unsigned short *)a)[1] = (unsigned short)c, a++)
247#endif
248
249/* #define P DBL_MANT_DIG */
250/* Ten_pmax = floor(P*log(2)/log(5)) */
251/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */
252/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */
253/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */
254
255#if defined(IEEE_LITTLE_ENDIAN) + defined(IEEE_BIG_ENDIAN)
256#define Exp_shift 20
257#define Exp_shift1 20
258#define Exp_msk1 0x100000
259#define Exp_msk11 0x100000
260#define Exp_mask 0x7ff00000
261#define P 53
262#define Bias 1023
263#define IEEE_Arith
264#define Emin (-1022)
265#define Exp_1 0x3ff00000
266#define Exp_11 0x3ff00000
267#define Ebits 11
268#define Frac_mask 0xfffff
269#define Frac_mask1 0xfffff
270#define Ten_pmax 22
271#define Bletch 0x10
272#define Bndry_mask 0xfffff
273#define Bndry_mask1 0xfffff
274#define LSB 1
275#define Sign_bit 0x80000000
276#define Log2P 1
277#define Tiny0 0
278#define Tiny1 1
279#define Quick_max 14
280#define Int_max 14
281#define Infinite(x) (word0(x) == 0x7ff00000) /* sufficient test for here */
282#else
283#undef Sudden_Underflow
284#define Sudden_Underflow
285#ifdef IBM
286#define Exp_shift 24
287#define Exp_shift1 24
288#define Exp_msk1 0x1000000
289#define Exp_msk11 0x1000000
290#define Exp_mask 0x7f000000
291#define P 14
292#define Bias 65
293#define Exp_1 0x41000000
294#define Exp_11 0x41000000
295#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */
296#define Frac_mask 0xffffff
297#define Frac_mask1 0xffffff
298#define Bletch 4
299#define Ten_pmax 22
300#define Bndry_mask 0xefffff
301#define Bndry_mask1 0xffffff
302#define LSB 1
303#define Sign_bit 0x80000000
304#define Log2P 4
305#define Tiny0 0x100000
306#define Tiny1 0
307#define Quick_max 14
308#define Int_max 15
309#else /* VAX */
310#define Exp_shift 23
311#define Exp_shift1 7
312#define Exp_msk1 0x80
313#define Exp_msk11 0x800000
314#define Exp_mask 0x7f80
315#define P 56
316#define Bias 129
317#define Exp_1 0x40800000
318#define Exp_11 0x4080
319#define Ebits 8
320#define Frac_mask 0x7fffff
321#define Frac_mask1 0xffff007f
322#define Ten_pmax 24
323#define Bletch 2
324#define Bndry_mask 0xffff007f
325#define Bndry_mask1 0xffff007f
326#define LSB 0x10000
327#define Sign_bit 0x8000
328#define Log2P 1
329#define Tiny0 0x80
330#define Tiny1 0
331#define Quick_max 15
332#define Int_max 15
333#endif
334#endif
335
336#ifndef IEEE_Arith
337#define ROUND_BIASED
338#endif
339
340#ifdef RND_PRODQUOT
341#define rounded_product(a,b) a = rnd_prod(a, b)
342#define rounded_quotient(a,b) a = rnd_quot(a, b)
343#ifdef KR_headers
344extern double rnd_prod(), rnd_quot();
345#else
346extern double rnd_prod(double, double), rnd_quot(double, double);
347#endif
348#else
349#define rounded_product(a,b) a *= b
350#define rounded_quotient(a,b) a /= b
351#endif
352
353#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1))
354#define Big1 0xffffffff
355
356#ifndef Just_16
357/* When Pack_32 is not defined, we store 16 bits per 32-bit Long.
358 * This makes some inner loops simpler and sometimes saves work
359 * during multiplications, but it often seems to make things slightly
360 * slower. Hence the default is now to store 32 bits per Long.
361 */
362#ifndef Pack_32
363#define Pack_32
364#endif
365#endif
366
367#define Kmax 15
368
369#ifdef __cplusplus
370extern "C" double strtod(const char *s00, char **se);
371extern "C" char *__dtoa(double d, int mode, int ndigits,
372 int *decpt, int *sign, char **rve);
373#endif
374
375 struct
376Bigint {
377 struct Bigint *next;
378 int k, maxwds, sign, wds;
379 ULong x[1];
380 };
381
382 typedef struct Bigint Bigint;
383
384 static Bigint *freelist[Kmax+1];
385
386 static Bigint *
387Balloc
388#ifdef KR_headers
389 (k) int k;
390#else
391 (int k)
392#endif
393{
394 int x;
395 Bigint *rv;
396
397 if ((rv = freelist[k])) {
398 freelist[k] = rv->next;
399 }
400 else {
401 x = 1 << k;
402 rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(Long));
403 rv->k = k;
404 rv->maxwds = x;
405 }
406 rv->sign = rv->wds = 0;
407 return rv;
408 }
409
410 static void
411Bfree
412#ifdef KR_headers
413 (v) Bigint *v;
414#else
415 (Bigint *v)
416#endif
417{
418 if (v) {
419 v->next = freelist[v->k];
420 freelist[v->k] = v;
421 }
422 }
423
424#define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \
425y->wds*sizeof(Long) + 2*sizeof(int))
426
427 static Bigint *
428multadd
429#ifdef KR_headers
430 (b, m, a) Bigint *b; int m, a;
431#else
432 (Bigint *b, int m, int a) /* multiply by m and add a */
433#endif
434{
435 int i, wds;
436 ULong *x, y;
437#ifdef Pack_32
438 ULong xi, z;
439#endif
440 Bigint *b1;
441
442 wds = b->wds;
443 x = b->x;
444 i = 0;
445 do {
446#ifdef Pack_32
447 xi = *x;
448 y = (xi & 0xffff) * m + a;
449 z = (xi >> 16) * m + (y >> 16);
450 a = (int)(z >> 16);
451 *x++ = (z << 16) + (y & 0xffff);
452#else
453 y = *x * m + a;
454 a = (int)(y >> 16);
455 *x++ = y & 0xffff;
456#endif
457 }
458 while(++i < wds);
459 if (a) {
460 if (wds >= b->maxwds) {
461 b1 = Balloc(b->k+1);
462 Bcopy(b1, b);
463 Bfree(b);
464 b = b1;
465 }
466 b->x[wds++] = a;
467 b->wds = wds;
468 }
469 return b;
470 }
471
472 static Bigint *
473s2b
474#ifdef KR_headers
475 (s, nd0, nd, y9) CONST char *s; int nd0, nd; ULong y9;
476#else
477 (CONST char *s, int nd0, int nd, ULong y9)
478#endif
479{
480 Bigint *b;
481 int i, k;
482 Long x, y;
483
484 x = (nd + 8) / 9;
485 for(k = 0, y = 1; x > y; y <<= 1, k++) ;
486#ifdef Pack_32
487 b = Balloc(k);
488 b->x[0] = y9;
489 b->wds = 1;
490#else
491 b = Balloc(k+1);
492 b->x[0] = y9 & 0xffff;
493 b->wds = (b->x[1] = y9 >> 16) ? 2 : 1;
494#endif
495
496 i = 9;
497 if (9 < nd0) {
498 s += 9;
499 do b = multadd(b, 10, *s++ - '0');
500 while(++i < nd0);
501 s++;
502 }
503 else
504 s += 10;
505 for(; i < nd; i++)
506 b = multadd(b, 10, *s++ - '0');
507 return b;
508 }
509
510 static int
511hi0bits
512#ifdef KR_headers
513 (x) register ULong x;
514#else
515 (register ULong x)
516#endif
517{
518 register int k = 0;
519
520 if (!(x & 0xffff0000)) {
521 k = 16;
522 x <<= 16;
523 }
524 if (!(x & 0xff000000)) {
525 k += 8;
526 x <<= 8;
527 }
528 if (!(x & 0xf0000000)) {
529 k += 4;
530 x <<= 4;
531 }
532 if (!(x & 0xc0000000)) {
533 k += 2;
534 x <<= 2;
535 }
536 if (!(x & 0x80000000)) {
537 k++;
538 if (!(x & 0x40000000))
539 return 32;
540 }
541 return k;
542 }
543
544 static int
545lo0bits
546#ifdef KR_headers
547 (y) ULong *y;
548#else
549 (ULong *y)
550#endif
551{
552 register int k;
553 register ULong x = *y;
554
555 if (x & 7) {
556 if (x & 1)
557 return 0;
558 if (x & 2) {
559 *y = x >> 1;
560 return 1;
561 }
562 *y = x >> 2;
563 return 2;
564 }
565 k = 0;
566 if (!(x & 0xffff)) {
567 k = 16;
568 x >>= 16;
569 }
570 if (!(x & 0xff)) {
571 k += 8;
572 x >>= 8;
573 }
574 if (!(x & 0xf)) {
575 k += 4;
576 x >>= 4;
577 }
578 if (!(x & 0x3)) {
579 k += 2;
580 x >>= 2;
581 }
582 if (!(x & 1)) {
583 k++;
584 x >>= 1;
585 if (!x & 1)
586 return 32;
587 }
588 *y = x;
589 return k;
590 }
591
592 static Bigint *
593i2b
594#ifdef KR_headers
595 (i) int i;
596#else
597 (int i)
598#endif
599{
600 Bigint *b;
601
602 b = Balloc(1);
603 b->x[0] = i;
604 b->wds = 1;
605 return b;
606 }
607
608 static Bigint *
609mult
610#ifdef KR_headers
611 (a, b) Bigint *a, *b;
612#else
613 (Bigint *a, Bigint *b)
614#endif
615{
616 Bigint *c;
617 int k, wa, wb, wc;
618 ULong carry, y, z;
619 ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
620#ifdef Pack_32
621 ULong z2;
622#endif
623
624 if (a->wds < b->wds) {
625 c = a;
626 a = b;
627 b = c;
628 }
629 k = a->k;
630 wa = a->wds;
631 wb = b->wds;
632 wc = wa + wb;
633 if (wc > a->maxwds)
634 k++;
635 c = Balloc(k);
636 for(x = c->x, xa = x + wc; x < xa; x++)
637 *x = 0;
638 xa = a->x;
639 xae = xa + wa;
640 xb = b->x;
641 xbe = xb + wb;
642 xc0 = c->x;
643#ifdef Pack_32
644 for(; xb < xbe; xb++, xc0++) {
645 if ((y = *xb & 0xffff)) {
646 x = xa;
647 xc = xc0;
648 carry = 0;
649 do {
650 z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
651 carry = z >> 16;
652 z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
653 carry = z2 >> 16;
654 Storeinc(xc, z2, z);
655 }
656 while(x < xae);
657 *xc = carry;
658 }
659 if ((y = *xb >> 16)) {
660 x = xa;
661 xc = xc0;
662 carry = 0;
663 z2 = *xc;
664 do {
665 z = (*x & 0xffff) * y + (*xc >> 16) + carry;
666 carry = z >> 16;
667 Storeinc(xc, z, z2);
668 z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
669 carry = z2 >> 16;
670 }
671 while(x < xae);
672 *xc = z2;
673 }
674 }
675#else
676 for(; xb < xbe; xc0++) {
677 if (y = *xb++) {
678 x = xa;
679 xc = xc0;
680 carry = 0;
681 do {
682 z = *x++ * y + *xc + carry;
683 carry = z >> 16;
684 *xc++ = z & 0xffff;
685 }
686 while(x < xae);
687 *xc = carry;
688 }
689 }
690#endif
691 for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
692 c->wds = wc;
693 return c;
694 }
695
696 static Bigint *p5s;
697
698 static Bigint *
699pow5mult
700#ifdef KR_headers
701 (b, k) Bigint *b; int k;
702#else
703 (Bigint *b, int k)
704#endif
705{
706 Bigint *b1, *p5, *p51;
707 int i;
708 static int p05[3] = { 5, 25, 125 };
709
710 if ((i = k & 3))
711 b = multadd(b, p05[i-1], 0);
712
713 if (!(k >>= 2))
714 return b;
715 if (!(p5 = p5s)) {
716 /* first time */
717 p5 = p5s = i2b(625);
718 p5->next = 0;
719 }
720 for(;;) {
721 if (k & 1) {
722 b1 = mult(b, p5);
723 Bfree(b);
724 b = b1;
725 }
726 if (!(k >>= 1))
727 break;
728 if (!(p51 = p5->next)) {
729 p51 = p5->next = mult(p5,p5);
730 p51->next = 0;
731 }
732 p5 = p51;
733 }
734 return b;
735 }
736
737 static Bigint *
738lshift
739#ifdef KR_headers
740 (b, k) Bigint *b; int k;
741#else
742 (Bigint *b, int k)
743#endif
744{
745 int i, k1, n, n1;
746 Bigint *b1;
747 ULong *x, *x1, *xe, z;
748
749#ifdef Pack_32
750 n = k >> 5;
751#else
752 n = k >> 4;
753#endif
754 k1 = b->k;
755 n1 = n + b->wds + 1;
756 for(i = b->maxwds; n1 > i; i <<= 1)
757 k1++;
758 b1 = Balloc(k1);
759 x1 = b1->x;
760 for(i = 0; i < n; i++)
761 *x1++ = 0;
762 x = b->x;
763 xe = x + b->wds;
764#ifdef Pack_32
765 if (k &= 0x1f) {
766 k1 = 32 - k;
767 z = 0;
768 do {
769 *x1++ = *x << k | z;
770 z = *x++ >> k1;
771 }
772 while(x < xe);
773 if ((*x1 = z))
774 ++n1;
775 }
776#else
777 if (k &= 0xf) {
778 k1 = 16 - k;
779 z = 0;
780 do {
781 *x1++ = *x << k & 0xffff | z;
782 z = *x++ >> k1;
783 }
784 while(x < xe);
785 if (*x1 = z)
786 ++n1;
787 }
788#endif
789 else do
790 *x1++ = *x++;
791 while(x < xe);
792 b1->wds = n1 - 1;
793 Bfree(b);
794 return b1;
795 }
796
797 static int
798cmp
799#ifdef KR_headers
800 (a, b) Bigint *a, *b;
801#else
802 (Bigint *a, Bigint *b)
803#endif
804{
805 ULong *xa, *xa0, *xb, *xb0;
806 int i, j;
807
808 i = a->wds;
809 j = b->wds;
810#ifdef DEBUG
811 if (i > 1 && !a->x[i-1])
812 Bug("cmp called with a->x[a->wds-1] == 0");
813 if (j > 1 && !b->x[j-1])
814 Bug("cmp called with b->x[b->wds-1] == 0");
815#endif
816 if (i -= j)
817 return i;
818 xa0 = a->x;
819 xa = xa0 + j;
820 xb0 = b->x;
821 xb = xb0 + j;
822 for(;;) {
823 if (*--xa != *--xb)
824 return *xa < *xb ? -1 : 1;
825 if (xa <= xa0)
826 break;
827 }
828 return 0;
829 }
830
831 static Bigint *
832diff
833#ifdef KR_headers
834 (a, b) Bigint *a, *b;
835#else
836 (Bigint *a, Bigint *b)
837#endif
838{
839 Bigint *c;
840 int i, wa, wb;
841 Long borrow, y; /* We need signed shifts here. */
842 ULong *xa, *xae, *xb, *xbe, *xc;
843#ifdef Pack_32
844 Long z;
845#endif
846
847 i = cmp(a,b);
848 if (!i) {
849 c = Balloc(0);
850 c->wds = 1;
851 c->x[0] = 0;
852 return c;
853 }
854 if (i < 0) {
855 c = a;
856 a = b;
857 b = c;
858 i = 1;
859 }
860 else
861 i = 0;
862 c = Balloc(a->k);
863 c->sign = i;
864 wa = a->wds;
865 xa = a->x;
866 xae = xa + wa;
867 wb = b->wds;
868 xb = b->x;
869 xbe = xb + wb;
870 xc = c->x;
871 borrow = 0;
872#ifdef Pack_32
873 do {
874 y = (*xa & 0xffff) - (*xb & 0xffff) + borrow;
875 borrow = y >> 16;
876 Sign_Extend(borrow, y);
877 z = (*xa++ >> 16) - (*xb++ >> 16) + borrow;
878 borrow = z >> 16;
879 Sign_Extend(borrow, z);
880 Storeinc(xc, z, y);
881 }
882 while(xb < xbe);
883 while(xa < xae) {
884 y = (*xa & 0xffff) + borrow;
885 borrow = y >> 16;
886 Sign_Extend(borrow, y);
887 z = (*xa++ >> 16) + borrow;
888 borrow = z >> 16;
889 Sign_Extend(borrow, z);
890 Storeinc(xc, z, y);
891 }
892#else
893 do {
894 y = *xa++ - *xb++ + borrow;
895 borrow = y >> 16;
896 Sign_Extend(borrow, y);
897 *xc++ = y & 0xffff;
898 }
899 while(xb < xbe);
900 while(xa < xae) {
901 y = *xa++ + borrow;
902 borrow = y >> 16;
903 Sign_Extend(borrow, y);
904 *xc++ = y & 0xffff;
905 }
906#endif
907 while(!*--xc)
908 wa--;
909 c->wds = wa;
910 return c;
911 }
912
913 static double
914ulp
915#ifdef KR_headers
916 (_x) double _x;
917#else
918 (double _x)
919#endif
920{
921 _double x;
922 register Long L;
923 _double a;
924
925 value(x) = _x;
926 L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1;
927#ifndef Sudden_Underflow
928 if (L > 0) {
929#endif
930#ifdef IBM
931 L |= Exp_msk1 >> 4;
932#endif
933 word0(a) = L;
934 word1(a) = 0;
935#ifndef Sudden_Underflow
936 }
937 else {
938 L = -L >> Exp_shift;
939 if (L < Exp_shift) {
940 word0(a) = 0x80000 >> L;
941 word1(a) = 0;
942 }
943 else {
944 word0(a) = 0;
945 L -= Exp_shift;
946 word1(a) = L >= 31 ? 1 : 1 << 31 - L;
947 }
948 }
949#endif
950 return value(a);
951 }
952
953 static double
954b2d
955#ifdef KR_headers
956 (a, e) Bigint *a; int *e;
957#else
958 (Bigint *a, int *e)
959#endif
960{
961 ULong *xa, *xa0, w, y, z;
962 int k;
963 _double d;
964#ifdef VAX
965 ULong d0, d1;
966#else
967#define d0 word0(d)
968#define d1 word1(d)
969#endif
970
971 xa0 = a->x;
972 xa = xa0 + a->wds;
973 y = *--xa;
974#ifdef DEBUG
975 if (!y) Bug("zero y in b2d");
976#endif
977 k = hi0bits(y);
978 *e = 32 - k;
979#ifdef Pack_32
980 if (k < Ebits) {
981 d0 = Exp_1 | y >> Ebits - k;
982 w = xa > xa0 ? *--xa : 0;
983 d1 = y << (32-Ebits) + k | w >> Ebits - k;
984 goto ret_d;
985 }
986 z = xa > xa0 ? *--xa : 0;
987 if (k -= Ebits) {
988 d0 = Exp_1 | y << k | z >> 32 - k;
989 y = xa > xa0 ? *--xa : 0;
990 d1 = z << k | y >> 32 - k;
991 }
992 else {
993 d0 = Exp_1 | y;
994 d1 = z;
995 }
996#else
997 if (k < Ebits + 16) {
998 z = xa > xa0 ? *--xa : 0;
999 d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
1000 w = xa > xa0 ? *--xa : 0;
1001 y = xa > xa0 ? *--xa : 0;
1002 d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
1003 goto ret_d;
1004 }
1005 z = xa > xa0 ? *--xa : 0;
1006 w = xa > xa0 ? *--xa : 0;
1007 k -= Ebits + 16;
1008 d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
1009 y = xa > xa0 ? *--xa : 0;
1010 d1 = w << k + 16 | y << k;
1011#endif
1012 ret_d:
1013#ifdef VAX
1014 word0(d) = d0 >> 16 | d0 << 16;
1015 word1(d) = d1 >> 16 | d1 << 16;
1016#else
1017#undef d0
1018#undef d1
1019#endif
1020 return value(d);
1021 }
1022
1023 static Bigint *
1024d2b
1025#ifdef KR_headers
1026 (_d, e, bits) double d; int *e, *bits;
1027#else
1028 (double _d, int *e, int *bits)
1029#endif
1030{
1031 Bigint *b;
1032 int de, i, k;
1033 ULong *x, y, z;
1034 _double d;
1035#ifdef VAX
1036 ULong d0, d1;
1037#endif
1038
1039 value(d) = _d;
1040#ifdef VAX
1041 d0 = word0(d) >> 16 | word0(d) << 16;
1042 d1 = word1(d) >> 16 | word1(d) << 16;
1043#else
1044#define d0 word0(d)
1045#define d1 word1(d)
1046#endif
1047
1048#ifdef Pack_32
1049 b = Balloc(1);
1050#else
1051 b = Balloc(2);
1052#endif
1053 x = b->x;
1054
1055 z = d0 & Frac_mask;
1056 d0 &= 0x7fffffff; /* clear sign bit, which we ignore */
1057#ifdef Sudden_Underflow
1058 de = (int)(d0 >> Exp_shift);
1059#ifndef IBM
1060 z |= Exp_msk11;
1061#endif
1062#else
1063 if (de = (int)(d0 >> Exp_shift))
1064 z |= Exp_msk1;
1065#endif
1066#ifdef Pack_32
1067 if (y = d1) {
1068 if (k = lo0bits(&y)) {
1069 x[0] = y | z << 32 - k;
1070 z >>= k;
1071 }
1072 else
1073 x[0] = y;
1074 i = b->wds = (x[1] = z) ? 2 : 1;
1075 }
1076 else {
1077#ifdef DEBUG
1078 if (!z)
1079 Bug("Zero passed to d2b");
1080#endif
1081 k = lo0bits(&z);
1082 x[0] = z;
1083 i = b->wds = 1;
1084 k += 32;
1085 }
1086#else
1087 if (y = d1) {
1088 if (k = lo0bits(&y))
1089 if (k >= 16) {
1090 x[0] = y | z << 32 - k & 0xffff;
1091 x[1] = z >> k - 16 & 0xffff;
1092 x[2] = z >> k;
1093 i = 2;
1094 }
1095 else {
1096 x[0] = y & 0xffff;
1097 x[1] = y >> 16 | z << 16 - k & 0xffff;
1098 x[2] = z >> k & 0xffff;
1099 x[3] = z >> k+16;
1100 i = 3;
1101 }
1102 else {
1103 x[0] = y & 0xffff;
1104 x[1] = y >> 16;
1105 x[2] = z & 0xffff;
1106 x[3] = z >> 16;
1107 i = 3;
1108 }
1109 }
1110 else {
1111#ifdef DEBUG
1112 if (!z)
1113 Bug("Zero passed to d2b");
1114#endif
1115 k = lo0bits(&z);
1116 if (k >= 16) {
1117 x[0] = z;
1118 i = 0;
1119 }
1120 else {
1121 x[0] = z & 0xffff;
1122 x[1] = z >> 16;
1123 i = 1;
1124 }
1125 k += 32;
1126 }
1127 while(!x[i])
1128 --i;
1129 b->wds = i + 1;
1130#endif
1131#ifndef Sudden_Underflow
1132 if (de) {
1133#endif
1134#ifdef IBM
1135 *e = (de - Bias - (P-1) << 2) + k;
1136 *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask);
1137#else
1138 *e = de - Bias - (P-1) + k;
1139 *bits = P - k;
1140#endif
1141#ifndef Sudden_Underflow
1142 }
1143 else {
1144 *e = de - Bias - (P-1) + 1 + k;
1145#ifdef Pack_32
1146 *bits = 32*i - hi0bits(x[i-1]);
1147#else
1148 *bits = (i+2)*16 - hi0bits(x[i]);
1149#endif
1150 }
1151#endif
1152 return b;
1153 }
1154#undef d0
1155#undef d1
1156
1157 static double
1158ratio
1159#ifdef KR_headers
1160 (a, b) Bigint *a, *b;
1161#else
1162 (Bigint *a, Bigint *b)
1163#endif
1164{
1165 _double da, db;
1166 int k, ka, kb;
1167
1168 value(da) = b2d(a, &ka);
1169 value(db) = b2d(b, &kb);
1170#ifdef Pack_32
1171 k = ka - kb + 32*(a->wds - b->wds);
1172#else
1173 k = ka - kb + 16*(a->wds - b->wds);
1174#endif
1175#ifdef IBM
1176 if (k > 0) {
1177 word0(da) += (k >> 2)*Exp_msk1;
1178 if (k &= 3)
1179 da *= 1 << k;
1180 }
1181 else {
1182 k = -k;
1183 word0(db) += (k >> 2)*Exp_msk1;
1184 if (k &= 3)
1185 db *= 1 << k;
1186 }
1187#else
1188 if (k > 0)
1189 word0(da) += k*Exp_msk1;
1190 else {
1191 k = -k;
1192 word0(db) += k*Exp_msk1;
1193 }
1194#endif
1195 return value(da) / value(db);
1196 }
1197
1198static CONST double
1199tens[] = {
1200 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
1201 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
1202 1e20, 1e21, 1e22
1203#ifdef VAX
1204 , 1e23, 1e24
1205#endif
1206 };
1207
1208#ifdef IEEE_Arith
1209static CONST double bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
1210static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
1211#define n_bigtens 5
1212#else
1213#ifdef IBM
1214static CONST double bigtens[] = { 1e16, 1e32, 1e64 };
1215static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64 };
1216#define n_bigtens 3
1217#else
1218static CONST double bigtens[] = { 1e16, 1e32 };
1219static CONST double tinytens[] = { 1e-16, 1e-32 };
1220#define n_bigtens 2
1221#endif
1222#endif
1223
1224 double
1225strtod
1226#ifdef KR_headers
1227 (s00, se) CONST char *s00; char **se;
1228#else
1229 (CONST char *s00, char **se)
1230#endif
1231{
1232 int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
1233 e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
1234 CONST char *s, *s0, *s1;
1235 double aadj, aadj1, adj;
1236 _double rv, rv0;
1237 Long L;
1238 ULong y, z;
1239 Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
1240
1241#ifndef KR_headers
1242 CONST char decimal_point = localeconv()->decimal_point[0];
1243#else
1244 CONST char decimal_point = '.';
1245#endif
1246
1247 sign = nz0 = nz = 0;
1248 value(rv) = 0.;
1249
1250
1251 for(s = s00; isspace((unsigned char) *s); s++)
1252 ;
1253
1254 if (*s == '-') {
1255 sign = 1;
1256 s++;
1257 } else if (*s == '+') {
1258 s++;
1259 }
1260
1261 if (*s == '\0') {
1262 s = s00;
1263 goto ret;
1264 }
1265
1266 if (*s == '0') {
1267 nz0 = 1;
1268 while(*++s == '0') ;
1269 if (!*s)
1270 goto ret;
1271 }
1272 s0 = s;
1273 y = z = 0;
1274 for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
1275 if (nd < 9)
1276 y = 10*y + c - '0';
1277 else if (nd < 16)
1278 z = 10*z + c - '0';
1279 nd0 = nd;
1280 if (c == decimal_point) {
1281 c = *++s;
1282 if (!nd) {
1283 for(; c == '0'; c = *++s)
1284 nz++;
1285 if (c > '0' && c <= '9') {
1286 s0 = s;
1287 nf += nz;
1288 nz = 0;
1289 goto have_dig;
1290 }
1291 goto dig_done;
1292 }
1293 for(; c >= '0' && c <= '9'; c = *++s) {
1294 have_dig:
1295 nz++;
1296 if (c -= '0') {
1297 nf += nz;
1298 for(i = 1; i < nz; i++)
1299 if (nd++ < 9)
1300 y *= 10;
1301 else if (nd <= DBL_DIG + 1)
1302 z *= 10;
1303 if (nd++ < 9)
1304 y = 10*y + c;
1305 else if (nd <= DBL_DIG + 1)
1306 z = 10*z + c;
1307 nz = 0;
1308 }
1309 }
1310 }
1311 dig_done:
1312 e = 0;
1313 if (c == 'e' || c == 'E') {
1314 if (!nd && !nz && !nz0) {
1315 s = s00;
1316 goto ret;
1317 }
1318 s00 = s;
1319 esign = 0;
1320 switch(c = *++s) {
1321 case '-':
1322 esign = 1;
1323 case '+':
1324 c = *++s;
1325 }
1326 if (c >= '0' && c <= '9') {
1327 while(c == '0')
1328 c = *++s;
1329 if (c > '0' && c <= '9') {
1330 L = c - '0';
1331 s1 = s;
1332 while((c = *++s) >= '0' && c <= '9')
1333 L = 10*L + c - '0';
1334 if (s - s1 > 8 || L > 19999)
1335 /* Avoid confusion from exponents
1336 * so large that e might overflow.
1337 */
1338 e = 19999; /* safe for 16 bit ints */
1339 else
1340 e = (int)L;
1341 if (esign)
1342 e = -e;
1343 }
1344 else
1345 e = 0;
1346 }
1347 else
1348 s = s00;
1349 }
1350 if (!nd) {
1351 if (!nz && !nz0)
1352 s = s00;
1353 goto ret;
1354 }
1355 e1 = e -= nf;
1356
1357 /* Now we have nd0 digits, starting at s0, followed by a
1358 * decimal point, followed by nd-nd0 digits. The number we're
1359 * after is the integer represented by those digits times
1360 * 10**e */
1361
1362 if (!nd0)
1363 nd0 = nd;
1364 k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
1365 value(rv) = y;
1366 if (k > 9)
1367 value(rv) = tens[k - 9] * value(rv) + z;
1368 bd0 = 0;
1369 if (nd <= DBL_DIG
1370#ifndef RND_PRODQUOT
1371 && FLT_ROUNDS == 1
1372#endif
1373 ) {
1374 if (!e)
1375 goto ret;
1376 if (e > 0) {
1377 if (e <= Ten_pmax) {
1378#ifdef VAX
1379 goto vax_ovfl_check;
1380#else
1381 /* value(rv) = */ rounded_product(value(rv),
1382 tens[e]);
1383 goto ret;
1384#endif
1385 }
1386 i = DBL_DIG - nd;
1387 if (e <= Ten_pmax + i) {
1388 /* A fancier test would sometimes let us do
1389 * this for larger i values.
1390 */
1391 e -= i;
1392 value(rv) *= tens[i];
1393#ifdef VAX
1394 /* VAX exponent range is so narrow we must
1395 * worry about overflow here...
1396 */
1397 vax_ovfl_check:
1398 word0(rv) -= P*Exp_msk1;
1399 /* value(rv) = */ rounded_product(value(rv),
1400 tens[e]);
1401 if ((word0(rv) & Exp_mask)
1402 > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
1403 goto ovfl;
1404 word0(rv) += P*Exp_msk1;
1405#else
1406 /* value(rv) = */ rounded_product(value(rv),
1407 tens[e]);
1408#endif
1409 goto ret;
1410 }
1411 }
1412#ifndef Inaccurate_Divide
1413 else if (e >= -Ten_pmax) {
1414 /* value(rv) = */ rounded_quotient(value(rv),
1415 tens[-e]);
1416 goto ret;
1417 }
1418#endif
1419 }
1420 e1 += nd - k;
1421
1422 /* Get starting approximation = rv * 10**e1 */
1423
1424 if (e1 > 0) {
1425 if (i = e1 & 15)
1426 value(rv) *= tens[i];
1427 if (e1 &= ~15) {
1428 if (e1 > DBL_MAX_10_EXP) {
1429 ovfl:
1430 errno = ERANGE;
1431#ifndef Bad_float_h
1432 value(rv) = HUGE_VAL;
1433#else
1434 /* Can't trust HUGE_VAL */
1435#ifdef IEEE_Arith
1436 word0(rv) = Exp_mask;
1437 word1(rv) = 0;
1438#else
1439 word0(rv) = Big0;
1440 word1(rv) = Big1;
1441#endif
1442#endif
1443 if (bd0)
1444 goto retfree;
1445 goto ret;
1446 }
1447 if (e1 >>= 4) {
1448 for(j = 0; e1 > 1; j++, e1 >>= 1)
1449 if (e1 & 1)
1450 value(rv) *= bigtens[j];
1451 /* The last multiplication could overflow. */
1452 word0(rv) -= P*Exp_msk1;
1453 value(rv) *= bigtens[j];
1454 if ((z = word0(rv) & Exp_mask)
1455 > Exp_msk1*(DBL_MAX_EXP+Bias-P))
1456 goto ovfl;
1457 if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {
1458 /* set to largest number */
1459 /* (Can't trust DBL_MAX) */
1460 word0(rv) = Big0;
1461 word1(rv) = Big1;
1462 }
1463 else
1464 word0(rv) += P*Exp_msk1;
1465 }
1466
1467 }
1468 }
1469 else if (e1 < 0) {
1470 e1 = -e1;
1471 if (i = e1 & 15)
1472 value(rv) /= tens[i];
1473 if (e1 &= ~15) {
1474 e1 >>= 4;
1475 if (e1 >= 1 << n_bigtens)
1476 goto undfl;
1477 for(j = 0; e1 > 1; j++, e1 >>= 1)
1478 if (e1 & 1)
1479 value(rv) *= tinytens[j];
1480 /* The last multiplication could underflow. */
1481 value(rv0) = value(rv);
1482 value(rv) *= tinytens[j];
1483 if (!value(rv)) {
1484 value(rv) = 2.*value(rv0);
1485 value(rv) *= tinytens[j];
1486 if (!value(rv)) {
1487 undfl:
1488 value(rv) = 0.;
1489 errno = ERANGE;
1490 if (bd0)
1491 goto retfree;
1492 goto ret;
1493 }
1494 word0(rv) = Tiny0;
1495 word1(rv) = Tiny1;
1496 /* The refinement below will clean
1497 * this approximation up.
1498 */
1499 }
1500 }
1501 }
1502
1503 /* Now the hard part -- adjusting rv to the correct value.*/
1504
1505 /* Put digits into bd: true value = bd * 10^e */
1506
1507 bd0 = s2b(s0, nd0, nd, y);
1508
1509 for(;;) {
1510 bd = Balloc(bd0->k);
1511 Bcopy(bd, bd0);
1512 bb = d2b(value(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */
1513 bs = i2b(1);
1514
1515 if (e >= 0) {
1516 bb2 = bb5 = 0;
1517 bd2 = bd5 = e;
1518 }
1519 else {
1520 bb2 = bb5 = -e;
1521 bd2 = bd5 = 0;
1522 }
1523 if (bbe >= 0)
1524 bb2 += bbe;
1525 else
1526 bd2 -= bbe;
1527 bs2 = bb2;
1528#ifdef Sudden_Underflow
1529#ifdef IBM
1530 j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3);
1531#else
1532 j = P + 1 - bbbits;
1533#endif
1534#else
1535 i = bbe + bbbits - 1; /* logb(rv) */
1536 if (i < Emin) /* denormal */
1537 j = bbe + (P-Emin);
1538 else
1539 j = P + 1 - bbbits;
1540#endif
1541 bb2 += j;
1542 bd2 += j;
1543 i = bb2 < bd2 ? bb2 : bd2;
1544 if (i > bs2)
1545 i = bs2;
1546 if (i > 0) {
1547 bb2 -= i;
1548 bd2 -= i;
1549 bs2 -= i;
1550 }
1551 if (bb5 > 0) {
1552 bs = pow5mult(bs, bb5);
1553 bb1 = mult(bs, bb);
1554 Bfree(bb);
1555 bb = bb1;
1556 }
1557 if (bb2 > 0)
1558 bb = lshift(bb, bb2);
1559 if (bd5 > 0)
1560 bd = pow5mult(bd, bd5);
1561 if (bd2 > 0)
1562 bd = lshift(bd, bd2);
1563 if (bs2 > 0)
1564 bs = lshift(bs, bs2);
1565 delta = diff(bb, bd);
1566 dsign = delta->sign;
1567 delta->sign = 0;
1568 i = cmp(delta, bs);
1569 if (i < 0) {
1570 /* Error is less than half an ulp -- check for
1571 * special case of mantissa a power of two.
1572 */
1573 if (dsign || word1(rv) || word0(rv) & Bndry_mask)
1574 break;
1575 delta = lshift(delta,Log2P);
1576 if (cmp(delta, bs) > 0)
1577 goto drop_down;
1578 break;
1579 }
1580 if (i == 0) {
1581 /* exactly half-way between */
1582 if (dsign) {
1583 if ((word0(rv) & Bndry_mask1) == Bndry_mask1
1584 && word1(rv) == 0xffffffff) {
1585 /*boundary case -- increment exponent*/
1586 word0(rv) = (word0(rv) & Exp_mask)
1587 + Exp_msk1
1588#ifdef IBM
1589 | Exp_msk1 >> 4
1590#endif
1591 ;
1592 word1(rv) = 0;
1593 break;
1594 }
1595 }
1596 else if (!(word0(rv) & Bndry_mask) && !word1(rv)) {
1597 drop_down:
1598 /* boundary case -- decrement exponent */
1599#ifdef Sudden_Underflow
1600 L = word0(rv) & Exp_mask;
1601#ifdef IBM
1602 if (L < Exp_msk1)
1603#else
1604 if (L <= Exp_msk1)
1605#endif
1606 goto undfl;
1607 L -= Exp_msk1;
1608#else
1609 L = (word0(rv) & Exp_mask) - Exp_msk1;
1610#endif
1611 word0(rv) = L | Bndry_mask1;
1612 word1(rv) = 0xffffffff;
1613#ifdef IBM
1614 goto cont;
1615#else
1616 break;
1617#endif
1618 }
1619#ifndef ROUND_BIASED
1620 if (!(word1(rv) & LSB))
1621 break;
1622#endif
1623 if (dsign)
1624 value(rv) += ulp(value(rv));
1625#ifndef ROUND_BIASED
1626 else {
1627 value(rv) -= ulp(value(rv));
1628#ifndef Sudden_Underflow
1629 if (!value(rv))
1630 goto undfl;
1631#endif
1632 }
1633#endif
1634 break;
1635 }
1636 if ((aadj = ratio(delta, bs)) <= 2.) {
1637 if (dsign)
1638 aadj = aadj1 = 1.;
1639 else if (word1(rv) || word0(rv) & Bndry_mask) {
1640#ifndef Sudden_Underflow
1641 if (word1(rv) == Tiny1 && !word0(rv))
1642 goto undfl;
1643#endif
1644 aadj = 1.;
1645 aadj1 = -1.;
1646 }
1647 else {
1648 /* special case -- power of FLT_RADIX to be */
1649 /* rounded down... */
1650
1651 if (aadj < 2./FLT_RADIX)
1652 aadj = 1./FLT_RADIX;
1653 else
1654 aadj *= 0.5;
1655 aadj1 = -aadj;
1656 }
1657 }
1658 else {
1659 aadj *= 0.5;
1660 aadj1 = dsign ? aadj : -aadj;
1661#ifdef Check_FLT_ROUNDS
1662 switch(FLT_ROUNDS) {
1663 case 2: /* towards +infinity */
1664 aadj1 -= 0.5;
1665 break;
1666 case 0: /* towards 0 */
1667 case 3: /* towards -infinity */
1668 aadj1 += 0.5;
1669 }
1670#else
1671 if (FLT_ROUNDS == 0)
1672 aadj1 += 0.5;
1673#endif
1674 }
1675 y = word0(rv) & Exp_mask;
1676
1677 /* Check for overflow */
1678
1679 if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
1680 value(rv0) = value(rv);
1681 word0(rv) -= P*Exp_msk1;
1682 adj = aadj1 * ulp(value(rv));
1683 value(rv) += adj;
1684 if ((word0(rv) & Exp_mask) >=
1685 Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
1686 if (word0(rv0) == Big0 && word1(rv0) == Big1)
1687 goto ovfl;
1688 word0(rv) = Big0;
1689 word1(rv) = Big1;
1690 goto cont;
1691 }
1692 else
1693 word0(rv) += P*Exp_msk1;
1694 }
1695 else {
1696#ifdef Sudden_Underflow
1697 if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
1698 value(rv0) = value(rv);
1699 word0(rv) += P*Exp_msk1;
1700 adj = aadj1 * ulp(value(rv));
1701 value(rv) += adj;
1702#ifdef IBM
1703 if ((word0(rv) & Exp_mask) < P*Exp_msk1)
1704#else
1705 if ((word0(rv) & Exp_mask) <= P*Exp_msk1)
1706#endif
1707 {
1708 if (word0(rv0) == Tiny0
1709 && word1(rv0) == Tiny1)
1710 goto undfl;
1711 word0(rv) = Tiny0;
1712 word1(rv) = Tiny1;
1713 goto cont;
1714 }
1715 else
1716 word0(rv) -= P*Exp_msk1;
1717 }
1718 else {
1719 adj = aadj1 * ulp(value(rv));
1720 value(rv) += adj;
1721 }
1722#else
1723 /* Compute adj so that the IEEE rounding rules will
1724 * correctly round rv + adj in some half-way cases.
1725 * If rv * ulp(rv) is denormalized (i.e.,
1726 * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid
1727 * trouble from bits lost to denormalization;
1728 * example: 1.2e-307 .
1729 */
1730 if (y <= (P-1)*Exp_msk1 && aadj >= 1.) {
1731 aadj1 = (double)(int)(aadj + 0.5);
1732 if (!dsign)
1733 aadj1 = -aadj1;
1734 }
1735 adj = aadj1 * ulp(value(rv));
1736 value(rv) += adj;
1737#endif
1738 }
1739 z = word0(rv) & Exp_mask;
1740 if (y == z) {
1741 /* Can we stop now? */
1742 L = aadj;
1743 aadj -= L;
1744 /* The tolerances below are conservative. */
1745 if (dsign || word1(rv) || word0(rv) & Bndry_mask) {
1746 if (aadj < .4999999 || aadj > .5000001)
1747 break;
1748 }
1749 else if (aadj < .4999999/FLT_RADIX)
1750 break;
1751 }
1752 cont:
1753 Bfree(bb);
1754 Bfree(bd);
1755 Bfree(bs);
1756 Bfree(delta);
1757 }
1758 retfree:
1759 Bfree(bb);
1760 Bfree(bd);
1761 Bfree(bs);
1762 Bfree(bd0);
1763 Bfree(delta);
1764 ret:
1765 if (se)
1766 *se = (char *)s;
1767 return sign ? -value(rv) : value(rv);
1768 }
1769
1770 static int
1771quorem
1772#ifdef KR_headers
1773 (b, S) Bigint *b, *S;
1774#else
1775 (Bigint *b, Bigint *S)
1776#endif
1777{
1778 int n;
1779 Long borrow, y;
1780 ULong carry, q, ys;
1781 ULong *bx, *bxe, *sx, *sxe;
1782#ifdef Pack_32
1783 Long z;
1784 ULong si, zs;
1785#endif
1786
1787 n = S->wds;
1788#ifdef DEBUG
1789 /*debug*/ if (b->wds > n)
1790 /*debug*/ Bug("oversize b in quorem");
1791#endif
1792 if (b->wds < n)
1793 return 0;
1794 sx = S->x;
1795 sxe = sx + --n;
1796 bx = b->x;
1797 bxe = bx + n;
1798 q = *bxe / (*sxe + 1); /* ensure q <= true quotient */
1799#ifdef DEBUG
1800 /*debug*/ if (q > 9)
1801 /*debug*/ Bug("oversized quotient in quorem");
1802#endif
1803 if (q) {
1804 borrow = 0;
1805 carry = 0;
1806 do {
1807#ifdef Pack_32
1808 si = *sx++;
1809 ys = (si & 0xffff) * q + carry;
1810 zs = (si >> 16) * q + (ys >> 16);
1811 carry = zs >> 16;
1812 y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
1813 borrow = y >> 16;
1814 Sign_Extend(borrow, y);
1815 z = (*bx >> 16) - (zs & 0xffff) + borrow;
1816 borrow = z >> 16;
1817 Sign_Extend(borrow, z);
1818 Storeinc(bx, z, y);
1819#else
1820 ys = *sx++ * q + carry;
1821 carry = ys >> 16;
1822 y = *bx - (ys & 0xffff) + borrow;
1823 borrow = y >> 16;
1824 Sign_Extend(borrow, y);
1825 *bx++ = y & 0xffff;
1826#endif
1827 }
1828 while(sx <= sxe);
1829 if (!*bxe) {
1830 bx = b->x;
1831 while(--bxe > bx && !*bxe)
1832 --n;
1833 b->wds = n;
1834 }
1835 }
1836 if (cmp(b, S) >= 0) {
1837 q++;
1838 borrow = 0;
1839 carry = 0;
1840 bx = b->x;
1841 sx = S->x;
1842 do {
1843#ifdef Pack_32
1844 si = *sx++;
1845 ys = (si & 0xffff) + carry;
1846 zs = (si >> 16) + (ys >> 16);
1847 carry = zs >> 16;
1848 y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
1849 borrow = y >> 16;
1850 Sign_Extend(borrow, y);
1851 z = (*bx >> 16) - (zs & 0xffff) + borrow;
1852 borrow = z >> 16;
1853 Sign_Extend(borrow, z);
1854 Storeinc(bx, z, y);
1855#else
1856 ys = *sx++ + carry;
1857 carry = ys >> 16;
1858 y = *bx - (ys & 0xffff) + borrow;
1859 borrow = y >> 16;
1860 Sign_Extend(borrow, y);
1861 *bx++ = y & 0xffff;
1862#endif
1863 }
1864 while(sx <= sxe);
1865 bx = b->x;
1866 bxe = bx + n;
1867 if (!*bxe) {
1868 while(--bxe > bx && !*bxe)
1869 --n;
1870 b->wds = n;
1871 }
1872 }
1873 return q;
1874 }
1875
1876/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
1877 *
1878 * Inspired by "How to Print Floating-Point Numbers Accurately" by
1879 * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101].
1880 *
1881 * Modifications:
1882 * 1. Rather than iterating, we use a simple numeric overestimate
1883 * to determine k = floor(log10(d)). We scale relevant
1884 * quantities using O(log2(k)) rather than O(k) multiplications.
1885 * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
1886 * try to generate digits strictly left to right. Instead, we
1887 * compute with fewer bits and propagate the carry if necessary
1888 * when rounding the final digit up. This is often faster.
1889 * 3. Under the assumption that input will be rounded nearest,
1890 * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
1891 * That is, we allow equality in stopping tests when the
1892 * round-nearest rule will give the same floating-point value
1893 * as would satisfaction of the stopping test with strict
1894 * inequality.
1895 * 4. We remove common factors of powers of 2 from relevant
1896 * quantities.
1897 * 5. When converting floating-point integers less than 1e16,
1898 * we use floating-point arithmetic rather than resorting
1899 * to multiple-precision integers.
1900 * 6. When asked to produce fewer than 15 digits, we first try
1901 * to get by with floating-point arithmetic; we resort to
1902 * multiple-precision integer arithmetic only if we cannot
1903 * guarantee that the floating-point calculation has given
1904 * the correctly rounded result. For k requested digits and
1905 * "uniformly" distributed input, the probability is
1906 * something like 10^(k-15) that we must resort to the Long
1907 * calculation.
1908 */
1909
1910 char *
1911__dtoa
1912#ifdef KR_headers
1913 (_d, mode, ndigits, decpt, sign, rve)
1914 double _d; int mode, ndigits, *decpt, *sign; char **rve;
1915#else
1916 (double _d, int mode, int ndigits, int *decpt, int *sign, char **rve)
1917#endif
1918{
1919 /* Arguments ndigits, decpt, sign are similar to those
1920 of ecvt and fcvt; trailing zeros are suppressed from
1921 the returned string. If not null, *rve is set to point
1922 to the end of the return value. If d is +-Infinity or NaN,
1923 then *decpt is set to 9999.
1924
1925 mode:
1926 0 ==> shortest string that yields d when read in
1927 and rounded to nearest.
1928 1 ==> like 0, but with Steele & White stopping rule;
1929 e.g. with IEEE P754 arithmetic , mode 0 gives
1930 1e23 whereas mode 1 gives 9.999999999999999e22.
1931 2 ==> max(1,ndigits) significant digits. This gives a
1932 return value similar to that of ecvt, except
1933 that trailing zeros are suppressed.
1934 3 ==> through ndigits past the decimal point. This
1935 gives a return value similar to that from fcvt,
1936 except that trailing zeros are suppressed, and
1937 ndigits can be negative.
1938 4-9 should give the same return values as 2-3, i.e.,
1939 4 <= mode <= 9 ==> same return as mode
1940 2 + (mode & 1). These modes are mainly for
1941 debugging; often they run slower but sometimes
1942 faster than modes 2-3.
1943 4,5,8,9 ==> left-to-right digit generation.
1944 6-9 ==> don't try fast floating-point estimate
1945 (if applicable).
1946
1947 Values of mode other than 0-9 are treated as mode 0.
1948
1949 Sufficient space is allocated to the return value
1950 to hold the suppressed trailing zeros.
1951 */
1952
1953 int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1,
1954 j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
1955 spec_case, try_quick;
1956 Long L;
1957#ifndef Sudden_Underflow
1958 int denorm;
1959 ULong x;
1960#endif
1961 Bigint *b, *b1, *delta, *mlo, *mhi, *S;
1962 double ds;
1963 char *s, *s0;
1964 static Bigint *result;
1965 static int result_k;
1966 _double d, d2, eps;
1967
1968 value(d) = _d;
1969 if (result) {
1970 result->k = result_k;
1971 result->maxwds = 1 << result_k;
1972 Bfree(result);
1973 result = 0;
1974 }
1975
1976 if (word0(d) & Sign_bit) {
1977 /* set sign for everything, including 0's and NaNs */
1978 *sign = 1;
1979 word0(d) &= ~Sign_bit; /* clear sign bit */
1980 }
1981 else
1982 *sign = 0;
1983
1984#if defined(IEEE_Arith) + defined(VAX)
1985#ifdef IEEE_Arith
1986 if ((word0(d) & Exp_mask) == Exp_mask)
1987#else
1988 if (word0(d) == 0x8000)
1989#endif
1990 {
1991 /* Infinity or NaN */
1992 *decpt = 9999;
1993 s =
1994#ifdef IEEE_Arith
1995 !word1(d) && !(word0(d) & 0xfffff) ? ndigits < 8 ? "Inf" : "Infinity" :
1996#endif
1997 "NaN";
1998 if (rve)
1999 *rve =
2000#ifdef IEEE_Arith
2001 s[3] ? s + 8 :
2002#endif
2003 s + 3;
2004 return s;
2005 }
2006#endif
2007#ifdef IBM
2008 value(d) += 0; /* normalize */
2009#endif
2010 if (!value(d)) {
2011 *decpt = 1;
2012 s = "0";
2013 if (rve)
2014 *rve = s + 1;
2015 return s;
2016 }
2017
2018 b = d2b(value(d), &be, &bbits);
2019#ifdef Sudden_Underflow
2020 i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
2021#else
2022 if (i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) {
2023#endif
2024 value(d2) = value(d);
2025 word0(d2) &= Frac_mask1;
2026 word0(d2) |= Exp_11;
2027#ifdef IBM
2028 if (j = 11 - hi0bits(word0(d2) & Frac_mask))
2029 value(d2) /= 1 << j;
2030#endif
2031
2032 /* log(x) ~=~ log(1.5) + (x-1.5)/1.5
2033 * log10(x) = log(x) / log(10)
2034 * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
2035 * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
2036 *
2037 * This suggests computing an approximation k to log10(d) by
2038 *
2039 * k = (i - Bias)*0.301029995663981
2040 * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
2041 *
2042 * We want k to be too large rather than too small.
2043 * The error in the first-order Taylor series approximation
2044 * is in our favor, so we just round up the constant enough
2045 * to compensate for any error in the multiplication of
2046 * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
2047 * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
2048 * adding 1e-13 to the constant term more than suffices.
2049 * Hence we adjust the constant term to 0.1760912590558.
2050 * (We could get a more accurate k by invoking log10,
2051 * but this is probably not worthwhile.)
2052 */
2053
2054 i -= Bias;
2055#ifdef IBM
2056 i <<= 2;
2057 i += j;
2058#endif
2059#ifndef Sudden_Underflow
2060 denorm = 0;
2061 }
2062 else {
2063 /* d is denormalized */
2064
2065 i = bbits + be + (Bias + (P-1) - 1);
2066 x = i > 32 ? word0(d) << 64 - i | word1(d) >> i - 32
2067 : word1(d) << 32 - i;
2068 value(d2) = x;
2069 word0(d2) -= 31*Exp_msk1; /* adjust exponent */
2070 i -= (Bias + (P-1) - 1) + 1;
2071 denorm = 1;
2072 }
2073#endif
2074 ds = (value(d2)-1.5)*0.289529654602168 + 0.1760912590558 +
2075 i*0.301029995663981;
2076 k = (int)ds;
2077 if (ds < 0. && ds != k)
2078 k--; /* want k = floor(ds) */
2079 k_check = 1;
2080 if (k >= 0 && k <= Ten_pmax) {
2081 if (value(d) < tens[k])
2082 k--;
2083 k_check = 0;
2084 }
2085 j = bbits - i - 1;
2086 if (j >= 0) {
2087 b2 = 0;
2088 s2 = j;
2089 }
2090 else {
2091 b2 = -j;
2092 s2 = 0;
2093 }
2094 if (k >= 0) {
2095 b5 = 0;
2096 s5 = k;
2097 s2 += k;
2098 }
2099 else {
2100 b2 -= k;
2101 b5 = -k;
2102 s5 = 0;
2103 }
2104 if (mode < 0 || mode > 9)
2105 mode = 0;
2106 try_quick = 1;
2107 if (mode > 5) {
2108 mode -= 4;
2109 try_quick = 0;
2110 }
2111 leftright = 1;
2112 switch(mode) {
2113 case 0:
2114 case 1:
2115 ilim = ilim1 = -1;
2116 i = 18;
2117 ndigits = 0;
2118 break;
2119 case 2:
2120 leftright = 0;
2121 /* no break */
2122 case 4:
2123 if (ndigits <= 0)
2124 ndigits = 1;
2125 ilim = ilim1 = i = ndigits;
2126 break;
2127 case 3:
2128 leftright = 0;
2129 /* no break */
2130 case 5:
2131 i = ndigits + k + 1;
2132 ilim = i;
2133 ilim1 = i - 1;
2134 if (i <= 0)
2135 i = 1;
2136 }
2137 j = sizeof(ULong);
2138 for(result_k = 0; sizeof(Bigint) - sizeof(ULong) + j <= i;
2139 j <<= 1) result_k++;
2140 result = Balloc(result_k);
2141 s = s0 = (char *)result;
2142
2143 if (ilim >= 0 && ilim <= Quick_max && try_quick) {
2144
2145 /* Try to get by with floating-point arithmetic. */
2146
2147 i = 0;
2148 value(d2) = value(d);
2149 k0 = k;
2150 ilim0 = ilim;
2151 ieps = 2; /* conservative */
2152 if (k > 0) {
2153 ds = tens[k&0xf];
2154 j = k >> 4;
2155 if (j & Bletch) {
2156 /* prevent overflows */
2157 j &= Bletch - 1;
2158 value(d) /= bigtens[n_bigtens-1];
2159 ieps++;
2160 }
2161 for(; j; j >>= 1, i++)
2162 if (j & 1) {
2163 ieps++;
2164 ds *= bigtens[i];
2165 }
2166 value(d) /= ds;
2167 }
2168 else if (j1 = -k) {
2169 value(d) *= tens[j1 & 0xf];
2170 for(j = j1 >> 4; j; j >>= 1, i++)
2171 if (j & 1) {
2172 ieps++;
2173 value(d) *= bigtens[i];
2174 }
2175 }
2176 if (k_check && value(d) < 1. && ilim > 0) {
2177 if (ilim1 <= 0)
2178 goto fast_failed;
2179 ilim = ilim1;
2180 k--;
2181 value(d) *= 10.;
2182 ieps++;
2183 }
2184 value(eps) = ieps*value(d) + 7.;
2185 word0(eps) -= (P-1)*Exp_msk1;
2186 if (ilim == 0) {
2187 S = mhi = 0;
2188 value(d) -= 5.;
2189 if (value(d) > value(eps))
2190 goto one_digit;
2191 if (value(d) < -value(eps))
2192 goto no_digits;
2193 goto fast_failed;
2194 }
2195#ifndef No_leftright
2196 if (leftright) {
2197 /* Use Steele & White method of only
2198 * generating digits needed.
2199 */
2200 value(eps) = 0.5/tens[ilim-1] - value(eps);
2201 for(i = 0;;) {
2202 L = value(d);
2203 value(d) -= L;
2204 *s++ = '0' + (int)L;
2205 if (value(d) < value(eps))
2206 goto ret1;
2207 if (1. - value(d) < value(eps))
2208 goto bump_up;
2209 if (++i >= ilim)
2210 break;
2211 value(eps) *= 10.;
2212 value(d) *= 10.;
2213 }
2214 }
2215 else {
2216#endif
2217 /* Generate ilim digits, then fix them up. */
2218 value(eps) *= tens[ilim-1];
2219 for(i = 1;; i++, value(d) *= 10.) {
2220 L = value(d);
2221 value(d) -= L;
2222 *s++ = '0' + (int)L;
2223 if (i == ilim) {
2224 if (value(d) > 0.5 + value(eps))
2225 goto bump_up;
2226 else if (value(d) < 0.5 - value(eps)) {
2227 while(*--s == '0');
2228 s++;
2229 goto ret1;
2230 }
2231 break;
2232 }
2233 }
2234#ifndef No_leftright
2235 }
2236#endif
2237 fast_failed:
2238 s = s0;
2239 value(d) = value(d2);
2240 k = k0;
2241 ilim = ilim0;
2242 }
2243
2244 /* Do we have a "small" integer? */
2245
2246 if (be >= 0 && k <= Int_max) {
2247 /* Yes. */
2248 ds = tens[k];
2249 if (ndigits < 0 && ilim <= 0) {
2250 S = mhi = 0;
2251 if (ilim < 0 || value(d) <= 5*ds)
2252 goto no_digits;
2253 goto one_digit;
2254 }
2255 for(i = 1;; i++) {
2256 L = value(d) / ds;
2257 value(d) -= L*ds;
2258#ifdef Check_FLT_ROUNDS
2259 /* If FLT_ROUNDS == 2, L will usually be high by 1 */
2260 if (value(d) < 0) {
2261 L--;
2262 value(d) += ds;
2263 }
2264#endif
2265 *s++ = '0' + (int)L;
2266 if (i == ilim) {
2267 value(d) += value(d);
2268 if (value(d) > ds || value(d) == ds && L & 1) {
2269 bump_up:
2270 while(*--s == '9')
2271 if (s == s0) {
2272 k++;
2273 *s = '0';
2274 break;
2275 }
2276 ++*s++;
2277 }
2278 break;
2279 }
2280 if (!(value(d) *= 10.))
2281 break;
2282 }
2283 goto ret1;
2284 }
2285
2286 m2 = b2;
2287 m5 = b5;
2288 mhi = mlo = 0;
2289 if (leftright) {
2290 if (mode < 2) {
2291 i =
2292#ifndef Sudden_Underflow
2293 denorm ? be + (Bias + (P-1) - 1 + 1) :
2294#endif
2295#ifdef IBM
2296 1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3);
2297#else
2298 1 + P - bbits;
2299#endif
2300 }
2301 else {
2302 j = ilim - 1;
2303 if (m5 >= j)
2304 m5 -= j;
2305 else {
2306 s5 += j -= m5;
2307 b5 += j;
2308 m5 = 0;
2309 }
2310 if ((i = ilim) < 0) {
2311 m2 -= i;
2312 i = 0;
2313 }
2314 }
2315 b2 += i;
2316 s2 += i;
2317 mhi = i2b(1);
2318 }
2319 if (m2 > 0 && s2 > 0) {
2320 i = m2 < s2 ? m2 : s2;
2321 b2 -= i;
2322 m2 -= i;
2323 s2 -= i;
2324 }
2325 if (b5 > 0) {
2326 if (leftright) {
2327 if (m5 > 0) {
2328 mhi = pow5mult(mhi, m5);
2329 b1 = mult(mhi, b);
2330 Bfree(b);
2331 b = b1;
2332 }
2333 if (j = b5 - m5)
2334 b = pow5mult(b, j);
2335 }
2336 else
2337 b = pow5mult(b, b5);
2338 }
2339 S = i2b(1);
2340 if (s5 > 0)
2341 S = pow5mult(S, s5);
2342
2343 /* Check for special case that d is a normalized power of 2. */
2344
2345 if (mode < 2) {
2346 if (!word1(d) && !(word0(d) & Bndry_mask)
2347#ifndef Sudden_Underflow
2348 && word0(d) & Exp_mask
2349#endif
2350 ) {
2351 /* The special case */
2352 b2 += Log2P;
2353 s2 += Log2P;
2354 spec_case = 1;
2355 }
2356 else
2357 spec_case = 0;
2358 }
2359
2360 /* Arrange for convenient computation of quotients:
2361 * shift left if necessary so divisor has 4 leading 0 bits.
2362 *
2363 * Perhaps we should just compute leading 28 bits of S once
2364 * and for all and pass them and a shift to quorem, so it
2365 * can do shifts and ors to compute the numerator for q.
2366 */
2367#ifdef Pack_32
2368 if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f)
2369 i = 32 - i;
2370#else
2371 if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf)
2372 i = 16 - i;
2373#endif
2374 if (i > 4) {
2375 i -= 4;
2376 b2 += i;
2377 m2 += i;
2378 s2 += i;
2379 }
2380 else if (i < 4) {
2381 i += 28;
2382 b2 += i;
2383 m2 += i;
2384 s2 += i;
2385 }
2386 if (b2 > 0)
2387 b = lshift(b, b2);
2388 if (s2 > 0)
2389 S = lshift(S, s2);
2390 if (k_check) {
2391 if (cmp(b,S) < 0) {
2392 k--;
2393 b = multadd(b, 10, 0); /* we botched the k estimate */
2394 if (leftright)
2395 mhi = multadd(mhi, 10, 0);
2396 ilim = ilim1;
2397 }
2398 }
2399 if (ilim <= 0 && mode > 2) {
2400 if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) {
2401 /* no digits, fcvt style */
2402 no_digits:
2403 k = -1 - ndigits;
2404 goto ret;
2405 }
2406 one_digit:
2407 *s++ = '1';
2408 k++;
2409 goto ret;
2410 }
2411 if (leftright) {
2412 if (m2 > 0)
2413 mhi = lshift(mhi, m2);
2414
2415 /* Compute mlo -- check for special case
2416 * that d is a normalized power of 2.
2417 */
2418
2419 mlo = mhi;
2420 if (spec_case) {
2421 mhi = Balloc(mhi->k);
2422 Bcopy(mhi, mlo);
2423 mhi = lshift(mhi, Log2P);
2424 }
2425
2426 for(i = 1;;i++) {
2427 dig = quorem(b,S) + '0';
2428 /* Do we yet have the shortest decimal string
2429 * that will round to d?
2430 */
2431 j = cmp(b, mlo);
2432 delta = diff(S, mhi);
2433 j1 = delta->sign ? 1 : cmp(b, delta);
2434 Bfree(delta);
2435#ifndef ROUND_BIASED
2436 if (j1 == 0 && !mode && !(word1(d) & 1)) {
2437 if (dig == '9')
2438 goto round_9_up;
2439 if (j > 0)
2440 dig++;
2441 *s++ = dig;
2442 goto ret;
2443 }
2444#endif
2445 if (j < 0 || j == 0 && !mode
2446#ifndef ROUND_BIASED
2447 && !(word1(d) & 1)
2448#endif
2449 ) {
2450 if (j1 > 0) {
2451 b = lshift(b, 1);
2452 j1 = cmp(b, S);
2453 if ((j1 > 0 || j1 == 0 && dig & 1)
2454 && dig++ == '9')
2455 goto round_9_up;
2456 }
2457 *s++ = dig;
2458 goto ret;
2459 }
2460 if (j1 > 0) {
2461 if (dig == '9') { /* possible if i == 1 */
2462 round_9_up:
2463 *s++ = '9';
2464 goto roundoff;
2465 }
2466 *s++ = dig + 1;
2467 goto ret;
2468 }
2469 *s++ = dig;
2470 if (i == ilim)
2471 break;
2472 b = multadd(b, 10, 0);
2473 if (mlo == mhi)
2474 mlo = mhi = multadd(mhi, 10, 0);
2475 else {
2476 mlo = multadd(mlo, 10, 0);
2477 mhi = multadd(mhi, 10, 0);
2478 }
2479 }
2480 }
2481 else
2482 for(i = 1;; i++) {
2483 *s++ = dig = quorem(b,S) + '0';
2484 if (i >= ilim)
2485 break;
2486 b = multadd(b, 10, 0);
2487 }
2488
2489 /* Round off last digit */
2490
2491 b = lshift(b, 1);
2492 j = cmp(b, S);
2493 if (j > 0 || j == 0 && dig & 1) {
2494 roundoff:
2495 while(*--s == '9')
2496 if (s == s0) {
2497 k++;
2498 *s++ = '1';
2499 goto ret;
2500 }
2501 ++*s++;
2502 }
2503 else {
2504 while(*--s == '0');
2505 s++;
2506 }
2507 ret:
2508 Bfree(S);
2509 if (mhi) {
2510 if (mlo && mlo != mhi)
2511 Bfree(mlo);
2512 Bfree(mhi);
2513 }
2514 ret1:
2515 Bfree(b);
2516 if (s == s0) { /* don't return empty string */
2517 *s++ = '0';
2518 k = 0;
2519 }
2520 *s = 0;
2521 *decpt = k + 1;
2522 if (rve)
2523 *rve = s;
2524 return s0;
2525 }
2526#ifdef __cplusplus
2527}
2528#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..1c39720794
--- /dev/null
+++ b/src/lib/libc/stdlib/strtol.c
@@ -0,0 +1,146 @@
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.5 2003/06/02 20:18:38 millert 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(nptr, endptr, base)
48 const char *nptr;
49 char **endptr;
50 register int base;
51{
52 register const char *s;
53 register long acc, cutoff;
54 register int c;
55 register int neg, any, cutlim;
56
57 /*
58 * Skip white space and pick up leading +/- sign if any.
59 * If base is 0, allow 0x for hex and 0 for octal, else
60 * assume decimal; if base is already 16, allow 0x.
61 */
62 s = nptr;
63 do {
64 c = (unsigned char) *s++;
65 } while (isspace(c));
66 if (c == '-') {
67 neg = 1;
68 c = *s++;
69 } else {
70 neg = 0;
71 if (c == '+')
72 c = *s++;
73 }
74 if ((base == 0 || base == 16) &&
75 c == '0' && (*s == 'x' || *s == 'X')) {
76 c = s[1];
77 s += 2;
78 base = 16;
79 }
80 if (base == 0)
81 base = c == '0' ? 8 : 10;
82
83 /*
84 * Compute the cutoff value between legal numbers and illegal
85 * numbers. That is the largest legal value, divided by the
86 * base. An input number that is greater than this value, if
87 * followed by a legal input character, is too big. One that
88 * is equal to this value may be valid or not; the limit
89 * between valid and invalid numbers is then based on the last
90 * digit. For instance, if the range for longs is
91 * [-2147483648..2147483647] and the input base is 10,
92 * cutoff will be set to 214748364 and cutlim to either
93 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
94 * a value > 214748364, or equal but the next digit is > 7 (or 8),
95 * the number is too big, and we will return a range error.
96 *
97 * Set any if any `digits' consumed; make it negative to indicate
98 * overflow.
99 */
100 cutoff = neg ? LONG_MIN : LONG_MAX;
101 cutlim = cutoff % base;
102 cutoff /= base;
103 if (neg) {
104 if (cutlim > 0) {
105 cutlim -= base;
106 cutoff += 1;
107 }
108 cutlim = -cutlim;
109 }
110 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
111 if (isdigit(c))
112 c -= '0';
113 else if (isalpha(c))
114 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
115 else
116 break;
117 if (c >= base)
118 break;
119 if (any < 0)
120 continue;
121 if (neg) {
122 if (acc < cutoff || acc == cutoff && c > cutlim) {
123 any = -1;
124 acc = LONG_MIN;
125 errno = ERANGE;
126 } else {
127 any = 1;
128 acc *= base;
129 acc -= c;
130 }
131 } else {
132 if (acc > cutoff || acc == cutoff && c > cutlim) {
133 any = -1;
134 acc = LONG_MAX;
135 errno = ERANGE;
136 } else {
137 any = 1;
138 acc *= base;
139 acc += c;
140 }
141 }
142 }
143 if (endptr != 0)
144 *endptr = (char *) (any ? s - 1 : nptr);
145 return (acc);
146}
diff --git a/src/lib/libc/stdlib/strtoll.c b/src/lib/libc/stdlib/strtoll.c
new file mode 100644
index 0000000000..ac9353890f
--- /dev/null
+++ b/src/lib/libc/stdlib/strtoll.c
@@ -0,0 +1,162 @@
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.2 2003/06/02 20:18:38 millert 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(nptr, endptr, base)
49 const char *nptr;
50 char **endptr;
51 int base;
52{
53 const char *s;
54 long long acc, cutoff;
55 int c;
56 int neg, any, cutlim;
57
58 /*
59 * Skip white space and pick up leading +/- sign if any.
60 * If base is 0, allow 0x for hex and 0 for octal, else
61 * assume decimal; if base is already 16, allow 0x.
62 */
63 s = nptr;
64 do {
65 c = (unsigned char) *s++;
66 } while (isspace(c));
67 if (c == '-') {
68 neg = 1;
69 c = *s++;
70 } else {
71 neg = 0;
72 if (c == '+')
73 c = *s++;
74 }
75 if ((base == 0 || base == 16) &&
76 c == '0' && (*s == 'x' || *s == 'X')) {
77 c = s[1];
78 s += 2;
79 base = 16;
80 }
81 if (base == 0)
82 base = c == '0' ? 8 : 10;
83
84 /*
85 * Compute the cutoff value between legal numbers and illegal
86 * numbers. That is the largest legal value, divided by the
87 * base. An input number that is greater than this value, if
88 * followed by a legal input character, is too big. One that
89 * is equal to this value may be valid or not; the limit
90 * between valid and invalid numbers is then based on the last
91 * digit. For instance, if the range for long longs is
92 * [-9223372036854775808..9223372036854775807] and the input base
93 * is 10, cutoff will be set to 922337203685477580 and cutlim to
94 * either 7 (neg==0) or 8 (neg==1), meaning that if we have
95 * accumulated a value > 922337203685477580, or equal but the
96 * next digit is > 7 (or 8), the number is too big, and we will
97 * return a range error.
98 *
99 * Set any if any `digits' consumed; make it negative to indicate
100 * overflow.
101 */
102 cutoff = neg ? LLONG_MIN : LLONG_MAX;
103 cutlim = cutoff % base;
104 cutoff /= base;
105 if (neg) {
106 if (cutlim > 0) {
107 cutlim -= base;
108 cutoff += 1;
109 }
110 cutlim = -cutlim;
111 }
112 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
113 if (isdigit(c))
114 c -= '0';
115 else if (isalpha(c))
116 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
117 else
118 break;
119 if (c >= base)
120 break;
121 if (any < 0)
122 continue;
123 if (neg) {
124 if (acc < cutoff || (acc == cutoff && c > cutlim)) {
125 any = -1;
126 acc = LLONG_MIN;
127 errno = ERANGE;
128 } else {
129 any = 1;
130 acc *= base;
131 acc -= c;
132 }
133 } else {
134 if (acc > cutoff || (acc == cutoff && c > cutlim)) {
135 any = -1;
136 acc = LLONG_MAX;
137 errno = ERANGE;
138 } else {
139 any = 1;
140 acc *= base;
141 acc += c;
142 }
143 }
144 }
145 if (endptr != 0)
146 *endptr = (char *) (any ? s - 1 : nptr);
147 return (acc);
148}
149
150#ifdef __weak_alias
151__weak_alias(strtoq, strtoll);
152#else
153quad_t
154strtoq(nptr, endptr, base)
155 const char *nptr;
156 char **endptr;
157 int base;
158{
159
160 return ((quad_t)strtoll(nptr, endptr, base);
161}
162#endif
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..7d31ce79fb
--- /dev/null
+++ b/src/lib/libc/stdlib/strtoul.c
@@ -0,0 +1,108 @@
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.5 2003/06/02 20:18:38 millert 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(nptr, endptr, base)
47 const char *nptr;
48 char **endptr;
49 register int base;
50{
51 register const char *s;
52 register unsigned long acc, cutoff;
53 register int c;
54 register int neg, any, cutlim;
55
56 /*
57 * See strtol for comments as to the logic used.
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 cutoff = ULONG_MAX / (unsigned long)base;
81 cutlim = ULONG_MAX % (unsigned long)base;
82 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
83 if (isdigit(c))
84 c -= '0';
85 else if (isalpha(c))
86 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
87 else
88 break;
89 if (c >= base)
90 break;
91 if (any < 0)
92 continue;
93 if (acc > cutoff || acc == cutoff && c > cutlim) {
94 any = -1;
95 acc = ULONG_MAX;
96 errno = ERANGE;
97 } else {
98 any = 1;
99 acc *= (unsigned long)base;
100 acc += c;
101 }
102 }
103 if (neg && any > 0)
104 acc = -acc;
105 if (endptr != 0)
106 *endptr = (char *) (any ? s - 1 : nptr);
107 return (acc);
108}
diff --git a/src/lib/libc/stdlib/strtoull.c b/src/lib/libc/stdlib/strtoull.c
new file mode 100644
index 0000000000..a0ac9b381f
--- /dev/null
+++ b/src/lib/libc/stdlib/strtoull.c
@@ -0,0 +1,124 @@
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.2 2003/06/02 20:18:38 millert 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(nptr, endptr, base)
49 const char *nptr;
50 char **endptr;
51 int base;
52{
53 const char *s;
54 unsigned long long acc, cutoff;
55 int c;
56 int neg, any, cutlim;
57
58 /*
59 * See strtoq for comments as to the logic used.
60 */
61 s = nptr;
62 do {
63 c = (unsigned char) *s++;
64 } while (isspace(c));
65 if (c == '-') {
66 neg = 1;
67 c = *s++;
68 } else {
69 neg = 0;
70 if (c == '+')
71 c = *s++;
72 }
73 if ((base == 0 || base == 16) &&
74 c == '0' && (*s == 'x' || *s == 'X')) {
75 c = s[1];
76 s += 2;
77 base = 16;
78 }
79 if (base == 0)
80 base = c == '0' ? 8 : 10;
81
82 cutoff = ULLONG_MAX / (unsigned long long)base;
83 cutlim = ULLONG_MAX % (unsigned long long)base;
84 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
85 if (isdigit(c))
86 c -= '0';
87 else if (isalpha(c))
88 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
89 else
90 break;
91 if (c >= base)
92 break;
93 if (any < 0)
94 continue;
95 if (acc > cutoff || (acc == cutoff && c > cutlim)) {
96 any = -1;
97 acc = ULLONG_MAX;
98 errno = ERANGE;
99 } else {
100 any = 1;
101 acc *= (unsigned long long)base;
102 acc += c;
103 }
104 }
105 if (neg && any > 0)
106 acc = -acc;
107 if (endptr != 0)
108 *endptr = (char *) (any ? s - 1 : nptr);
109 return (acc);
110}
111
112#ifdef __weak_alias
113__weak_alias(strtouq, strtoull);
114#else
115u_quad_t
116strtouq(nptr, endptr, base)
117 const char *nptr;
118 char **endptr;
119 int base;
120{
121
122 return ((u_quad_t)strtoull(nptr, endptr, base);
123}
124#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..06b439230b
--- /dev/null
+++ b/src/lib/libc/stdlib/system.c
@@ -0,0 +1,78 @@
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.6 2003/06/02 20:18:38 millert 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(command)
45 const char *command;
46{
47 pid_t pid;
48 sig_t intsave, quitsave;
49 sigset_t mask, omask;
50 int pstat;
51 char *argp[] = {"sh", "-c", NULL, NULL};
52
53 if (!command) /* just checking... */
54 return(1);
55
56 argp[2] = (char *)command;
57
58 sigemptyset(&mask);
59 sigaddset(&mask, SIGCHLD);
60 sigprocmask(SIG_BLOCK, &mask, &omask);
61 switch (pid = vfork()) {
62 case -1: /* error */
63 sigprocmask(SIG_SETMASK, &omask, NULL);
64 return(-1);
65 case 0: /* child */
66 sigprocmask(SIG_SETMASK, &omask, NULL);
67 execve(_PATH_BSHELL, argp, environ);
68 _exit(127);
69 }
70
71 intsave = signal(SIGINT, SIG_IGN);
72 quitsave = signal(SIGQUIT, SIG_IGN);
73 pid = waitpid(pid, (int *)&pstat, 0);
74 sigprocmask(SIG_SETMASK, &omask, NULL);
75 (void)signal(SIGINT, intsave);
76 (void)signal(SIGQUIT, quitsave);
77 return (pid == -1 ? -1 : pstat);
78}
diff --git a/src/lib/libc/stdlib/tfind.c b/src/lib/libc/stdlib/tfind.c
new file mode 100644
index 0000000000..5c3b8c17f5
--- /dev/null
+++ b/src/lib/libc/stdlib/tfind.c
@@ -0,0 +1,41 @@
1/*
2 * Tree search generalized from Knuth (6.2.2) Algorithm T just like
3 * the AT&T man page says.
4 *
5 * The node_t structure is for internal use only, lint doesn't grok it.
6 *
7 * Written by reading the System V Interface Definition, not the code.
8 *
9 * Totally public domain.
10 */
11/*LINTLIBRARY*/
12#include <search.h>
13
14typedef struct node_t
15{
16 char *key;
17 struct node_t *llink, *rlink;
18} node;
19
20/* find a node, or return 0 */
21void *
22tfind(vkey, vrootp, compar)
23 const void *vkey; /* key to be found */
24 void *const *vrootp; /* address of the tree root */
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..0ad5866172
--- /dev/null
+++ b/src/lib/libc/stdlib/tsearch.c
@@ -0,0 +1,126 @@
1/*
2 * Tree search generalized from Knuth (6.2.2) Algorithm T just like
3 * the AT&T man page says.
4 *
5 * The node_t structure is for internal use only, lint doesn't grok it.
6 *
7 * Written by reading the System V Interface Definition, not the code.
8 *
9 * Totally public domain.
10 */
11/*LINTLIBRARY*/
12
13#include <search.h>
14#include <stdlib.h>
15
16typedef struct node_t {
17 char *key;
18 struct node_t *left, *right;
19} node;
20
21/* find or insert datum into search tree */
22void *
23tsearch(vkey, vrootp, compar)
24 const void *vkey; /* key to be located */
25 void **vrootp; /* address of tree root */
26 int (*compar)(const void *, const void *);
27{
28 register 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(vkey, vrootp, compar)
55 const void *vkey; /* key to be deleted */
56 void **vrootp; /* address of the root of tree */
57 int (*compar)(const void *, const void *);
58{
59 node **rootp = (node **)vrootp;
60 char *key = (char *)vkey;
61 node *p;
62 register node *q;
63 register node *r;
64 int cmp;
65
66 if (rootp == (struct node_t **)0 || (p = *rootp) == (struct node_t *)0)
67 return ((struct node_t *)0);
68 while ((cmp = (*compar)(key, (*rootp)->key)) != 0) {
69 p = *rootp;
70 rootp = (cmp < 0) ?
71 &(*rootp)->left : /* follow left branch */
72 &(*rootp)->right; /* follow right branch */
73 if (*rootp == (struct node_t *)0)
74 return ((void *)0); /* key not found */
75 }
76 r = (*rootp)->right; /* D1: */
77 if ((q = (*rootp)->left) == (struct node_t *)0) /* Left (struct node_t *)0? */
78 q = r;
79 else if (r != (struct node_t *)0) { /* Right link is null? */
80 if (r->left == (struct node_t *)0) { /* D2: Find successor */
81 r->left = q;
82 q = r;
83 } else { /* D3: Find (struct node_t *)0 link */
84 for (q = r->left; q->left != (struct node_t *)0; q = r->left)
85 r = q;
86 r->left = q->right;
87 q->left = (*rootp)->left;
88 q->right = (*rootp)->right;
89 }
90 }
91 free((struct node_t *) *rootp); /* D4: Free node */
92 *rootp = q; /* link parent to new node */
93 return(p);
94}
95
96/* Walk the nodes of a tree */
97static void
98trecurse(root, action, level)
99 register node *root; /* Root of the tree to be walked */
100 register void (*action)(); /* Function to be called at each node */
101 register int level;
102{
103 if (root->left == (struct node_t *)0 && root->right == (struct node_t *)0)
104 (*action)(root, leaf, level);
105 else {
106 (*action)(root, preorder, level);
107 if (root->left != (struct node_t *)0)
108 trecurse(root->left, action, level + 1);
109 (*action)(root, postorder, level);
110 if (root->right != (struct node_t *)0)
111 trecurse(root->right, action, level + 1);
112 (*action)(root, endorder, level);
113 }
114}
115
116/* Walk the nodes of a tree */
117void
118twalk(vroot, action)
119 const void *vroot; /* Root of the tree to be walked */
120 void (*action)(const void *, VISIT, int);
121{
122 node *root = (node *)vroot;
123
124 if (root != (node *)0 && action != (void(*)())0)
125 trecurse(root, action, 0);
126}