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_long.3377
-rw-r--r--src/lib/libc/stdlib/getopt_long.c544
-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.3432
-rw-r--r--src/lib/libc/stdlib/malloc.c1327
-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.c2529
-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
94 files changed, 13986 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..74f8ff5e7a
--- /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 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..2430c124f9
--- /dev/null
+++ b/src/lib/libc/stdlib/abort.c
@@ -0,0 +1,78 @@
1/*
2 * Copyright (c) 1985 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31static char *rcsid = "$OpenBSD: abort.c,v 1.13 2004/01/20 19:35:17 millert Exp $";
32#endif /* LIBC_SCCS and not lint */
33
34#include <signal.h>
35#include <stdlib.h>
36#include <unistd.h>
37#include "thread_private.h"
38#include "atexit.h"
39
40void
41abort(void)
42{
43 struct atexit *p = __atexit;
44 static int cleanup_called = 0;
45 sigset_t mask;
46
47
48 sigfillset(&mask);
49 /*
50 * don't block SIGABRT to give any handler a chance; we ignore
51 * any errors -- X311J doesn't allow abort to return anyway.
52 */
53 sigdelset(&mask, SIGABRT);
54 (void)_thread_sys_sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
55
56 /*
57 * POSIX requires we flush stdio buffers on abort
58 */
59 if (cleanup_called == 0) {
60 while (p != NULL && p->next != NULL)
61 p = p->next;
62 if (p != NULL && p->fns[0] != NULL) {
63 cleanup_called = 1;
64 (*p->fns[0])();
65 }
66 }
67
68 (void)kill(getpid(), SIGABRT);
69
70 /*
71 * if SIGABRT ignored, or caught and the handler returns, do
72 * it again, only harder.
73 */
74 (void)signal(SIGABRT, SIG_DFL);
75 (void)_thread_sys_sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
76 (void)kill(getpid(), SIGABRT);
77 _exit(1);
78}
diff --git a/src/lib/libc/stdlib/abs.3 b/src/lib/libc/stdlib/abs.3
new file mode 100644
index 0000000000..f0a6b8a23a
--- /dev/null
+++ b/src/lib/libc/stdlib/abs.3
@@ -0,0 +1,65 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information
6.\" Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: abs.3,v 1.6 2003/06/02 20:18:37 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt ABS 3
36.Os
37.Sh NAME
38.Nm abs
39.Nd integer absolute value function
40.Sh SYNOPSIS
41.Fd #include <stdlib.h>
42.Ft int
43.Fn abs "int j"
44.Sh DESCRIPTION
45The
46.Fn abs
47function computes the absolute value of the integer
48.Fa j .
49.Sh RETURN VALUES
50The
51.Fn abs
52function returns the absolute value.
53.Sh SEE ALSO
54.Xr cabs 3 ,
55.Xr floor 3 ,
56.Xr hypot 3 ,
57.Xr labs 3 ,
58.Xr math 3
59.Sh STANDARDS
60The
61.Fn abs
62function conforms to
63.St -ansiC .
64.Sh BUGS
65The absolute value of the most negative integer remains negative.
diff --git a/src/lib/libc/stdlib/abs.c b/src/lib/libc/stdlib/abs.c
new file mode 100644
index 0000000000..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..a75614310e
--- /dev/null
+++ b/src/lib/libc/stdlib/div.3
@@ -0,0 +1,63 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" Chris Torek.
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. Neither the name of the University nor the names of its contributors
15.\" may be used to endorse or promote products derived from this software
16.\" without specific prior written permission.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28.\" SUCH DAMAGE.
29.\"
30.\" $OpenBSD: div.3,v 1.7 2004/01/23 23:08:46 jmc Exp $
31.\"
32.Dd April 19, 1991
33.Dt DIV 3
34.Os
35.Sh NAME
36.Nm div
37.Nd return quotient and remainder from division
38.Sh SYNOPSIS
39.Fd #include <stdlib.h>
40.Ft div_t
41.Fn div "int num" "int denom"
42.Sh DESCRIPTION
43The
44.Fn div
45function computes the value
46.Fa num Ns / Ns Fa denom
47and returns the quotient and remainder in a structure named
48.Fa div_t
49that contains two
50.Li int
51members named
52.Fa quot
53and
54.Fa rem .
55.Sh SEE ALSO
56.Xr ldiv 3 ,
57.Xr math 3 ,
58.Xr qdiv 3
59.Sh STANDARDS
60The
61.Fn div
62function conforms to
63.St -ansiC .
diff --git a/src/lib/libc/stdlib/div.c b/src/lib/libc/stdlib/div.c
new file mode 100644
index 0000000000..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..689cb1c6f9
--- /dev/null
+++ b/src/lib/libc/stdlib/ecvt.3
@@ -0,0 +1,165 @@
1.\" $OpenBSD: ecvt.3,v 1.7 2004/01/25 14:48:32 jmc Exp $
2.\"
3.\" Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
4.\"
5.\" Permission to use, copy, modify, and distribute this software for any
6.\" purpose with or without fee is hereby granted, provided that the above
7.\" copyright notice and this permission notice appear in all copies.
8.\"
9.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16.\"
17.\" Sponsored in part by the Defense Advanced Research Projects
18.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
19.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
20.\"
21.Dd December 1, 2002
22.Dt ECVT 3
23.Os
24.Sh NAME
25.Nm ecvt ,
26.Nm fcvt ,
27.Nm gcvt
28.Nd convert double to
29.Tn ASCII
30string
31.Sh SYNOPSIS
32.Fd #include <stdlib.h>
33.Ft char *
34.Fn ecvt "double value" "int ndigit" "int *decpt" "int *sign"
35.Ft char *
36.Fn fcvt "double value" "int ndigit" "int *decpt" "int *sign"
37.Ft char *
38.Fn gcvt "double value" "int ndigit" "char *buf"
39.Sh DESCRIPTION
40.Bf -symbolic
41These functions are provided for compatibility with legacy code.
42New code should use the
43.Xr snprintf 3
44function for improved safety and portability.
45.Ef
46.Pp
47The
48.Fn ecvt ,
49.Fn fcvt
50and
51.Fn gcvt
52functions convert the double precision floating-point number
53.Fa value
54to a NUL-terminated
55.Tn ASCII
56string.
57.Pp
58The
59.Fn ecvt
60function converts
61.Fa value
62to a NUL-terminated string of exactly
63.Fa ndigit
64digits and returns a pointer to that string.
65The result is padded with zeroes from left to right as needed.
66There are no leading zeroes unless
67.Fa value
68itself is 0.
69The least significant digit is rounded in an implementation-dependent manner.
70The position of the decimal point relative to the beginning of the string
71is stored in
72.Fa decpt .
73A negative value indicates that the decimal point is located
74to the left of the returned digits (this occurs when there is no
75whole number component to
76.Fa value ) .
77If
78.Fa value
79is zero, it is unspecified whether the integer pointed to by
80.Fa decpt
81will be 0 or 1.
82The decimal point itself is not included in the returned string.
83If the sign of the result is negative, the integer pointed to by
84.Fa sign
85is non-zero; otherwise, it is 0.
86.Pp
87If the converted value is out of range or is not representable,
88the contents of the returned string are unspecified.
89.Pp
90The
91.Fn fcvt
92function is identical to
93.Fn ecvt
94with the exception that
95.Fa ndigit
96specifies the number of digits after the decimal point (zero-padded as
97needed).
98.Pp
99The
100.Fn gcvt
101function converts
102.Fa value
103to a NUL-terminated string similar to the %g
104.Xr printf 3
105format specifier and stores the result in
106.Fa buf .
107It produces
108.Fa ndigit
109significant digits similar to the %f
110.Xr printf 3
111format specifier where possible.
112If
113.Fa ndigit
114does allow sufficient precision, the result is stored in
115exponential notation similar to the %e
116.Xr printf 3
117format specifier.
118If
119.Fa value
120is less than zero,
121.Fa buf
122will be prefixed with a minus sign.
123A decimal point is included in the returned string if
124.Fa value
125is not a whole number.
126Unlike the
127.Fn ecvt
128and
129.Fn fcvt
130functions,
131.Fa buf
132is not zero-padded.
133.Sh RETURN VALUES
134The
135.Fn ecvt ,
136.Fn fcvt
137and
138.Fn gcvt
139functions return a NUL-terminated string representation of
140.Fa value .
141.Sh WARNINGS
142The
143.Fn ecvt
144and
145.Fn fcvt
146functions return a pointer to internal storage space that will be
147overwritten by subsequent calls to either function.
148.Pp
149The maximum possible precision of the return value is limited by the
150precision of a double and may not be the same on all architectures.
151.Pp
152The
153.Xr snprintf 3
154function is preferred over these functions for new code.
155.Sh SEE ALSO
156.Xr printf 3 ,
157.Xr strtod 3
158.Sh STANDARDS
159The
160.Fn ecvt ,
161.Fn fcvt
162and
163.Fn gcvt
164functions conform to
165.St -p1003.1-2001 .
diff --git a/src/lib/libc/stdlib/ecvt.c b/src/lib/libc/stdlib/ecvt.c
new file mode 100644
index 0000000000..657c531808
--- /dev/null
+++ b/src/lib/libc/stdlib/ecvt.c
@@ -0,0 +1,103 @@
1/* $OpenBSD: ecvt.c,v 1.3 2003/06/17 21:56:24 millert Exp $ */
2
3/*
4 * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * Sponsored in part by the Defense Advanced Research Projects
19 * Agency (DARPA) and Air Force Research Laboratory, Air Force
20 * Materiel Command, USAF, under agreement number F39502-99-1-0512.
21 */
22
23#if defined(LIBC_SCCS) && !defined(lint)
24static char rcsid[] = "$OpenBSD: ecvt.c,v 1.3 2003/06/17 21:56:24 millert Exp $";
25#endif /* LIBC_SCCS and not lint */
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30
31extern char *__dtoa(double, int, int, int *, int *, char **);
32static char *__cvt(double, int, int *, int *, int, int);
33
34static char *
35__cvt(double value, int ndigit, int *decpt, int *sign, int fmode, int pad)
36{
37 static char *s;
38 char *p, *rve;
39 size_t siz;
40
41 if (ndigit == 0) {
42 *sign = value < 0.0;
43 *decpt = 0;
44 return ("");
45 }
46
47 if (s) {
48 free(s);
49 s = NULL;
50 }
51
52 if (ndigit < 0)
53 siz = -ndigit + 1;
54 else
55 siz = ndigit + 1;
56
57
58 /* __dtoa() doesn't allocate space for 0 so we do it by hand */
59 if (value == 0.0) {
60 *decpt = 1 - fmode; /* 1 for 'e', 0 for 'f' */
61 *sign = 0;
62 if ((rve = s = (char *)malloc(siz)) == NULL)
63 return(NULL);
64 *rve++ = '0';
65 *rve = '\0';
66 } else {
67 p = __dtoa(value, fmode + 2, ndigit, decpt, sign, &rve);
68 if (*decpt == 9999) {
69 /* Nan or Infinity */
70 *decpt = 0;
71 return(p);
72 }
73 /* make a local copy and adjust rve to be in terms of s */
74 if (pad && fmode)
75 siz += *decpt;
76 if ((s = (char *)malloc(siz)) == NULL)
77 return(NULL);
78 (void) strlcpy(s, p, siz);
79 rve = s + (rve - p);
80 }
81
82 /* Add trailing zeros (unless we got NaN or Inf) */
83 if (pad && *decpt != 9999) {
84 siz -= rve - s;
85 while (--siz)
86 *rve++ = '0';
87 *rve = '\0';
88 }
89
90 return(s);
91}
92
93char *
94ecvt(double value, int ndigit, int *decpt, int *sign)
95{
96 return(__cvt(value, ndigit, decpt, sign, 0, 1));
97}
98
99char *
100fcvt(double value, int ndigit, int *decpt, int *sign)
101{
102 return(__cvt(value, ndigit, decpt, sign, 1, 1));
103}
diff --git a/src/lib/libc/stdlib/erand48.c b/src/lib/libc/stdlib/erand48.c
new file mode 100644
index 0000000000..b92dacffcc
--- /dev/null
+++ b/src/lib/libc/stdlib/erand48.c
@@ -0,0 +1,27 @@
1/*
2 * Copyright (c) 1993 Martin Birgmeier
3 * All rights reserved.
4 *
5 * You may redistribute unmodified or modified versions of this source
6 * code provided that the above copyright notice and this and the
7 * following conditions are retained.
8 *
9 * This software is provided ``as is'', and comes with no warranties
10 * of any kind. I shall in no event be liable for anything that happens
11 * to anyone/anything when using this software.
12 */
13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: erand48.c,v 1.2 1996/08/19 08:33:29 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
18#include "rand48.h"
19
20double
21erand48(unsigned short xseed[3])
22{
23 __dorand48(xseed);
24 return ldexp((double) xseed[0], -48) +
25 ldexp((double) xseed[1], -32) +
26 ldexp((double) xseed[2], -16);
27}
diff --git a/src/lib/libc/stdlib/exit.3 b/src/lib/libc/stdlib/exit.3
new file mode 100644
index 0000000000..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..054004e1d8
--- /dev/null
+++ b/src/lib/libc/stdlib/getenv.3
@@ -0,0 +1,142 @@
1.\" Copyright (c) 1988, 1991, 1993
2.\" The Regents of the University of California. All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information
6.\" Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: getenv.3,v 1.9 2004/01/23 23:08:46 jmc Exp $
33.\"
34.Dd December 11, 1993
35.Dt GETENV 3
36.Os
37.Sh NAME
38.Nm getenv ,
39.Nm putenv ,
40.Nm setenv ,
41.Nm unsetenv
42.Nd environment variable functions
43.Sh SYNOPSIS
44.Fd #include <stdlib.h>
45.Ft char *
46.Fn getenv "const char *name"
47.Ft int
48.Fn setenv "const char *name" "const char *value" "int overwrite"
49.Ft int
50.Fn putenv "const char *string"
51.Ft void
52.Fn unsetenv "const char *name"
53.Sh DESCRIPTION
54These functions set, unset, and fetch environment variables from the host
55.Em environment list .
56For compatibility with differing environment conventions, the given arguments
57.Fa name
58and
59.Fa value
60may be appended and prepended, respectively, with an equal sign
61.Dq Li \&= .
62.Pp
63The
64.Fn getenv
65function obtains the current value of the environment variable,
66.Fa name .
67If the variable
68.Fa name
69is not in the current environment, a null pointer is returned.
70.Pp
71The
72.Fn setenv
73function inserts or resets the environment variable
74.Fa name
75in the current environment list.
76If the variable
77.Fa name
78does not exist in the list, it is inserted with the given
79.Fa value .
80If the variable does exist, the argument
81.Fa overwrite
82is tested; if
83.Fa overwrite
84is zero, the variable is not reset, otherwise it is reset to the given
85.Fa value .
86.Pp
87The
88.Fn putenv
89function takes an argument of the form
90.Ar name Ns = Ns Ar value
91and is equivalent to:
92.Bd -literal -offset indent
93setenv(name, value, 1);
94.Ed
95.Pp
96The
97.Fn unsetenv
98function deletes all instances of the variable name pointed to by
99.Fa name
100from the list.
101.Sh RETURN VALUES
102The functions
103.Fn setenv
104and
105.Fn putenv
106return zero if successful; otherwise the global variable
107.Va errno
108is set to indicate the error and \-1 is returned.
109.Pp
110If
111.Fn getenv
112is successful, the string returned should be considered read-only.
113.Sh ERRORS
114.Bl -tag -width [ENOMEM]
115.It Bq Er ENOMEM
116The function
117.Fn setenv
118or
119.Fn putenv
120failed because they were unable to allocate memory for the environment.
121.El
122.Sh SEE ALSO
123.Xr csh 1 ,
124.Xr sh 1 ,
125.Xr execve 2 ,
126.Xr environ 7
127.Sh STANDARDS
128The
129.Fn getenv
130function conforms to
131.St -ansiC .
132.Sh HISTORY
133The functions
134.Fn setenv
135and
136.Fn unsetenv
137appeared in
138.At v7 .
139The
140.Fn putenv
141function appeared in
142.Bx 4.3 Reno .
diff --git a/src/lib/libc/stdlib/getenv.c b/src/lib/libc/stdlib/getenv.c
new file mode 100644
index 0000000000..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_long.3 b/src/lib/libc/stdlib/getopt_long.3
new file mode 100644
index 0000000000..978583ef96
--- /dev/null
+++ b/src/lib/libc/stdlib/getopt_long.3
@@ -0,0 +1,377 @@
1.\" $OpenBSD: getopt_long.3,v 1.10 2004/01/06 23:44:28 fgsch Exp $
2.\" $NetBSD: getopt_long.3,v 1.11 2002/10/02 10:54:19 wiz Exp $
3.\"
4.\" Copyright (c) 1988, 1991, 1993
5.\" The Regents of the University of California. All rights reserved.
6.\"
7.\" Redistribution and use in source and binary forms, with or without
8.\" modification, are permitted provided that the following conditions
9.\" are met:
10.\" 1. Redistributions of source code must retain the above copyright
11.\" notice, this list of conditions and the following disclaimer.
12.\" 2. Redistributions in binary form must reproduce the above copyright
13.\" notice, this list of conditions and the following disclaimer in the
14.\" documentation and/or other materials provided with the distribution.
15.\" 3. Neither the name of the University nor the names of its contributors
16.\" may be used to endorse or promote products derived from this software
17.\" without specific prior written permission.
18.\"
19.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29.\" SUCH DAMAGE.
30.\"
31.\" @(#)getopt.3 8.5 (Berkeley) 4/27/95
32.\"
33.Dd April 1, 2000
34.Dt GETOPT_LONG 3
35.Os
36.Sh NAME
37.Nm getopt_long ,
38.Nm getopt_long_only
39.Nd get long options from command line argument list
40.Sh SYNOPSIS
41.Fd #include <getopt.h>
42.Vt extern char *optarg;
43.Vt extern int optind;
44.Vt extern int optopt;
45.Vt extern int opterr;
46.Vt extern int optreset;
47.Ft int
48.Fn getopt_long "int argc" "char * const *argv" "const char *optstring" "const struct option *longopts" "int *longindex"
49.Ft int
50.Fn getopt_long_only "int argc" "char * const *argv" "const char *optstring" "const struct option *longopts" "int *longindex"
51.Sh DESCRIPTION
52The
53.Fn getopt_long
54function is similar to
55.Xr getopt 3
56but it accepts options in two forms: words and characters.
57The
58.Fn getopt_long
59function provides a superset of the functionality of
60.Xr getopt 3 .
61.Fn getopt_long
62can be used in two ways.
63In the first way, every long option understood by the program has a
64corresponding short option, and the option structure is only used to
65translate from long options to short options.
66When used in this fashion,
67.Fn getopt_long
68behaves identically to
69.Xr getopt 3 .
70This is a good way to add long option processing to an existing program
71with the minimum of rewriting.
72.Pp
73In the second mechanism, a long option sets a flag in the
74.Fa option
75structure passed, or will store a pointer to the command line argument
76in the
77.Fa option
78structure passed to it for options that take arguments.
79Additionally, the long option's argument may be specified as a single
80argument with an equal sign, e.g.
81.Bd -literal
82myprogram --myoption=somevalue
83.Ed
84.Pp
85When a long option is processed the call to
86.Fn getopt_long
87will return 0.
88For this reason, long option processing without
89shortcuts is not backwards compatible with
90.Xr getopt 3 .
91.Pp
92It is possible to combine these methods, providing for long options
93processing with short option equivalents for some options.
94Less frequently used options would be processed as long options only.
95.Pp
96The
97.Fn getopt_long
98call requires a structure to be initialized describing the long
99options.
100The structure is:
101.Bd -literal
102struct option {
103 char *name;
104 int has_arg;
105 int *flag;
106 int val;
107};
108.Ed
109.Pp
110The
111.Fa name
112field should contain the option name without the leading double dash.
113.Pp
114The
115.Fa has_arg
116field should be one of:
117.Bl -tag -width "optional_argument"
118.It Li no_argument
119no argument to the option is expect.
120.It Li required_argument
121an argument to the option is required.
122.It Li optional_argument
123an argument to the option may be presented.
124.El
125.Pp
126If
127.Fa flag
128is not
129.Dv NULL ,
130then the integer pointed to by it will be set to the value in the
131.Fa val
132field.
133If the
134.Fa flag
135field is
136.Dv NULL ,
137then the
138.Fa val
139field will be returned.
140Setting
141.Fa flag
142to
143.Dv NULL
144and setting
145.Fa val
146to the corresponding short option will make this function act just
147like
148.Xr getopt 3 .
149.Pp
150If the
151.Fa longindex
152field is not
153.Dv NULL ,
154then the integer pointed to by it will be set to the index of the long
155option relative to
156.Fa longopts .
157.Pp
158The last element of the
159.Fa longopts
160array has to be filled with zeroes.
161.Pp
162The
163.Fn getopt_long_only
164function behaves identically to
165.Fn getopt_long
166with the exception that long options may start with
167.Sq -
168in addition to
169.Sq -- .
170If an option starting with
171.Sq -
172does not match a long option but does match a single-character option,
173the single-character option is returned.
174.Sh RETURN VALUES
175If the
176.Fa flag
177field in
178.Li struct option
179is
180.Dv NULL ,
181.Fn getopt_long
182and
183.Fn getopt_long_only
184return the value specified in the
185.Fa val
186field, which is usually just the corresponding short option.
187If
188.Fa flag
189is not
190.Dv NULL ,
191these functions return 0 and store
192.Fa val
193in the location pointed to by
194.Fa flag .
195These functions return
196.Sq \:
197if there was a missing option argument,
198.Sq \&?
199if the user specified an unknown or ambiguous option, and
200\-1 when the argument list has been exhausted.
201.Sh EXAMPLES
202.Bd -literal -compact
203int bflag, ch, fd;
204int daggerset;
205
206/* options descriptor */
207static struct option longopts[] = {
208 { "buffy", no_argument, NULL, 'b' },
209 { "fluoride", required_argument, NULL, 'f' },
210 { "daggerset", no_argument, &daggerset, 1 },
211 { NULL, 0, NULL, 0 }
212};
213
214bflag = 0;
215while ((ch = getopt_long(argc, argv, "bf:", longopts, NULL)) != -1)
216 switch (ch) {
217 case 'b':
218 bflag = 1;
219 break;
220 case 'f':
221 if ((fd = open(optarg, O_RDONLY, 0)) == -1)
222 err(1, "unable to open %s", optarg);
223 break;
224 case 0:
225 if (daggerset) {
226 fprintf(stderr,"Buffy will use her dagger to "
227 "apply fluoride to dracula's teeth\en");
228 }
229 break;
230 default:
231 usage();
232}
233argc -= optind;
234argv += optind;
235.Ed
236.Sh IMPLEMENTATION DIFFERENCES
237This section describes differences to the GNU implementation
238found in glibc-2.1.3:
239.Bl -tag -width "xxx"
240.It Li o
241handling of - as first char of option string in presence of
242environment variable POSIXLY_CORRECT:
243.Bl -tag -width "OpenBSD"
244.It Li GNU
245ignores POSIXLY_CORRECT and returns non-options as
246arguments to option '\e1'.
247.It Li OpenBSD
248honors POSIXLY_CORRECT and stops at the first non-option.
249.El
250.It Li o
251handling of - within the option string (not the first character):
252.Bl -tag -width "OpenBSD"
253.It Li GNU
254treats a
255.Ql -
256on the command line as a non-argument.
257.It Li OpenBSD
258a
259.Ql -
260within the option string matches a
261.Ql -
262(single dash) on the command line.
263This functionality is provided for backward compatibility with
264programs, such as
265.Xr su 1 ,
266that use
267.Ql -
268as an option flag.
269This practice is wrong, and should not be used in any current development.
270.El
271.It Li o
272handling of :: in options string in presence of POSIXLY_CORRECT:
273.Bl -tag -width "OpenBSD"
274.It Li Both
275GNU and OpenBSD ignore POSIXLY_CORRECT here and take :: to
276mean the preceding option takes an optional argument.
277.El
278.It Li o
279return value in case of missing argument if first character
280(after + or -) in option string is not ':':
281.Bl -tag -width "OpenBSD"
282.It Li GNU
283returns '?'
284.It OpenBSD
285returns ':' (since OpenBSD's getopt does).
286.El
287.It Li o
288handling of --a in getopt:
289.Bl -tag -width "OpenBSD"
290.It Li GNU
291parses this as option '-', option 'a'.
292.It Li OpenBSD
293parses this as '--', and returns \-1 (ignoring the a).
294(Because the original getopt does.)
295.El
296.It Li o
297setting of optopt for long options with flag !=
298.Dv NULL :
299.Bl -tag -width "OpenBSD"
300.It Li GNU
301sets optopt to val.
302.It Li OpenBSD
303sets optopt to 0 (since val would never be returned).
304.El
305.It Li o
306handling of -W with W; in option string in getopt (not getopt_long):
307.Bl -tag -width "OpenBSD"
308.It Li GNU
309causes a segfault.
310.It Li OpenBSD
311no special handling is done;
312.Dq W;
313is interpreted as two separate options, neither of which take an argument.
314.El
315.It Li o
316setting of optarg for long options without an argument that are
317invoked via -W (W; in option string):
318.Bl -tag -width "OpenBSD"
319.It Li GNU
320sets optarg to the option name (the argument of -W).
321.It Li OpenBSD
322sets optarg to
323.Dv NULL
324(the argument of the long option).
325.El
326.It Li o
327handling of -W with an argument that is not (a prefix to) a known
328long option (W; in option string):
329.Bl -tag -width "OpenBSD"
330.It Li GNU
331returns -W with optarg set to the unknown option.
332.It Li OpenBSD
333treats this as an error (unknown option) and returns '?' with
334optopt set to 0 and optarg set to
335.Dv NULL
336(as GNU's man page documents).
337.El
338.It Li o
339The error messages are different.
340.It Li o
341OpenBSD does not permute the argument vector at the same points in
342the calling sequence as GNU does.
343The aspects normally used by the caller
344(ordering after \-1 is returned, value of optind relative
345to current positions) are the same, though.
346(We do fewer variable swaps.)
347.El
348.Sh ENVIRONMENT
349.Bl -tag -width POSIXLY_CORRECT
350.It Ev POSIXLY_CORRECT
351If set, option processing stops when the first non-option is found and
352a leading
353.Sq -
354or
355.Sq +
356in the
357.Ar optstring
358is ignored.
359.El
360.Sh SEE ALSO
361.Xr getopt 3
362.Sh HISTORY
363The
364.Fn getopt_long
365and
366.Fn getopt_long_only
367functions first appeared in GNU libiberty.
368This implementation first appeared in
369.Ox 3.3 .
370.Sh BUGS
371The
372.Ar argv
373argument is not really
374.Dv const
375as its elements may be permuted (unless
376.Ev POSIXLY_CORRECT
377is set).
diff --git a/src/lib/libc/stdlib/getopt_long.c b/src/lib/libc/stdlib/getopt_long.c
new file mode 100644
index 0000000000..6079ce3503
--- /dev/null
+++ b/src/lib/libc/stdlib/getopt_long.c
@@ -0,0 +1,544 @@
1/* $OpenBSD: getopt_long.c,v 1.16 2004/02/04 18:17:25 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.16 2004/02/04 18:17:25 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 * If we have "-" do nothing, if "--" we are done.
383 */
384 if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
385 optind++;
386 place = EMSG;
387 /*
388 * We found an option (--), so if we skipped
389 * non-options, we have to permute.
390 */
391 if (nonopt_end != -1) {
392 permute_args(nonopt_start, nonopt_end,
393 optind, nargv);
394 optind -= nonopt_end - nonopt_start;
395 }
396 nonopt_start = nonopt_end = -1;
397 return (-1);
398 }
399 }
400
401 /*
402 * Check long options if:
403 * 1) we were passed some
404 * 2) the arg is not just "-"
405 * 3) either the arg starts with -- we are getopt_long_only()
406 */
407 if (long_options != NULL && place != nargv[optind] &&
408 (*place == '-' || (flags & FLAG_LONGONLY))) {
409 short_too = 0;
410 if (*place == '-')
411 place++; /* --foo long option */
412 else if (*place != ':' && strchr(options, *place) != NULL)
413 short_too = 1; /* could be short option too */
414
415 optchar = parse_long_options(nargv, options, long_options,
416 idx, short_too);
417 if (optchar != -1) {
418 place = EMSG;
419 return (optchar);
420 }
421 }
422
423 if ((optchar = (int)*place++) == (int)':' ||
424 optchar == (int)'-' && *place != '\0' ||
425 (oli = strchr(options, optchar)) == NULL) {
426 /*
427 * If the user specified "-" and '-' isn't listed in
428 * options, return -1 (non-option) as per POSIX.
429 * Otherwise, it is an unknown option character (or ':').
430 */
431 if (optchar == (int)'-' && *place == '\0')
432 return (-1);
433 if (!*place)
434 ++optind;
435 if (PRINT_ERROR)
436 warnx(illoptchar, optchar);
437 optopt = optchar;
438 return (BADCH);
439 }
440 if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
441 /* -W long-option */
442 if (*place) /* no space */
443 /* NOTHING */;
444 else if (++optind >= nargc) { /* no arg */
445 place = EMSG;
446 if (PRINT_ERROR)
447 warnx(recargchar, optchar);
448 optopt = optchar;
449 return (BADARG);
450 } else /* white space */
451 place = nargv[optind];
452 optchar = parse_long_options(nargv, options, long_options,
453 idx, 0);
454 place = EMSG;
455 return (optchar);
456 }
457 if (*++oli != ':') { /* doesn't take argument */
458 if (!*place)
459 ++optind;
460 } else { /* takes (optional) argument */
461 optarg = NULL;
462 if (*place) /* no white space */
463 optarg = place;
464 /* XXX: disable test for :: if PC? (GNU doesn't) */
465 else if (oli[1] != ':') { /* arg not optional */
466 if (++optind >= nargc) { /* no arg */
467 place = EMSG;
468 if (PRINT_ERROR)
469 warnx(recargchar, optchar);
470 optopt = optchar;
471 return (BADARG);
472 } else
473 optarg = nargv[optind];
474 } else if (!(flags & FLAG_PERMUTE)) {
475 /*
476 * If permutation is disabled, we can accept an
477 * optional arg separated by whitespace.
478 */
479 if (optind + 1 < nargc)
480 optarg = nargv[++optind];
481 }
482 place = EMSG;
483 ++optind;
484 }
485 /* dump back option letter */
486 return (optchar);
487}
488
489#ifdef REPLACE_GETOPT
490/*
491 * getopt --
492 * Parse argc/argv argument vector.
493 *
494 * [eventually this will replace the BSD getopt]
495 */
496int
497getopt(int nargc, char * const *nargv, const char *options)
498{
499
500 /*
501 * We dont' pass FLAG_PERMUTE to getopt_internal() since
502 * the BSD getopt(3) (unlike GNU) has never done this.
503 *
504 * Furthermore, since many privileged programs call getopt()
505 * before dropping privileges it makes sense to keep things
506 * as simple (and bug-free) as possible.
507 */
508 return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
509}
510#endif /* REPLACE_GETOPT */
511
512/*
513 * getopt_long --
514 * Parse argc/argv argument vector.
515 */
516int
517getopt_long(nargc, nargv, options, long_options, idx)
518 int nargc;
519 char * const *nargv;
520 const char *options;
521 const struct option *long_options;
522 int *idx;
523{
524
525 return (getopt_internal(nargc, nargv, options, long_options, idx,
526 FLAG_PERMUTE));
527}
528
529/*
530 * getopt_long_only --
531 * Parse argc/argv argument vector.
532 */
533int
534getopt_long_only(nargc, nargv, options, long_options, idx)
535 int nargc;
536 char * const *nargv;
537 const char *options;
538 const struct option *long_options;
539 int *idx;
540{
541
542 return (getopt_internal(nargc, nargv, options, long_options, idx,
543 FLAG_PERMUTE|FLAG_LONGONLY));
544}
diff --git a/src/lib/libc/stdlib/getsubopt.3 b/src/lib/libc/stdlib/getsubopt.3
new file mode 100644
index 0000000000..8513cfb66a
--- /dev/null
+++ b/src/lib/libc/stdlib/getsubopt.3
@@ -0,0 +1,143 @@
1.\" $OpenBSD: getsubopt.3,v 1.8 2004/01/23 23:08:46 jmc Exp $
2.\"
3.\" Copyright (c) 1990, 1991, 1993
4.\" The Regents of the University of California. All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. Neither the name of the University nor the names of its contributors
15.\" may be used to endorse or promote products derived from this software
16.\" without specific prior written permission.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28.\" SUCH DAMAGE.
29.\"
30.\" @(#)getsubopt.3 8.1 (Berkeley) 6/9/93
31.\"
32.Dd June 9, 1993
33.Dt GETSUBOPT 3
34.Os
35.Sh NAME
36.Nm getsubopt
37.Nd get sub options from an argument
38.Sh SYNOPSIS
39.Fd #include <stdlib.h>
40.Vt extern char *suboptarg;
41.Ft int
42.Fn getsubopt "char **optionp" "char * const *tokens" "char **valuep"
43.Sh DESCRIPTION
44The
45.Fn getsubopt
46function parses a string containing tokens delimited by one or more
47tab, space or comma
48.Pq Ql \&,
49characters.
50It is intended for use in parsing groups of option arguments provided
51as part of a utility command line.
52.Pp
53The argument
54.Fa optionp
55is a pointer to a pointer to the string.
56The argument
57.Fa tokens
58is a pointer to a null-terminated array of pointers to strings.
59.Pp
60The
61.Fn getsubopt
62function returns the zero-based offset of the pointer in the
63.Fa tokens
64array referencing a string which matches the first token
65in the string, or \-1 if the string contains no tokens or
66.Fa tokens
67does not contain a matching string.
68.Pp
69If the token is of the form
70.Ar name Ns = Ns Ar value ,
71the location referenced by
72.Fa valuep
73will be set to point to the start of the
74.Dq value
75portion of the token.
76.Pp
77On return from
78.Fn getsubopt ,
79.Fa optionp
80will be set to point to the start of the next token in the string,
81or the 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..cd8110ed90
--- /dev/null
+++ b/src/lib/libc/stdlib/insque.3
@@ -0,0 +1,100 @@
1.\" $OpenBSD: insque.3,v 1.3 2004/01/25 14:48:32 jmc Exp $
2.\" Copyright (c) 1993 John Brezak
3.\" All rights reserved.
4.\"
5.\" Redistribution and use in source and binary forms, with or without
6.\" modification, are permitted provided that the following conditions
7.\" are met:
8.\" 1. Redistributions of source code must retain the above copyright
9.\" notice, this list of conditions and the following disclaimer.
10.\" 2. Redistributions in binary form must reproduce the above copyright
11.\" notice, this list of conditions and the following disclaimer in the
12.\" documentation and/or other materials provided with the distribution.
13.\" 3. The name of the author may be used to endorse or promote products
14.\" derived from this software without specific prior written permission.
15.\"
16.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND
17.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
20.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26.\" SUCH DAMAGE.
27.\"
28.\"
29.Dd August 12, 1993
30.Dt INSQUE 3
31.Os
32.Sh NAME
33.Nm insque ,
34.Nm remque
35.Nd insert/remove element from a queue
36.Sh SYNOPSIS
37.Fd #include <search.h>
38.Ft void
39.Fn insque "void *elem" "void *pred"
40.Ft void
41.Fn remque "void *elem"
42.Sh DESCRIPTION
43.Bf -symbolic
44These interfaces have been superceded by the
45.Xr queue 3
46macros and are provided for compatibility with legacy code.
47.Ef
48.Pp
49.Fn insque
50and
51.Fn remque
52manipulate queues built from doubly linked lists.
53The queue can be either circular or linear.
54Each element in the queue must be of the following form:
55.Bd -literal
56struct qelem {
57 struct qelem *q_forw;
58 struct qelem *q_back;
59 char q_data[];
60};
61.Ed
62.Pp
63The first two elements in the struct must be pointers of the
64same type that point to the previous and next elements in
65the queue respectively.
66Any subsequent data in the struct is application-dependent.
67.Pp
68The
69.Fn insque
70function inserts
71.Fa elem
72into a queue immediately after
73.Fa pred .
74.Pp
75The
76.Fn remque
77function removes
78.Fa elem
79from the queue.
80.Sh DIAGNOSTICS
81These functions are not atomic unless that machine architecture allows it.
82.Sh SEE ALSO
83.Xr queue 3
84.Sh STANDARDS
85The
86.Fn lsearch
87and
88.Fn lfind
89functions conform to the
90.St -p1003.1-2001
91and
92.St -xpg4.3 .
93specifications.
94.Sh HISTORY
95The
96.Fn insque
97and
98.Fn remque
99functions are derived from the insque and remque instructions on a
100.Tn VAX .
diff --git a/src/lib/libc/stdlib/insque.c b/src/lib/libc/stdlib/insque.c
new file mode 100644
index 0000000000..549246c71f
--- /dev/null
+++ b/src/lib/libc/stdlib/insque.c
@@ -0,0 +1,52 @@
1/* $OpenBSD: insque.c,v 1.1 2003/05/08 23:26:30 millert Exp $ */
2
3/*
4 * Copyright (c) 1993 John Brezak
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#if defined(LIBC_SCCS) && !defined(lint)
32static char *rcsid = "$OpenBSD: insque.c,v 1.1 2003/05/08 23:26:30 millert Exp $";
33#endif /* LIBC_SCCS and not lint */
34
35#include <search.h>
36
37struct qelem {
38 struct qelem *q_forw;
39 struct qelem *q_back;
40};
41
42void
43insque(void *entry, void *pred)
44{
45 struct qelem *e = (struct qelem *) entry;
46 struct qelem *p = (struct qelem *) pred;
47
48 e->q_forw = p->q_forw;
49 e->q_back = p;
50 p->q_forw->q_back = e;
51 p->q_forw = e;
52}
diff --git a/src/lib/libc/stdlib/jrand48.c b/src/lib/libc/stdlib/jrand48.c
new file mode 100644
index 0000000000..99cddb71e5
--- /dev/null
+++ b/src/lib/libc/stdlib/jrand48.c
@@ -0,0 +1,25 @@
1/*
2 * Copyright (c) 1993 Martin Birgmeier
3 * All rights reserved.
4 *
5 * You may redistribute unmodified or modified versions of this source
6 * code provided that the above copyright notice and this and the
7 * following conditions are retained.
8 *
9 * This software is provided ``as is'', and comes with no warranties
10 * of any kind. I shall in no event be liable for anything that happens
11 * to anyone/anything when using this software.
12 */
13
14#if defined(LIBC_SCCS) && !defined(lint)
15static char rcsid[] = "$OpenBSD: jrand48.c,v 1.2 1996/08/19 08:33:33 tholo Exp $";
16#endif /* LIBC_SCCS and not lint */
17
18#include "rand48.h"
19
20long
21jrand48(unsigned short xseed[3])
22{
23 __dorand48(xseed);
24 return ((long) xseed[2] << 16) + (long) xseed[1];
25}
diff --git a/src/lib/libc/stdlib/l64a.c b/src/lib/libc/stdlib/l64a.c
new file mode 100644
index 0000000000..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..63e1f2165c
--- /dev/null
+++ b/src/lib/libc/stdlib/ldiv.3
@@ -0,0 +1,65 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" Chris Torek and the American National Standards Committee X3,
6.\" on Information Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: ldiv.3,v 1.7 2004/01/23 23:08:46 jmc Exp $
33.\"
34.Dd June 29, 1991
35.Dt LDIV 3
36.Os
37.Sh NAME
38.Nm ldiv
39.Nd return quotient and remainder from division
40.Sh SYNOPSIS
41.Fd #include <stdlib.h>
42.Ft ldiv_t
43.Fn ldiv "long num" "long denom"
44.Sh DESCRIPTION
45The
46.Fn ldiv
47function computes the value
48.Fa num Ns / Ns Fa denom
49and returns the quotient and remainder in a structure named
50.Li ldiv_t
51that contains two
52.Li long integer
53members named
54.Fa quot
55and
56.Fa rem .
57.Sh SEE ALSO
58.Xr div 3 ,
59.Xr math 3 ,
60.Xr qdiv 3
61.Sh STANDARDS
62The
63.Fn ldiv
64function conforms to
65.St -ansiC .
diff --git a/src/lib/libc/stdlib/ldiv.c b/src/lib/libc/stdlib/ldiv.c
new file mode 100644
index 0000000000..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..2adc51096d
--- /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-2001
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..1154537385
--- /dev/null
+++ b/src/lib/libc/stdlib/malloc.3
@@ -0,0 +1,432 @@
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.36 2004/02/09 13:07:42 espie Exp $
34.\"
35.Dd August 27, 1996
36.Dt MALLOC 3
37.Os
38.Sh NAME
39.Nm malloc ,
40.Nm calloc ,
41.Nm realloc ,
42.Nm free ,
43.Nm cfree
44.Nd memory allocation and deallocation
45.Sh SYNOPSIS
46.Fd #include <stdlib.h>
47.Ft void *
48.Fn malloc "size_t size"
49.Ft void *
50.Fn calloc "size_t nmemb" "size_t size"
51.Ft void *
52.Fn realloc "void *ptr" "size_t size"
53.Ft void
54.Fn free "void *ptr"
55.Ft void
56.Fn cfree "void *ptr"
57.Ft char *
58.Va malloc_options ;
59.Sh DESCRIPTION
60The
61.Fn malloc
62function allocates uninitialized space for an object whose
63size is specified by
64.Fa size .
65The
66.Fn malloc
67function maintains multiple lists of free blocks according to size, allocating
68space from the appropriate list.
69.Pp
70The allocated space is
71suitably aligned (after possible pointer
72coercion) for storage of any type of object.
73If the space is of
74.Em pagesize
75or larger, the memory returned will be page-aligned.
76.Pp
77Allocation of a zero size object returns a pointer to a zero size object.
78This zero size object is access protected, so any access to it will
79generate an exception (SIGSEGV).
80Many zero-sized objects can be placed consecutively in shared
81protected pages.
82The minimum size of the protection on each object is suitably aligned and
83sized as previously stated, but the protection may extend further depending
84on where in a protected zone the object lands.
85.Pp
86The
87.Fn calloc
88function allocates space for an array of
89.Fa nmemb
90objects, each of whose size is
91.Fa size .
92The space is initialized to all bits zero.
93.Pp
94The
95.Fn free
96function causes the space pointed to by
97.Fa ptr
98to be deallocated, that is, at least made available for further allocation,
99but if possible, it will passed back to the kernel with
100.Xr sbrk 2 .
101If
102.Fa ptr
103is a null pointer, no action occurs.
104.Pp
105A
106.Fn cfree
107function is also provided for compatibility with old systems and other
108.Nm malloc
109libraries; it is simply an alias for
110.Fn free .
111.Pp
112The
113.Fn realloc
114function changes the size of the object pointed to by
115.Fa ptr
116to
117.Fa size
118bytes and returns a pointer to the (possibly moved) object.
119The contents of the object are unchanged up to the lesser
120of the new and old sizes.
121If the new size is larger, the value of the newly allocated portion
122of the object is indeterminate and uninitialized.
123If
124.Fa ptr
125is a null pointer, the
126.Fn realloc
127function behaves like the
128.Fn malloc
129function for the specified size.
130If the space cannot be allocated, the object
131pointed to by
132.Fa ptr
133is unchanged.
134If
135.Fa size
136is zero and
137.Fa ptr
138is not a null pointer, the object it points to is freed and a new zero size
139object is returned.
140.Pp
141When using
142.Fn realloc
143one must be careful to avoid the following idiom:
144.Bd -literal -offset indent
145size += 50;
146if ((p = realloc(p, size)) == NULL)
147 return (NULL);
148.Ed
149.Pp
150Do not adjust the variable describing how much memory has been allocated
151until one knows the allocation has been successful.
152This can cause aberrant program behavior if the incorrect size value is used.
153In most cases, the above sample will also result in a leak of memory.
154As stated earlier, a return value of
155.Dv NULL
156indicates that the old object still remains allocated.
157Better code looks like this:
158.Bd -literal -offset indent
159newsize = size + 50;
160if ((newp = realloc(p, newsize)) == NULL) {
161 free(p);
162 p = NULL;
163 size = 0;
164 return (NULL);
165}
166p = newp;
167size = newsize;
168.Ed
169.Pp
170Malloc will first look for a symbolic link called
171.Pa /etc/malloc.conf
172and next check the environment for a variable called
173.Ev MALLOC_OPTIONS
174and finally for the global variable
175.Va malloc_options
176and scan them for flags in that order.
177Flags are single letters, uppercase means on, lowercase means off.
178.Bl -tag -width indent
179.It Cm A
180.Dq Abort .
181.Fn malloc
182will coredump the process, rather than tolerate failure.
183This is a very handy debugging aid, since the core file will represent the
184time of failure, rather than when the null pointer was accessed.
185.Pp
186.It Cm D
187.Dq Dump .
188.Fn malloc
189will dump statistics in a file called
190.Pa malloc.out
191at exit.
192This option requires the library to have been compiled with -DMALLOC_STATS in
193order to have any effect.
194.Pp
195.It Cm F
196.Dq Freeguard .
197Enable use after free protection.
198Unused pages on the freelist are read and write protected to
199cause a segmentation fault upon access.
200.Pp
201.It Cm G
202.Dq Guard .
203Enable guard pages and chunk randomization.
204Each page size or larger allocation is followed by a guard page that will
205cause a segmentation fault upon any access.
206Smaller than page size chunks are returned in a random order.
207.Pp
208.It Cm H
209.Dq Hint .
210Pass a hint to the kernel about pages we don't use.
211If the machine is paging a lot this may help a bit.
212.Pp
213.It Cm J
214.Dq Junk .
215Fill some junk into the area allocated.
216Currently junk is bytes of 0xd0; this is pronounced
217.Dq Duh .
218\&:-)
219.Pp
220.It Cm N
221Do not output warning messages when encountering possible corruption
222or bad pointers.
223.Pp
224.It Cm R
225.Dq realloc .
226Always reallocate when
227.Fn realloc
228is called, even if the initial allocation was big enough.
229This can substantially aid in compacting memory.
230.\".Pp
231.\".It Cm U
232.\".Dq utrace .
233.\"Generate entries for
234.\".Xr ktrace 1
235.\"for all operations.
236.\"Consult the source for this one.
237.Pp
238.It Cm X
239.Dq xmalloc .
240Rather than return failure,
241.Xr abort 3
242the program with a diagnostic message on stderr.
243It is the intention that this option be set at compile time by
244including in the source:
245.Bd -literal -offset indent
246extern char *malloc_options;
247malloc_options = "X";
248.Ed
249.Pp
250.It Cm Z
251.Dq Zero .
252Fill some junk into the area allocated (see
253.Cm J ) ,
254except for the exact length the user asked for, which is zeroed.
255.Pp
256.It Cm <
257.Dq Half the cache size .
258Reduce the size of the cache by a factor of two.
259.Pp
260.It Cm >
261.Dq Double the cache size .
262Double the size of the cache by a factor of two.
263.El
264.Pp
265So to set a systemwide reduction of cache size and coredumps on problems
266one would:
267.Li ln -s 'A<' /etc/malloc.conf
268.Pp
269The
270.Cm J
271and
272.Cm Z
273flags are mostly for testing and debugging.
274If a program changes behavior if either of these options are used,
275it is buggy.
276.Pp
277The default cache size is 16 pages.
278.Sh RETURN VALUES
279The
280.Fn malloc
281and
282.Fn calloc
283functions return a pointer to the allocated space if successful; otherwise,
284a null pointer is returned and
285.Va errno
286is set to
287.Er ENOMEM .
288.Pp
289The
290.Fn free
291and
292.Fn cfree
293functions return no value.
294.Pp
295The
296.Fn realloc
297function returns a pointer to the (possibly moved) allocated space
298if successful; otherwise, a null pointer is returned and
299.Va errno
300is set to
301.Er ENOMEM .
302.Sh ENVIRONMENT
303See above.
304.Sh FILES
305.Bl -tag -width "/etc/malloc.conf"
306.It Pa /etc/malloc.conf
307symbolic link to filename containing option flags
308.El
309.Sh DIAGNOSTICS
310If
311.Fn malloc ,
312.Fn calloc ,
313.Fn realloc ,
314or
315.Fn free
316detect an error or warning condition,
317a message will be printed to file descriptor
3182 (not using stdio).
319Errors will always result in the process being
320.Xr abort 3 'ed.
321If the
322.Cm A
323option has been specified, warnings will also
324.Xr abort 3
325the process.
326.Pp
327Here is a brief description of the error messages and what they mean:
328.Bl -tag -width Fl
329.It Dq (ES): mumble mumble mumble
330.Fn malloc
331has been compiled with
332.Dv \&-DEXTRA_SANITY
333and something looks fishy in there.
334Consult sources and/or wizards.
335.It Dq allocation failed
336If the
337.Cm A
338option is specified it is an error for
339.Fn malloc ,
340.Fn calloc ,
341or
342.Fn realloc
343to return
344.Dv NULL .
345.It Dq mmap(2) failed, check limits.
346This is a rather weird condition that is most likely to indicate a
347seriously overloaded system or a
348.Xr ulimit 1
349restriction.
350.It Dq freelist is destroyed.
351.Fn malloc Ns 's
352internal freelist has been stomped on.
353.El
354.Pp
355Here is a brief description of the warning messages and what they mean:
356.Bl -tag -width Fl
357.It Dq chunk/page is already free.
358There was an attempt to free a chunk that had already been freed.
359.It Dq junk pointer, too high to make sense.
360The pointer doesn't make sense.
361It's above the area of memory that
362.Fn malloc
363knows something about.
364This could be a pointer from some
365.Xr mmap 2 'ed
366memory.
367.It Dq junk pointer, too low to make sense.
368The pointer doesn't make sense.
369It's below the area of memory that
370.Fn malloc
371knows something about.
372This pointer probably came from your data or bss segments.
373.It Dq malloc() has never been called.
374Nothing has ever been allocated, yet something is being freed or
375realloc'ed.
376.It Dq modified (chunk-/page-) pointer.
377The pointer passed to free or realloc has been modified.
378.It Dq pointer to wrong page.
379The pointer that
380.Fn malloc
381is trying to free is not pointing to
382a sensible page.
383.It Dq recursive call.
384An attempt was made to call recursively into these functions, i.e., from a
385signal handler.
386This behavior is not supported.
387In particular, signal handlers should
388.Em not
389use any of the
390.Fn malloc
391functions nor utilize any other functions which may call
392.Fn malloc
393(e.g.,
394.Xr stdio 3
395routines).
396.It Dq unknown char in MALLOC_OPTIONS
397We found something we didn't understand.
398.El
399.Sh SEE ALSO
400.Xr brk 2 ,
401.Xr alloca 3 ,
402.Xr getpagesize 3 ,
403.Xr memory 3
404.Sh STANDARDS
405The
406.Fn malloc
407function conforms to
408.St -ansiC .
409.Sh HISTORY
410The present implementation of
411.Fn malloc
412started out as a filesystem on a drum
413attached to a 20-bit binary challenged computer built with discrete germanium
414transistors, and it has since graduated to handle primary storage rather than
415secondary.
416.Pp
417The main difference from other
418.Fn malloc
419implementations are believed to be that
420the free pages are not accessed until allocated.
421Most
422.Fn malloc
423implementations will store a data structure containing a,
424possibly double-, linked list in the free chunks of memory, used to tie
425all the free memory together.
426That is a quite suboptimal thing to do.
427Every time the free-list is traversed, all the otherwise unused, and very
428likely paged out, pages get faulted into primary memory, just to see what
429lies after them in the list.
430.Pp
431On systems which are paging, this can increase the page-faults
432of a process by a factor of five.
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c
new file mode 100644
index 0000000000..f5704754a0
--- /dev/null
+++ b/src/lib/libc/stdlib/malloc.c
@@ -0,0 +1,1327 @@
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.66 2004/02/19 23:20:53 tdeval Exp $";
12#endif /* LIBC_SCCS and not lint */
13
14/*
15 * Defining MALLOC_EXTRA_SANITY will enable extra checks which are
16 * related to internal conditions and consistency in malloc.c. This has
17 * a noticeable runtime performance hit, and generally will not do you
18 * any good unless you fiddle with the internals of malloc or want
19 * to catch random pointer corruption as early as possible.
20 */
21#ifndef MALLOC_EXTRA_SANITY
22#undef MALLOC_EXTRA_SANITY
23#endif
24
25/*
26 * Defining MALLOC_STATS will enable you to call malloc_dump() and set
27 * the [dD] options in the MALLOC_OPTIONS environment variable.
28 * It has no run-time performance hit, but does pull in stdio...
29 */
30#ifndef MALLOC_STATS
31#undef MALLOC_STATS
32#endif
33
34/*
35 * What to use for Junk. This is the byte value we use to fill with
36 * when the 'J' option is enabled.
37 */
38#define SOME_JUNK 0xd0 /* as in "Duh" :-) */
39
40#include <sys/types.h>
41#include <sys/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, u_long index, struct pginfo *info)
996{
997 u_long i, l;
998 struct pgfree *pf, *pt=NULL;
999 void *tail;
1000
1001 if (info == MALLOC_FREE) {
1002 wrtwarning("page is already free\n");
1003 return;
1004 }
1005
1006 if (info != MALLOC_FIRST) {
1007 wrtwarning("pointer to wrong page\n");
1008 return;
1009 }
1010
1011 if ((u_long)ptr & malloc_pagemask) {
1012 wrtwarning("modified (page-) pointer\n");
1013 return;
1014 }
1015
1016 /* Count how many pages and mark them free at the same time */
1017 page_dir[index] = MALLOC_FREE;
1018 for (i = 1; page_dir[index+i] == MALLOC_FOLLOW; i++)
1019 page_dir[index + i] = MALLOC_FREE;
1020
1021 l = i << malloc_pageshift;
1022
1023 if (malloc_junk)
1024 memset(ptr, SOME_JUNK, l);
1025
1026#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
1027 if (malloc_hint)
1028 madvise(ptr, l, MADV_FREE);
1029#endif
1030
1031 if (malloc_guard) {
1032 page_dir[index + i] = MALLOC_FREE;
1033 l += malloc_guard;
1034 }
1035 tail = (char *)ptr+l;
1036
1037 if (malloc_freeprot)
1038 mprotect(ptr, tail - ptr, PROT_NONE);
1039
1040 /* add to free-list */
1041 if (px == NULL)
1042 px = imalloc(sizeof *px); /* This cannot fail... */
1043 px->page = ptr;
1044 px->end = tail;
1045 px->size = l;
1046
1047 if (free_list.next == NULL) {
1048
1049 /* Nothing on free list, put this at head */
1050 px->next = free_list.next;
1051 px->prev = &free_list;
1052 free_list.next = px;
1053 pf = px;
1054 px = NULL;
1055
1056 } else {
1057
1058 /* Find the right spot, leave pf pointing to the modified entry. */
1059
1060 for(pf = free_list.next; pf->end < ptr && pf->next != NULL;
1061 pf = pf->next)
1062 ; /* Race ahead here */
1063
1064 if (pf->page > tail) {
1065 /* Insert before entry */
1066 px->next = pf;
1067 px->prev = pf->prev;
1068 pf->prev = px;
1069 px->prev->next = px;
1070 pf = px;
1071 px = NULL;
1072 } else if (pf->end == ptr ) {
1073 /* Append to the previous entry */
1074 pf->end = (char *)pf->end + l;
1075 pf->size += l;
1076 if (pf->next != NULL && pf->end == pf->next->page ) {
1077 /* And collapse the next too. */
1078 pt = pf->next;
1079 pf->end = pt->end;
1080 pf->size += pt->size;
1081 pf->next = pt->next;
1082 if (pf->next != NULL)
1083 pf->next->prev = pf;
1084 }
1085 } else if (pf->page == tail) {
1086 /* Prepend to entry */
1087 pf->size += l;
1088 pf->page = ptr;
1089 } else if (pf->next == NULL) {
1090 /* Append at tail of chain */
1091 px->next = NULL;
1092 px->prev = pf;
1093 pf->next = px;
1094 pf = px;
1095 px = NULL;
1096 } else {
1097 wrterror("freelist is destroyed\n");
1098 }
1099 }
1100
1101 /* Return something to OS ? */
1102 if (pf->next == NULL && /* If we're the last one, */
1103 pf->size > malloc_cache && /* ..and the cache is full, */
1104 pf->end == malloc_brk && /* ..and none behind us, */
1105 malloc_brk == sbrk(0)) { /* ..and it's OK to do... */
1106
1107 /*
1108 * Keep the cache intact. Notice that the '>' above guarantees that
1109 * the pf will always have at least one page afterwards.
1110 */
1111 pf->end = (char *)pf->page + malloc_cache;
1112 pf->size = malloc_cache;
1113
1114 brk(pf->end);
1115 malloc_brk = pf->end;
1116
1117 index = ptr2index(pf->end);
1118
1119 for(i=index;i <= last_index;)
1120 page_dir[i++] = MALLOC_NOT_MINE;
1121
1122 last_index = index - 1;
1123
1124 /* XXX: We could realloc/shrink the pagedir here I guess. */
1125 }
1126 if (pt != NULL)
1127 ifree(pt);
1128}
1129
1130/*
1131 * Free a chunk, and possibly the page it's on, if the page becomes empty.
1132 */
1133
1134/* ARGSUSED */
1135static __inline__ void
1136free_bytes(void *ptr, int index, struct pginfo *info)
1137{
1138 int i;
1139 struct pginfo **mp;
1140 void *vp;
1141
1142 /* Find the chunk number on the page */
1143 i = ((u_long)ptr & malloc_pagemask) >> info->shift;
1144
1145 if ((u_long)ptr & ((1UL<<(info->shift))-1)) {
1146 wrtwarning("modified (chunk-) pointer\n");
1147 return;
1148 }
1149
1150 if (info->bits[i/MALLOC_BITS] & (1UL<<(i%MALLOC_BITS))) {
1151 wrtwarning("chunk is already free\n");
1152 return;
1153 }
1154
1155 if (malloc_junk && info->size != 0)
1156 memset(ptr, SOME_JUNK, info->size);
1157
1158 info->bits[i/MALLOC_BITS] |= 1UL<<(i%MALLOC_BITS);
1159 info->free++;
1160
1161 if (info->size != 0)
1162 mp = page_dir + info->shift;
1163 else
1164 mp = page_dir;
1165
1166 if (info->free == 1) {
1167
1168 /* Page became non-full */
1169
1170 /* Insert in address order */
1171 while (*mp && (*mp)->next && (*mp)->next->page < info->page)
1172 mp = &(*mp)->next;
1173 info->next = *mp;
1174 *mp = info;
1175 return;
1176 }
1177
1178 if (info->free != info->total)
1179 return;
1180
1181 /* Find & remove this page in the queue */
1182 while (*mp != info) {
1183 mp = &((*mp)->next);
1184#ifdef MALLOC_EXTRA_SANITY
1185 if (!*mp)
1186 wrterror("(ES): Not on queue\n");
1187#endif /* MALLOC_EXTRA_SANITY */
1188 }
1189 *mp = info->next;
1190
1191 /* Free the page & the info structure if need be */
1192 page_dir[ptr2index(info->page)] = MALLOC_FIRST;
1193
1194 /* If the page was mprotected, unprotect it before releasing it */
1195 if (info->size == 0) {
1196 mprotect(info->page, malloc_pagesize, PROT_READ|PROT_WRITE);
1197 /* Do we have to care if mprotect succeeds here ? */
1198 }
1199
1200 vp = info->page; /* Order is important ! */
1201 if(vp != (void*)info)
1202 ifree(info);
1203 ifree(vp);
1204}
1205
1206static void
1207ifree(void *ptr)
1208{
1209 struct pginfo *info;
1210 u_long index;
1211
1212 /* This is legal */
1213 if (ptr == NULL)
1214 return;
1215
1216 if (!malloc_started) {
1217 wrtwarning("malloc() has never been called\n");
1218 return;
1219 }
1220
1221 /* If we're already sinking, don't make matters any worse. */
1222 if (suicide)
1223 return;
1224
1225 index = ptr2index(ptr);
1226
1227 if (index < malloc_pageshift) {
1228 wrtwarning("junk pointer, too low to make sense\n");
1229 return;
1230 }
1231
1232 if (index > last_index) {
1233 wrtwarning("junk pointer, too high to make sense\n");
1234 return;
1235 }
1236
1237 info = page_dir[index];
1238
1239 if (info < MALLOC_MAGIC)
1240 free_pages(ptr, index, info);
1241 else
1242 free_bytes(ptr, index, info);
1243 return;
1244}
1245
1246static int malloc_active;
1247
1248/*
1249 * Common function for handling recursion. Only
1250 * print the error message once, to avoid making the problem
1251 * potentially worse.
1252 */
1253static void
1254malloc_recurse(void)
1255{
1256 static int noprint;
1257
1258 if (noprint == 0)
1259 wrtwarning("recursive call\n");
1260 noprint = 1;
1261 malloc_active--;
1262 _MALLOC_UNLOCK();
1263 errno = EDEADLK;
1264}
1265
1266/*
1267 * These are the public exported interface routines.
1268 */
1269void *
1270malloc(size_t size)
1271{
1272 void *r;
1273
1274 _MALLOC_LOCK();
1275 malloc_func = " in malloc():";
1276 if (malloc_active++) {
1277 malloc_recurse();
1278 return (NULL);
1279 }
1280 r = imalloc(size);
1281 UTRACE(0, size, r);
1282 malloc_active--;
1283 _MALLOC_UNLOCK();
1284 if (malloc_xmalloc && r == NULL)
1285 wrterror("out of memory\n");
1286 return (r);
1287}
1288
1289void
1290free(void *ptr)
1291{
1292 _MALLOC_LOCK();
1293 malloc_func = " in free():";
1294 if (malloc_active++) {
1295 malloc_recurse();
1296 return;
1297 }
1298 ifree(ptr);
1299 UTRACE(ptr, 0, 0);
1300 malloc_active--;
1301 _MALLOC_UNLOCK();
1302 return;
1303}
1304
1305void *
1306realloc(void *ptr, size_t size)
1307{
1308 void *r;
1309
1310 _MALLOC_LOCK();
1311 malloc_func = " in realloc():";
1312 if (malloc_active++) {
1313 malloc_recurse();
1314 return (NULL);
1315 }
1316 if (ptr == NULL) {
1317 r = imalloc(size);
1318 } else {
1319 r = irealloc(ptr, size);
1320 }
1321 UTRACE(ptr, size, r);
1322 malloc_active--;
1323 _MALLOC_UNLOCK();
1324 if (malloc_xmalloc && r == NULL)
1325 wrterror("out of memory\n");
1326 return (r);
1327}
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..5f17ec17d4
--- /dev/null
+++ b/src/lib/libc/stdlib/qdiv.3
@@ -0,0 +1,60 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" Chris Torek and the American National Standards Committee X3,
6.\" on Information Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: qdiv.3,v 1.6 2004/01/23 23:08:46 jmc Exp $
33.\"
34.Dd June 29, 1991
35.Dt QDIV 3
36.Os
37.Sh NAME
38.Nm qdiv
39.Nd return quotient and remainder from division
40.Sh SYNOPSIS
41.Fd #include <stdlib.h>
42.Ft qdiv_t
43.Fn qdiv "quad_t num" "quad_t denom"
44.Sh DESCRIPTION
45The
46.Fn qdiv
47function computes the value
48.Fa num Ns / Ns Fa denom
49and returns the quotient and remainder in a structure named
50.Li qdiv_t
51that contains two
52.Li quad integer
53members named
54.Fa quot
55and
56.Fa rem .
57.Sh SEE ALSO
58.Xr div 3 ,
59.Xr ldiv 3 ,
60.Xr math 3
diff --git a/src/lib/libc/stdlib/qdiv.c b/src/lib/libc/stdlib/qdiv.c
new file mode 100644
index 0000000000..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..8e839d6155
--- /dev/null
+++ b/src/lib/libc/stdlib/strtod.c
@@ -0,0 +1,2529 @@
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.19 2004/02/03 16:52:11 drahn 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 defined(__x86_64__) || (defined(__arm__) && defined(__VFP_FP__))
100#include <sys/types.h>
101#if BYTE_ORDER == BIG_ENDIAN
102#define IEEE_BIG_ENDIAN
103#else
104#define IEEE_LITTLE_ENDIAN
105#endif
106#endif
107
108#if defined(__arm__) && !defined(__VFP_FP__)
109/*
110 * Although the CPU is little endian the FP has different
111 * byte and word endianness. The byte order is still little endian
112 * but the word order is big endian.
113 */
114#define IEEE_BIG_ENDIAN
115#endif
116
117#ifdef __vax__
118#define VAX
119#endif
120
121#define Long int32_t
122#define ULong u_int32_t
123
124#ifdef DEBUG
125#include "stdio.h"
126#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);}
127#endif
128
129#ifdef __cplusplus
130#include "malloc.h"
131#include "memory.h"
132#else
133#ifndef KR_headers
134#include "stdlib.h"
135#include "string.h"
136#include "locale.h"
137#else
138#include "malloc.h"
139#include "memory.h"
140#endif
141#endif
142
143#ifdef MALLOC
144#ifdef KR_headers
145extern char *MALLOC();
146#else
147extern void *MALLOC(size_t);
148#endif
149#else
150#define MALLOC malloc
151#endif
152
153#include "ctype.h"
154#include "errno.h"
155
156#ifdef Bad_float_h
157#ifdef IEEE_BIG_ENDIAN
158#define IEEE_ARITHMETIC
159#endif
160#ifdef IEEE_LITTLE_ENDIAN
161#define IEEE_ARITHMETIC
162#endif
163
164#ifdef IEEE_ARITHMETIC
165#define DBL_DIG 15
166#define DBL_MAX_10_EXP 308
167#define DBL_MAX_EXP 1024
168#define FLT_RADIX 2
169#define FLT_ROUNDS 1
170#define DBL_MAX 1.7976931348623157e+308
171#endif
172
173#ifdef IBM
174#define DBL_DIG 16
175#define DBL_MAX_10_EXP 75
176#define DBL_MAX_EXP 63
177#define FLT_RADIX 16
178#define FLT_ROUNDS 0
179#define DBL_MAX 7.2370055773322621e+75
180#endif
181
182#ifdef VAX
183#define DBL_DIG 16
184#define DBL_MAX_10_EXP 38
185#define DBL_MAX_EXP 127
186#define FLT_RADIX 2
187#define FLT_ROUNDS 1
188#define DBL_MAX 1.7014118346046923e+38
189#endif
190
191#ifndef LONG_MAX
192#define LONG_MAX 2147483647
193#endif
194#else
195#include "float.h"
196#endif
197#ifndef __MATH_H__
198#include "math.h"
199#endif
200
201#ifdef __cplusplus
202extern "C" {
203#endif
204
205#ifndef CONST
206#ifdef KR_headers
207#define CONST /* blank */
208#else
209#define CONST const
210#endif
211#endif
212
213#ifdef Unsigned_Shifts
214#define Sign_Extend(a,b) if (b < 0) a |= 0xffff0000;
215#else
216#define Sign_Extend(a,b) /*no-op*/
217#endif
218
219#if defined(IEEE_LITTLE_ENDIAN) + defined(IEEE_BIG_ENDIAN) + defined(VAX) + \
220 defined(IBM) != 1
221Exactly one of IEEE_LITTLE_ENDIAN IEEE_BIG_ENDIAN, VAX, or
222IBM should be defined.
223#endif
224
225typedef union {
226 double d;
227 ULong ul[2];
228} _double;
229#define value(x) ((x).d)
230#ifdef IEEE_LITTLE_ENDIAN
231#define word0(x) ((x).ul[1])
232#define word1(x) ((x).ul[0])
233#else
234#define word0(x) ((x).ul[0])
235#define word1(x) ((x).ul[1])
236#endif
237
238/* The following definition of Storeinc is appropriate for MIPS processors.
239 * An alternative that might be better on some machines is
240 * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff)
241 */
242#if defined(IEEE_LITTLE_ENDIAN) + defined(VAX) + defined(__arm__)
243#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \
244((unsigned short *)a)[0] = (unsigned short)c, a++)
245#else
246#define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \
247((unsigned short *)a)[1] = (unsigned short)c, a++)
248#endif
249
250/* #define P DBL_MANT_DIG */
251/* Ten_pmax = floor(P*log(2)/log(5)) */
252/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */
253/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */
254/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */
255
256#if defined(IEEE_LITTLE_ENDIAN) + defined(IEEE_BIG_ENDIAN)
257#define Exp_shift 20
258#define Exp_shift1 20
259#define Exp_msk1 0x100000
260#define Exp_msk11 0x100000
261#define Exp_mask 0x7ff00000
262#define P 53
263#define Bias 1023
264#define IEEE_Arith
265#define Emin (-1022)
266#define Exp_1 0x3ff00000
267#define Exp_11 0x3ff00000
268#define Ebits 11
269#define Frac_mask 0xfffff
270#define Frac_mask1 0xfffff
271#define Ten_pmax 22
272#define Bletch 0x10
273#define Bndry_mask 0xfffff
274#define Bndry_mask1 0xfffff
275#define LSB 1
276#define Sign_bit 0x80000000
277#define Log2P 1
278#define Tiny0 0
279#define Tiny1 1
280#define Quick_max 14
281#define Int_max 14
282#define Infinite(x) (word0(x) == 0x7ff00000) /* sufficient test for here */
283#else
284#undef Sudden_Underflow
285#define Sudden_Underflow
286#ifdef IBM
287#define Exp_shift 24
288#define Exp_shift1 24
289#define Exp_msk1 0x1000000
290#define Exp_msk11 0x1000000
291#define Exp_mask 0x7f000000
292#define P 14
293#define Bias 65
294#define Exp_1 0x41000000
295#define Exp_11 0x41000000
296#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */
297#define Frac_mask 0xffffff
298#define Frac_mask1 0xffffff
299#define Bletch 4
300#define Ten_pmax 22
301#define Bndry_mask 0xefffff
302#define Bndry_mask1 0xffffff
303#define LSB 1
304#define Sign_bit 0x80000000
305#define Log2P 4
306#define Tiny0 0x100000
307#define Tiny1 0
308#define Quick_max 14
309#define Int_max 15
310#else /* VAX */
311#define Exp_shift 23
312#define Exp_shift1 7
313#define Exp_msk1 0x80
314#define Exp_msk11 0x800000
315#define Exp_mask 0x7f80
316#define P 56
317#define Bias 129
318#define Exp_1 0x40800000
319#define Exp_11 0x4080
320#define Ebits 8
321#define Frac_mask 0x7fffff
322#define Frac_mask1 0xffff007f
323#define Ten_pmax 24
324#define Bletch 2
325#define Bndry_mask 0xffff007f
326#define Bndry_mask1 0xffff007f
327#define LSB 0x10000
328#define Sign_bit 0x8000
329#define Log2P 1
330#define Tiny0 0x80
331#define Tiny1 0
332#define Quick_max 15
333#define Int_max 15
334#endif
335#endif
336
337#ifndef IEEE_Arith
338#define ROUND_BIASED
339#endif
340
341#ifdef RND_PRODQUOT
342#define rounded_product(a,b) a = rnd_prod(a, b)
343#define rounded_quotient(a,b) a = rnd_quot(a, b)
344#ifdef KR_headers
345extern double rnd_prod(), rnd_quot();
346#else
347extern double rnd_prod(double, double), rnd_quot(double, double);
348#endif
349#else
350#define rounded_product(a,b) a *= b
351#define rounded_quotient(a,b) a /= b
352#endif
353
354#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1))
355#define Big1 0xffffffff
356
357#ifndef Just_16
358/* When Pack_32 is not defined, we store 16 bits per 32-bit Long.
359 * This makes some inner loops simpler and sometimes saves work
360 * during multiplications, but it often seems to make things slightly
361 * slower. Hence the default is now to store 32 bits per Long.
362 */
363#ifndef Pack_32
364#define Pack_32
365#endif
366#endif
367
368#define Kmax 15
369
370#ifdef __cplusplus
371extern "C" double strtod(const char *s00, char **se);
372extern "C" char *__dtoa(double d, int mode, int ndigits,
373 int *decpt, int *sign, char **rve);
374#endif
375
376 struct
377Bigint {
378 struct Bigint *next;
379 int k, maxwds, sign, wds;
380 ULong x[1];
381 };
382
383 typedef struct Bigint Bigint;
384
385 static Bigint *freelist[Kmax+1];
386
387 static Bigint *
388Balloc
389#ifdef KR_headers
390 (k) int k;
391#else
392 (int k)
393#endif
394{
395 int x;
396 Bigint *rv;
397
398 if ((rv = freelist[k])) {
399 freelist[k] = rv->next;
400 }
401 else {
402 x = 1 << k;
403 rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(Long));
404 rv->k = k;
405 rv->maxwds = x;
406 }
407 rv->sign = rv->wds = 0;
408 return rv;
409 }
410
411 static void
412Bfree
413#ifdef KR_headers
414 (v) Bigint *v;
415#else
416 (Bigint *v)
417#endif
418{
419 if (v) {
420 v->next = freelist[v->k];
421 freelist[v->k] = v;
422 }
423 }
424
425#define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \
426y->wds*sizeof(Long) + 2*sizeof(int))
427
428 static Bigint *
429multadd
430#ifdef KR_headers
431 (b, m, a) Bigint *b; int m, a;
432#else
433 (Bigint *b, int m, int a) /* multiply by m and add a */
434#endif
435{
436 int i, wds;
437 ULong *x, y;
438#ifdef Pack_32
439 ULong xi, z;
440#endif
441 Bigint *b1;
442
443 wds = b->wds;
444 x = b->x;
445 i = 0;
446 do {
447#ifdef Pack_32
448 xi = *x;
449 y = (xi & 0xffff) * m + a;
450 z = (xi >> 16) * m + (y >> 16);
451 a = (int)(z >> 16);
452 *x++ = (z << 16) + (y & 0xffff);
453#else
454 y = *x * m + a;
455 a = (int)(y >> 16);
456 *x++ = y & 0xffff;
457#endif
458 }
459 while(++i < wds);
460 if (a) {
461 if (wds >= b->maxwds) {
462 b1 = Balloc(b->k+1);
463 Bcopy(b1, b);
464 Bfree(b);
465 b = b1;
466 }
467 b->x[wds++] = a;
468 b->wds = wds;
469 }
470 return b;
471 }
472
473 static Bigint *
474s2b
475#ifdef KR_headers
476 (s, nd0, nd, y9) CONST char *s; int nd0, nd; ULong y9;
477#else
478 (CONST char *s, int nd0, int nd, ULong y9)
479#endif
480{
481 Bigint *b;
482 int i, k;
483 Long x, y;
484
485 x = (nd + 8) / 9;
486 for(k = 0, y = 1; x > y; y <<= 1, k++) ;
487#ifdef Pack_32
488 b = Balloc(k);
489 b->x[0] = y9;
490 b->wds = 1;
491#else
492 b = Balloc(k+1);
493 b->x[0] = y9 & 0xffff;
494 b->wds = (b->x[1] = y9 >> 16) ? 2 : 1;
495#endif
496
497 i = 9;
498 if (9 < nd0) {
499 s += 9;
500 do b = multadd(b, 10, *s++ - '0');
501 while(++i < nd0);
502 s++;
503 }
504 else
505 s += 10;
506 for(; i < nd; i++)
507 b = multadd(b, 10, *s++ - '0');
508 return b;
509 }
510
511 static int
512hi0bits
513#ifdef KR_headers
514 (x) register ULong x;
515#else
516 (register ULong x)
517#endif
518{
519 register int k = 0;
520
521 if (!(x & 0xffff0000)) {
522 k = 16;
523 x <<= 16;
524 }
525 if (!(x & 0xff000000)) {
526 k += 8;
527 x <<= 8;
528 }
529 if (!(x & 0xf0000000)) {
530 k += 4;
531 x <<= 4;
532 }
533 if (!(x & 0xc0000000)) {
534 k += 2;
535 x <<= 2;
536 }
537 if (!(x & 0x80000000)) {
538 k++;
539 if (!(x & 0x40000000))
540 return 32;
541 }
542 return k;
543 }
544
545 static int
546lo0bits
547#ifdef KR_headers
548 (y) ULong *y;
549#else
550 (ULong *y)
551#endif
552{
553 register int k;
554 register ULong x = *y;
555
556 if (x & 7) {
557 if (x & 1)
558 return 0;
559 if (x & 2) {
560 *y = x >> 1;
561 return 1;
562 }
563 *y = x >> 2;
564 return 2;
565 }
566 k = 0;
567 if (!(x & 0xffff)) {
568 k = 16;
569 x >>= 16;
570 }
571 if (!(x & 0xff)) {
572 k += 8;
573 x >>= 8;
574 }
575 if (!(x & 0xf)) {
576 k += 4;
577 x >>= 4;
578 }
579 if (!(x & 0x3)) {
580 k += 2;
581 x >>= 2;
582 }
583 if (!(x & 1)) {
584 k++;
585 x >>= 1;
586 if (!x & 1)
587 return 32;
588 }
589 *y = x;
590 return k;
591 }
592
593 static Bigint *
594i2b
595#ifdef KR_headers
596 (i) int i;
597#else
598 (int i)
599#endif
600{
601 Bigint *b;
602
603 b = Balloc(1);
604 b->x[0] = i;
605 b->wds = 1;
606 return b;
607 }
608
609 static Bigint *
610mult
611#ifdef KR_headers
612 (a, b) Bigint *a, *b;
613#else
614 (Bigint *a, Bigint *b)
615#endif
616{
617 Bigint *c;
618 int k, wa, wb, wc;
619 ULong carry, y, z;
620 ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
621#ifdef Pack_32
622 ULong z2;
623#endif
624
625 if (a->wds < b->wds) {
626 c = a;
627 a = b;
628 b = c;
629 }
630 k = a->k;
631 wa = a->wds;
632 wb = b->wds;
633 wc = wa + wb;
634 if (wc > a->maxwds)
635 k++;
636 c = Balloc(k);
637 for(x = c->x, xa = x + wc; x < xa; x++)
638 *x = 0;
639 xa = a->x;
640 xae = xa + wa;
641 xb = b->x;
642 xbe = xb + wb;
643 xc0 = c->x;
644#ifdef Pack_32
645 for(; xb < xbe; xb++, xc0++) {
646 if ((y = *xb & 0xffff)) {
647 x = xa;
648 xc = xc0;
649 carry = 0;
650 do {
651 z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
652 carry = z >> 16;
653 z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
654 carry = z2 >> 16;
655 Storeinc(xc, z2, z);
656 }
657 while(x < xae);
658 *xc = carry;
659 }
660 if ((y = *xb >> 16)) {
661 x = xa;
662 xc = xc0;
663 carry = 0;
664 z2 = *xc;
665 do {
666 z = (*x & 0xffff) * y + (*xc >> 16) + carry;
667 carry = z >> 16;
668 Storeinc(xc, z, z2);
669 z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
670 carry = z2 >> 16;
671 }
672 while(x < xae);
673 *xc = z2;
674 }
675 }
676#else
677 for(; xb < xbe; xc0++) {
678 if (y = *xb++) {
679 x = xa;
680 xc = xc0;
681 carry = 0;
682 do {
683 z = *x++ * y + *xc + carry;
684 carry = z >> 16;
685 *xc++ = z & 0xffff;
686 }
687 while(x < xae);
688 *xc = carry;
689 }
690 }
691#endif
692 for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
693 c->wds = wc;
694 return c;
695 }
696
697 static Bigint *p5s;
698
699 static Bigint *
700pow5mult
701#ifdef KR_headers
702 (b, k) Bigint *b; int k;
703#else
704 (Bigint *b, int k)
705#endif
706{
707 Bigint *b1, *p5, *p51;
708 int i;
709 static int p05[3] = { 5, 25, 125 };
710
711 if ((i = k & 3))
712 b = multadd(b, p05[i-1], 0);
713
714 if (!(k >>= 2))
715 return b;
716 if (!(p5 = p5s)) {
717 /* first time */
718 p5 = p5s = i2b(625);
719 p5->next = 0;
720 }
721 for(;;) {
722 if (k & 1) {
723 b1 = mult(b, p5);
724 Bfree(b);
725 b = b1;
726 }
727 if (!(k >>= 1))
728 break;
729 if (!(p51 = p5->next)) {
730 p51 = p5->next = mult(p5,p5);
731 p51->next = 0;
732 }
733 p5 = p51;
734 }
735 return b;
736 }
737
738 static Bigint *
739lshift
740#ifdef KR_headers
741 (b, k) Bigint *b; int k;
742#else
743 (Bigint *b, int k)
744#endif
745{
746 int i, k1, n, n1;
747 Bigint *b1;
748 ULong *x, *x1, *xe, z;
749
750#ifdef Pack_32
751 n = k >> 5;
752#else
753 n = k >> 4;
754#endif
755 k1 = b->k;
756 n1 = n + b->wds + 1;
757 for(i = b->maxwds; n1 > i; i <<= 1)
758 k1++;
759 b1 = Balloc(k1);
760 x1 = b1->x;
761 for(i = 0; i < n; i++)
762 *x1++ = 0;
763 x = b->x;
764 xe = x + b->wds;
765#ifdef Pack_32
766 if (k &= 0x1f) {
767 k1 = 32 - k;
768 z = 0;
769 do {
770 *x1++ = *x << k | z;
771 z = *x++ >> k1;
772 }
773 while(x < xe);
774 if ((*x1 = z))
775 ++n1;
776 }
777#else
778 if (k &= 0xf) {
779 k1 = 16 - k;
780 z = 0;
781 do {
782 *x1++ = *x << k & 0xffff | z;
783 z = *x++ >> k1;
784 }
785 while(x < xe);
786 if (*x1 = z)
787 ++n1;
788 }
789#endif
790 else do
791 *x1++ = *x++;
792 while(x < xe);
793 b1->wds = n1 - 1;
794 Bfree(b);
795 return b1;
796 }
797
798 static int
799cmp
800#ifdef KR_headers
801 (a, b) Bigint *a, *b;
802#else
803 (Bigint *a, Bigint *b)
804#endif
805{
806 ULong *xa, *xa0, *xb, *xb0;
807 int i, j;
808
809 i = a->wds;
810 j = b->wds;
811#ifdef DEBUG
812 if (i > 1 && !a->x[i-1])
813 Bug("cmp called with a->x[a->wds-1] == 0");
814 if (j > 1 && !b->x[j-1])
815 Bug("cmp called with b->x[b->wds-1] == 0");
816#endif
817 if (i -= j)
818 return i;
819 xa0 = a->x;
820 xa = xa0 + j;
821 xb0 = b->x;
822 xb = xb0 + j;
823 for(;;) {
824 if (*--xa != *--xb)
825 return *xa < *xb ? -1 : 1;
826 if (xa <= xa0)
827 break;
828 }
829 return 0;
830 }
831
832 static Bigint *
833diff
834#ifdef KR_headers
835 (a, b) Bigint *a, *b;
836#else
837 (Bigint *a, Bigint *b)
838#endif
839{
840 Bigint *c;
841 int i, wa, wb;
842 Long borrow, y; /* We need signed shifts here. */
843 ULong *xa, *xae, *xb, *xbe, *xc;
844#ifdef Pack_32
845 Long z;
846#endif
847
848 i = cmp(a,b);
849 if (!i) {
850 c = Balloc(0);
851 c->wds = 1;
852 c->x[0] = 0;
853 return c;
854 }
855 if (i < 0) {
856 c = a;
857 a = b;
858 b = c;
859 i = 1;
860 }
861 else
862 i = 0;
863 c = Balloc(a->k);
864 c->sign = i;
865 wa = a->wds;
866 xa = a->x;
867 xae = xa + wa;
868 wb = b->wds;
869 xb = b->x;
870 xbe = xb + wb;
871 xc = c->x;
872 borrow = 0;
873#ifdef Pack_32
874 do {
875 y = (*xa & 0xffff) - (*xb & 0xffff) + borrow;
876 borrow = y >> 16;
877 Sign_Extend(borrow, y);
878 z = (*xa++ >> 16) - (*xb++ >> 16) + borrow;
879 borrow = z >> 16;
880 Sign_Extend(borrow, z);
881 Storeinc(xc, z, y);
882 }
883 while(xb < xbe);
884 while(xa < xae) {
885 y = (*xa & 0xffff) + borrow;
886 borrow = y >> 16;
887 Sign_Extend(borrow, y);
888 z = (*xa++ >> 16) + borrow;
889 borrow = z >> 16;
890 Sign_Extend(borrow, z);
891 Storeinc(xc, z, y);
892 }
893#else
894 do {
895 y = *xa++ - *xb++ + borrow;
896 borrow = y >> 16;
897 Sign_Extend(borrow, y);
898 *xc++ = y & 0xffff;
899 }
900 while(xb < xbe);
901 while(xa < xae) {
902 y = *xa++ + borrow;
903 borrow = y >> 16;
904 Sign_Extend(borrow, y);
905 *xc++ = y & 0xffff;
906 }
907#endif
908 while(!*--xc)
909 wa--;
910 c->wds = wa;
911 return c;
912 }
913
914 static double
915ulp
916#ifdef KR_headers
917 (_x) double _x;
918#else
919 (double _x)
920#endif
921{
922 _double x;
923 register Long L;
924 _double a;
925
926 value(x) = _x;
927 L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1;
928#ifndef Sudden_Underflow
929 if (L > 0) {
930#endif
931#ifdef IBM
932 L |= Exp_msk1 >> 4;
933#endif
934 word0(a) = L;
935 word1(a) = 0;
936#ifndef Sudden_Underflow
937 }
938 else {
939 L = -L >> Exp_shift;
940 if (L < Exp_shift) {
941 word0(a) = 0x80000 >> L;
942 word1(a) = 0;
943 }
944 else {
945 word0(a) = 0;
946 L -= Exp_shift;
947 word1(a) = L >= 31 ? 1 : 1 << 31 - L;
948 }
949 }
950#endif
951 return value(a);
952 }
953
954 static double
955b2d
956#ifdef KR_headers
957 (a, e) Bigint *a; int *e;
958#else
959 (Bigint *a, int *e)
960#endif
961{
962 ULong *xa, *xa0, w, y, z;
963 int k;
964 _double d;
965#ifdef VAX
966 ULong d0, d1;
967#else
968#define d0 word0(d)
969#define d1 word1(d)
970#endif
971
972 xa0 = a->x;
973 xa = xa0 + a->wds;
974 y = *--xa;
975#ifdef DEBUG
976 if (!y) Bug("zero y in b2d");
977#endif
978 k = hi0bits(y);
979 *e = 32 - k;
980#ifdef Pack_32
981 if (k < Ebits) {
982 d0 = Exp_1 | y >> Ebits - k;
983 w = xa > xa0 ? *--xa : 0;
984 d1 = y << (32-Ebits) + k | w >> Ebits - k;
985 goto ret_d;
986 }
987 z = xa > xa0 ? *--xa : 0;
988 if (k -= Ebits) {
989 d0 = Exp_1 | y << k | z >> 32 - k;
990 y = xa > xa0 ? *--xa : 0;
991 d1 = z << k | y >> 32 - k;
992 }
993 else {
994 d0 = Exp_1 | y;
995 d1 = z;
996 }
997#else
998 if (k < Ebits + 16) {
999 z = xa > xa0 ? *--xa : 0;
1000 d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
1001 w = xa > xa0 ? *--xa : 0;
1002 y = xa > xa0 ? *--xa : 0;
1003 d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
1004 goto ret_d;
1005 }
1006 z = xa > xa0 ? *--xa : 0;
1007 w = xa > xa0 ? *--xa : 0;
1008 k -= Ebits + 16;
1009 d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
1010 y = xa > xa0 ? *--xa : 0;
1011 d1 = w << k + 16 | y << k;
1012#endif
1013 ret_d:
1014#ifdef VAX
1015 word0(d) = d0 >> 16 | d0 << 16;
1016 word1(d) = d1 >> 16 | d1 << 16;
1017#else
1018#undef d0
1019#undef d1
1020#endif
1021 return value(d);
1022 }
1023
1024 static Bigint *
1025d2b
1026#ifdef KR_headers
1027 (_d, e, bits) double d; int *e, *bits;
1028#else
1029 (double _d, int *e, int *bits)
1030#endif
1031{
1032 Bigint *b;
1033 int de, i, k;
1034 ULong *x, y, z;
1035 _double d;
1036#ifdef VAX
1037 ULong d0, d1;
1038#endif
1039
1040 value(d) = _d;
1041#ifdef VAX
1042 d0 = word0(d) >> 16 | word0(d) << 16;
1043 d1 = word1(d) >> 16 | word1(d) << 16;
1044#else
1045#define d0 word0(d)
1046#define d1 word1(d)
1047#endif
1048
1049#ifdef Pack_32
1050 b = Balloc(1);
1051#else
1052 b = Balloc(2);
1053#endif
1054 x = b->x;
1055
1056 z = d0 & Frac_mask;
1057 d0 &= 0x7fffffff; /* clear sign bit, which we ignore */
1058#ifdef Sudden_Underflow
1059 de = (int)(d0 >> Exp_shift);
1060#ifndef IBM
1061 z |= Exp_msk11;
1062#endif
1063#else
1064 if (de = (int)(d0 >> Exp_shift))
1065 z |= Exp_msk1;
1066#endif
1067#ifdef Pack_32
1068 if (y = d1) {
1069 if (k = lo0bits(&y)) {
1070 x[0] = y | z << 32 - k;
1071 z >>= k;
1072 }
1073 else
1074 x[0] = y;
1075 i = b->wds = (x[1] = z) ? 2 : 1;
1076 }
1077 else {
1078#ifdef DEBUG
1079 if (!z)
1080 Bug("Zero passed to d2b");
1081#endif
1082 k = lo0bits(&z);
1083 x[0] = z;
1084 i = b->wds = 1;
1085 k += 32;
1086 }
1087#else
1088 if (y = d1) {
1089 if (k = lo0bits(&y))
1090 if (k >= 16) {
1091 x[0] = y | z << 32 - k & 0xffff;
1092 x[1] = z >> k - 16 & 0xffff;
1093 x[2] = z >> k;
1094 i = 2;
1095 }
1096 else {
1097 x[0] = y & 0xffff;
1098 x[1] = y >> 16 | z << 16 - k & 0xffff;
1099 x[2] = z >> k & 0xffff;
1100 x[3] = z >> k+16;
1101 i = 3;
1102 }
1103 else {
1104 x[0] = y & 0xffff;
1105 x[1] = y >> 16;
1106 x[2] = z & 0xffff;
1107 x[3] = z >> 16;
1108 i = 3;
1109 }
1110 }
1111 else {
1112#ifdef DEBUG
1113 if (!z)
1114 Bug("Zero passed to d2b");
1115#endif
1116 k = lo0bits(&z);
1117 if (k >= 16) {
1118 x[0] = z;
1119 i = 0;
1120 }
1121 else {
1122 x[0] = z & 0xffff;
1123 x[1] = z >> 16;
1124 i = 1;
1125 }
1126 k += 32;
1127 }
1128 while(!x[i])
1129 --i;
1130 b->wds = i + 1;
1131#endif
1132#ifndef Sudden_Underflow
1133 if (de) {
1134#endif
1135#ifdef IBM
1136 *e = (de - Bias - (P-1) << 2) + k;
1137 *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask);
1138#else
1139 *e = de - Bias - (P-1) + k;
1140 *bits = P - k;
1141#endif
1142#ifndef Sudden_Underflow
1143 }
1144 else {
1145 *e = de - Bias - (P-1) + 1 + k;
1146#ifdef Pack_32
1147 *bits = 32*i - hi0bits(x[i-1]);
1148#else
1149 *bits = (i+2)*16 - hi0bits(x[i]);
1150#endif
1151 }
1152#endif
1153 return b;
1154 }
1155#undef d0
1156#undef d1
1157
1158 static double
1159ratio
1160#ifdef KR_headers
1161 (a, b) Bigint *a, *b;
1162#else
1163 (Bigint *a, Bigint *b)
1164#endif
1165{
1166 _double da, db;
1167 int k, ka, kb;
1168
1169 value(da) = b2d(a, &ka);
1170 value(db) = b2d(b, &kb);
1171#ifdef Pack_32
1172 k = ka - kb + 32*(a->wds - b->wds);
1173#else
1174 k = ka - kb + 16*(a->wds - b->wds);
1175#endif
1176#ifdef IBM
1177 if (k > 0) {
1178 word0(da) += (k >> 2)*Exp_msk1;
1179 if (k &= 3)
1180 da *= 1 << k;
1181 }
1182 else {
1183 k = -k;
1184 word0(db) += (k >> 2)*Exp_msk1;
1185 if (k &= 3)
1186 db *= 1 << k;
1187 }
1188#else
1189 if (k > 0)
1190 word0(da) += k*Exp_msk1;
1191 else {
1192 k = -k;
1193 word0(db) += k*Exp_msk1;
1194 }
1195#endif
1196 return value(da) / value(db);
1197 }
1198
1199static CONST double
1200tens[] = {
1201 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
1202 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
1203 1e20, 1e21, 1e22
1204#ifdef VAX
1205 , 1e23, 1e24
1206#endif
1207 };
1208
1209#ifdef IEEE_Arith
1210static CONST double bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
1211static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
1212#define n_bigtens 5
1213#else
1214#ifdef IBM
1215static CONST double bigtens[] = { 1e16, 1e32, 1e64 };
1216static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64 };
1217#define n_bigtens 3
1218#else
1219static CONST double bigtens[] = { 1e16, 1e32 };
1220static CONST double tinytens[] = { 1e-16, 1e-32 };
1221#define n_bigtens 2
1222#endif
1223#endif
1224
1225 double
1226strtod
1227#ifdef KR_headers
1228 (s00, se) CONST char *s00; char **se;
1229#else
1230 (CONST char *s00, char **se)
1231#endif
1232{
1233 int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
1234 e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
1235 CONST char *s, *s0, *s1;
1236 double aadj, aadj1, adj;
1237 _double rv, rv0;
1238 Long L;
1239 ULong y, z;
1240 Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
1241
1242#ifndef KR_headers
1243 CONST char decimal_point = localeconv()->decimal_point[0];
1244#else
1245 CONST char decimal_point = '.';
1246#endif
1247
1248 sign = nz0 = nz = 0;
1249 value(rv) = 0.;
1250
1251
1252 for(s = s00; isspace((unsigned char) *s); s++)
1253 ;
1254
1255 if (*s == '-') {
1256 sign = 1;
1257 s++;
1258 } else if (*s == '+') {
1259 s++;
1260 }
1261
1262 if (*s == '\0') {
1263 s = s00;
1264 goto ret;
1265 }
1266
1267 if (*s == '0') {
1268 nz0 = 1;
1269 while(*++s == '0') ;
1270 if (!*s)
1271 goto ret;
1272 }
1273 s0 = s;
1274 y = z = 0;
1275 for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
1276 if (nd < 9)
1277 y = 10*y + c - '0';
1278 else if (nd < 16)
1279 z = 10*z + c - '0';
1280 nd0 = nd;
1281 if (c == decimal_point) {
1282 c = *++s;
1283 if (!nd) {
1284 for(; c == '0'; c = *++s)
1285 nz++;
1286 if (c > '0' && c <= '9') {
1287 s0 = s;
1288 nf += nz;
1289 nz = 0;
1290 goto have_dig;
1291 }
1292 goto dig_done;
1293 }
1294 for(; c >= '0' && c <= '9'; c = *++s) {
1295 have_dig:
1296 nz++;
1297 if (c -= '0') {
1298 nf += nz;
1299 for(i = 1; i < nz; i++)
1300 if (nd++ < 9)
1301 y *= 10;
1302 else if (nd <= DBL_DIG + 1)
1303 z *= 10;
1304 if (nd++ < 9)
1305 y = 10*y + c;
1306 else if (nd <= DBL_DIG + 1)
1307 z = 10*z + c;
1308 nz = 0;
1309 }
1310 }
1311 }
1312 dig_done:
1313 e = 0;
1314 if (c == 'e' || c == 'E') {
1315 if (!nd && !nz && !nz0) {
1316 s = s00;
1317 goto ret;
1318 }
1319 s00 = s;
1320 esign = 0;
1321 switch(c = *++s) {
1322 case '-':
1323 esign = 1;
1324 case '+':
1325 c = *++s;
1326 }
1327 if (c >= '0' && c <= '9') {
1328 while(c == '0')
1329 c = *++s;
1330 if (c > '0' && c <= '9') {
1331 L = c - '0';
1332 s1 = s;
1333 while((c = *++s) >= '0' && c <= '9')
1334 L = 10*L + c - '0';
1335 if (s - s1 > 8 || L > 19999)
1336 /* Avoid confusion from exponents
1337 * so large that e might overflow.
1338 */
1339 e = 19999; /* safe for 16 bit ints */
1340 else
1341 e = (int)L;
1342 if (esign)
1343 e = -e;
1344 }
1345 else
1346 e = 0;
1347 }
1348 else
1349 s = s00;
1350 }
1351 if (!nd) {
1352 if (!nz && !nz0)
1353 s = s00;
1354 goto ret;
1355 }
1356 e1 = e -= nf;
1357
1358 /* Now we have nd0 digits, starting at s0, followed by a
1359 * decimal point, followed by nd-nd0 digits. The number we're
1360 * after is the integer represented by those digits times
1361 * 10**e */
1362
1363 if (!nd0)
1364 nd0 = nd;
1365 k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
1366 value(rv) = y;
1367 if (k > 9)
1368 value(rv) = tens[k - 9] * value(rv) + z;
1369 bd0 = 0;
1370 if (nd <= DBL_DIG
1371#ifndef RND_PRODQUOT
1372 && FLT_ROUNDS == 1
1373#endif
1374 ) {
1375 if (!e)
1376 goto ret;
1377 if (e > 0) {
1378 if (e <= Ten_pmax) {
1379#ifdef VAX
1380 goto vax_ovfl_check;
1381#else
1382 /* value(rv) = */ rounded_product(value(rv),
1383 tens[e]);
1384 goto ret;
1385#endif
1386 }
1387 i = DBL_DIG - nd;
1388 if (e <= Ten_pmax + i) {
1389 /* A fancier test would sometimes let us do
1390 * this for larger i values.
1391 */
1392 e -= i;
1393 value(rv) *= tens[i];
1394#ifdef VAX
1395 /* VAX exponent range is so narrow we must
1396 * worry about overflow here...
1397 */
1398 vax_ovfl_check:
1399 word0(rv) -= P*Exp_msk1;
1400 /* value(rv) = */ rounded_product(value(rv),
1401 tens[e]);
1402 if ((word0(rv) & Exp_mask)
1403 > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
1404 goto ovfl;
1405 word0(rv) += P*Exp_msk1;
1406#else
1407 /* value(rv) = */ rounded_product(value(rv),
1408 tens[e]);
1409#endif
1410 goto ret;
1411 }
1412 }
1413#ifndef Inaccurate_Divide
1414 else if (e >= -Ten_pmax) {
1415 /* value(rv) = */ rounded_quotient(value(rv),
1416 tens[-e]);
1417 goto ret;
1418 }
1419#endif
1420 }
1421 e1 += nd - k;
1422
1423 /* Get starting approximation = rv * 10**e1 */
1424
1425 if (e1 > 0) {
1426 if (i = e1 & 15)
1427 value(rv) *= tens[i];
1428 if (e1 &= ~15) {
1429 if (e1 > DBL_MAX_10_EXP) {
1430 ovfl:
1431 errno = ERANGE;
1432#ifndef Bad_float_h
1433 value(rv) = HUGE_VAL;
1434#else
1435 /* Can't trust HUGE_VAL */
1436#ifdef IEEE_Arith
1437 word0(rv) = Exp_mask;
1438 word1(rv) = 0;
1439#else
1440 word0(rv) = Big0;
1441 word1(rv) = Big1;
1442#endif
1443#endif
1444 if (bd0)
1445 goto retfree;
1446 goto ret;
1447 }
1448 if (e1 >>= 4) {
1449 for(j = 0; e1 > 1; j++, e1 >>= 1)
1450 if (e1 & 1)
1451 value(rv) *= bigtens[j];
1452 /* The last multiplication could overflow. */
1453 word0(rv) -= P*Exp_msk1;
1454 value(rv) *= bigtens[j];
1455 if ((z = word0(rv) & Exp_mask)
1456 > Exp_msk1*(DBL_MAX_EXP+Bias-P))
1457 goto ovfl;
1458 if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {
1459 /* set to largest number */
1460 /* (Can't trust DBL_MAX) */
1461 word0(rv) = Big0;
1462 word1(rv) = Big1;
1463 }
1464 else
1465 word0(rv) += P*Exp_msk1;
1466 }
1467
1468 }
1469 }
1470 else if (e1 < 0) {
1471 e1 = -e1;
1472 if (i = e1 & 15)
1473 value(rv) /= tens[i];
1474 if (e1 &= ~15) {
1475 e1 >>= 4;
1476 if (e1 >= 1 << n_bigtens)
1477 goto undfl;
1478 for(j = 0; e1 > 1; j++, e1 >>= 1)
1479 if (e1 & 1)
1480 value(rv) *= tinytens[j];
1481 /* The last multiplication could underflow. */
1482 value(rv0) = value(rv);
1483 value(rv) *= tinytens[j];
1484 if (!value(rv)) {
1485 value(rv) = 2.*value(rv0);
1486 value(rv) *= tinytens[j];
1487 if (!value(rv)) {
1488 undfl:
1489 value(rv) = 0.;
1490 errno = ERANGE;
1491 if (bd0)
1492 goto retfree;
1493 goto ret;
1494 }
1495 word0(rv) = Tiny0;
1496 word1(rv) = Tiny1;
1497 /* The refinement below will clean
1498 * this approximation up.
1499 */
1500 }
1501 }
1502 }
1503
1504 /* Now the hard part -- adjusting rv to the correct value.*/
1505
1506 /* Put digits into bd: true value = bd * 10^e */
1507
1508 bd0 = s2b(s0, nd0, nd, y);
1509
1510 for(;;) {
1511 bd = Balloc(bd0->k);
1512 Bcopy(bd, bd0);
1513 bb = d2b(value(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */
1514 bs = i2b(1);
1515
1516 if (e >= 0) {
1517 bb2 = bb5 = 0;
1518 bd2 = bd5 = e;
1519 }
1520 else {
1521 bb2 = bb5 = -e;
1522 bd2 = bd5 = 0;
1523 }
1524 if (bbe >= 0)
1525 bb2 += bbe;
1526 else
1527 bd2 -= bbe;
1528 bs2 = bb2;
1529#ifdef Sudden_Underflow
1530#ifdef IBM
1531 j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3);
1532#else
1533 j = P + 1 - bbbits;
1534#endif
1535#else
1536 i = bbe + bbbits - 1; /* logb(rv) */
1537 if (i < Emin) /* denormal */
1538 j = bbe + (P-Emin);
1539 else
1540 j = P + 1 - bbbits;
1541#endif
1542 bb2 += j;
1543 bd2 += j;
1544 i = bb2 < bd2 ? bb2 : bd2;
1545 if (i > bs2)
1546 i = bs2;
1547 if (i > 0) {
1548 bb2 -= i;
1549 bd2 -= i;
1550 bs2 -= i;
1551 }
1552 if (bb5 > 0) {
1553 bs = pow5mult(bs, bb5);
1554 bb1 = mult(bs, bb);
1555 Bfree(bb);
1556 bb = bb1;
1557 }
1558 if (bb2 > 0)
1559 bb = lshift(bb, bb2);
1560 if (bd5 > 0)
1561 bd = pow5mult(bd, bd5);
1562 if (bd2 > 0)
1563 bd = lshift(bd, bd2);
1564 if (bs2 > 0)
1565 bs = lshift(bs, bs2);
1566 delta = diff(bb, bd);
1567 dsign = delta->sign;
1568 delta->sign = 0;
1569 i = cmp(delta, bs);
1570 if (i < 0) {
1571 /* Error is less than half an ulp -- check for
1572 * special case of mantissa a power of two.
1573 */
1574 if (dsign || word1(rv) || word0(rv) & Bndry_mask)
1575 break;
1576 delta = lshift(delta,Log2P);
1577 if (cmp(delta, bs) > 0)
1578 goto drop_down;
1579 break;
1580 }
1581 if (i == 0) {
1582 /* exactly half-way between */
1583 if (dsign) {
1584 if ((word0(rv) & Bndry_mask1) == Bndry_mask1
1585 && word1(rv) == 0xffffffff) {
1586 /*boundary case -- increment exponent*/
1587 word0(rv) = (word0(rv) & Exp_mask)
1588 + Exp_msk1
1589#ifdef IBM
1590 | Exp_msk1 >> 4
1591#endif
1592 ;
1593 word1(rv) = 0;
1594 break;
1595 }
1596 }
1597 else if (!(word0(rv) & Bndry_mask) && !word1(rv)) {
1598 drop_down:
1599 /* boundary case -- decrement exponent */
1600#ifdef Sudden_Underflow
1601 L = word0(rv) & Exp_mask;
1602#ifdef IBM
1603 if (L < Exp_msk1)
1604#else
1605 if (L <= Exp_msk1)
1606#endif
1607 goto undfl;
1608 L -= Exp_msk1;
1609#else
1610 L = (word0(rv) & Exp_mask) - Exp_msk1;
1611#endif
1612 word0(rv) = L | Bndry_mask1;
1613 word1(rv) = 0xffffffff;
1614#ifdef IBM
1615 goto cont;
1616#else
1617 break;
1618#endif
1619 }
1620#ifndef ROUND_BIASED
1621 if (!(word1(rv) & LSB))
1622 break;
1623#endif
1624 if (dsign)
1625 value(rv) += ulp(value(rv));
1626#ifndef ROUND_BIASED
1627 else {
1628 value(rv) -= ulp(value(rv));
1629#ifndef Sudden_Underflow
1630 if (!value(rv))
1631 goto undfl;
1632#endif
1633 }
1634#endif
1635 break;
1636 }
1637 if ((aadj = ratio(delta, bs)) <= 2.) {
1638 if (dsign)
1639 aadj = aadj1 = 1.;
1640 else if (word1(rv) || word0(rv) & Bndry_mask) {
1641#ifndef Sudden_Underflow
1642 if (word1(rv) == Tiny1 && !word0(rv))
1643 goto undfl;
1644#endif
1645 aadj = 1.;
1646 aadj1 = -1.;
1647 }
1648 else {
1649 /* special case -- power of FLT_RADIX to be */
1650 /* rounded down... */
1651
1652 if (aadj < 2./FLT_RADIX)
1653 aadj = 1./FLT_RADIX;
1654 else
1655 aadj *= 0.5;
1656 aadj1 = -aadj;
1657 }
1658 }
1659 else {
1660 aadj *= 0.5;
1661 aadj1 = dsign ? aadj : -aadj;
1662#ifdef Check_FLT_ROUNDS
1663 switch(FLT_ROUNDS) {
1664 case 2: /* towards +infinity */
1665 aadj1 -= 0.5;
1666 break;
1667 case 0: /* towards 0 */
1668 case 3: /* towards -infinity */
1669 aadj1 += 0.5;
1670 }
1671#else
1672 if (FLT_ROUNDS == 0)
1673 aadj1 += 0.5;
1674#endif
1675 }
1676 y = word0(rv) & Exp_mask;
1677
1678 /* Check for overflow */
1679
1680 if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
1681 value(rv0) = value(rv);
1682 word0(rv) -= P*Exp_msk1;
1683 adj = aadj1 * ulp(value(rv));
1684 value(rv) += adj;
1685 if ((word0(rv) & Exp_mask) >=
1686 Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
1687 if (word0(rv0) == Big0 && word1(rv0) == Big1)
1688 goto ovfl;
1689 word0(rv) = Big0;
1690 word1(rv) = Big1;
1691 goto cont;
1692 }
1693 else
1694 word0(rv) += P*Exp_msk1;
1695 }
1696 else {
1697#ifdef Sudden_Underflow
1698 if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
1699 value(rv0) = value(rv);
1700 word0(rv) += P*Exp_msk1;
1701 adj = aadj1 * ulp(value(rv));
1702 value(rv) += adj;
1703#ifdef IBM
1704 if ((word0(rv) & Exp_mask) < P*Exp_msk1)
1705#else
1706 if ((word0(rv) & Exp_mask) <= P*Exp_msk1)
1707#endif
1708 {
1709 if (word0(rv0) == Tiny0
1710 && word1(rv0) == Tiny1)
1711 goto undfl;
1712 word0(rv) = Tiny0;
1713 word1(rv) = Tiny1;
1714 goto cont;
1715 }
1716 else
1717 word0(rv) -= P*Exp_msk1;
1718 }
1719 else {
1720 adj = aadj1 * ulp(value(rv));
1721 value(rv) += adj;
1722 }
1723#else
1724 /* Compute adj so that the IEEE rounding rules will
1725 * correctly round rv + adj in some half-way cases.
1726 * If rv * ulp(rv) is denormalized (i.e.,
1727 * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid
1728 * trouble from bits lost to denormalization;
1729 * example: 1.2e-307 .
1730 */
1731 if (y <= (P-1)*Exp_msk1 && aadj >= 1.) {
1732 aadj1 = (double)(int)(aadj + 0.5);
1733 if (!dsign)
1734 aadj1 = -aadj1;
1735 }
1736 adj = aadj1 * ulp(value(rv));
1737 value(rv) += adj;
1738#endif
1739 }
1740 z = word0(rv) & Exp_mask;
1741 if (y == z) {
1742 /* Can we stop now? */
1743 L = aadj;
1744 aadj -= L;
1745 /* The tolerances below are conservative. */
1746 if (dsign || word1(rv) || word0(rv) & Bndry_mask) {
1747 if (aadj < .4999999 || aadj > .5000001)
1748 break;
1749 }
1750 else if (aadj < .4999999/FLT_RADIX)
1751 break;
1752 }
1753 cont:
1754 Bfree(bb);
1755 Bfree(bd);
1756 Bfree(bs);
1757 Bfree(delta);
1758 }
1759 retfree:
1760 Bfree(bb);
1761 Bfree(bd);
1762 Bfree(bs);
1763 Bfree(bd0);
1764 Bfree(delta);
1765 ret:
1766 if (se)
1767 *se = (char *)s;
1768 return sign ? -value(rv) : value(rv);
1769 }
1770
1771 static int
1772quorem
1773#ifdef KR_headers
1774 (b, S) Bigint *b, *S;
1775#else
1776 (Bigint *b, Bigint *S)
1777#endif
1778{
1779 int n;
1780 Long borrow, y;
1781 ULong carry, q, ys;
1782 ULong *bx, *bxe, *sx, *sxe;
1783#ifdef Pack_32
1784 Long z;
1785 ULong si, zs;
1786#endif
1787
1788 n = S->wds;
1789#ifdef DEBUG
1790 /*debug*/ if (b->wds > n)
1791 /*debug*/ Bug("oversize b in quorem");
1792#endif
1793 if (b->wds < n)
1794 return 0;
1795 sx = S->x;
1796 sxe = sx + --n;
1797 bx = b->x;
1798 bxe = bx + n;
1799 q = *bxe / (*sxe + 1); /* ensure q <= true quotient */
1800#ifdef DEBUG
1801 /*debug*/ if (q > 9)
1802 /*debug*/ Bug("oversized quotient in quorem");
1803#endif
1804 if (q) {
1805 borrow = 0;
1806 carry = 0;
1807 do {
1808#ifdef Pack_32
1809 si = *sx++;
1810 ys = (si & 0xffff) * q + carry;
1811 zs = (si >> 16) * q + (ys >> 16);
1812 carry = zs >> 16;
1813 y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
1814 borrow = y >> 16;
1815 Sign_Extend(borrow, y);
1816 z = (*bx >> 16) - (zs & 0xffff) + borrow;
1817 borrow = z >> 16;
1818 Sign_Extend(borrow, z);
1819 Storeinc(bx, z, y);
1820#else
1821 ys = *sx++ * q + carry;
1822 carry = ys >> 16;
1823 y = *bx - (ys & 0xffff) + borrow;
1824 borrow = y >> 16;
1825 Sign_Extend(borrow, y);
1826 *bx++ = y & 0xffff;
1827#endif
1828 }
1829 while(sx <= sxe);
1830 if (!*bxe) {
1831 bx = b->x;
1832 while(--bxe > bx && !*bxe)
1833 --n;
1834 b->wds = n;
1835 }
1836 }
1837 if (cmp(b, S) >= 0) {
1838 q++;
1839 borrow = 0;
1840 carry = 0;
1841 bx = b->x;
1842 sx = S->x;
1843 do {
1844#ifdef Pack_32
1845 si = *sx++;
1846 ys = (si & 0xffff) + carry;
1847 zs = (si >> 16) + (ys >> 16);
1848 carry = zs >> 16;
1849 y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
1850 borrow = y >> 16;
1851 Sign_Extend(borrow, y);
1852 z = (*bx >> 16) - (zs & 0xffff) + borrow;
1853 borrow = z >> 16;
1854 Sign_Extend(borrow, z);
1855 Storeinc(bx, z, y);
1856#else
1857 ys = *sx++ + carry;
1858 carry = ys >> 16;
1859 y = *bx - (ys & 0xffff) + borrow;
1860 borrow = y >> 16;
1861 Sign_Extend(borrow, y);
1862 *bx++ = y & 0xffff;
1863#endif
1864 }
1865 while(sx <= sxe);
1866 bx = b->x;
1867 bxe = bx + n;
1868 if (!*bxe) {
1869 while(--bxe > bx && !*bxe)
1870 --n;
1871 b->wds = n;
1872 }
1873 }
1874 return q;
1875 }
1876
1877/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
1878 *
1879 * Inspired by "How to Print Floating-Point Numbers Accurately" by
1880 * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101].
1881 *
1882 * Modifications:
1883 * 1. Rather than iterating, we use a simple numeric overestimate
1884 * to determine k = floor(log10(d)). We scale relevant
1885 * quantities using O(log2(k)) rather than O(k) multiplications.
1886 * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
1887 * try to generate digits strictly left to right. Instead, we
1888 * compute with fewer bits and propagate the carry if necessary
1889 * when rounding the final digit up. This is often faster.
1890 * 3. Under the assumption that input will be rounded nearest,
1891 * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
1892 * That is, we allow equality in stopping tests when the
1893 * round-nearest rule will give the same floating-point value
1894 * as would satisfaction of the stopping test with strict
1895 * inequality.
1896 * 4. We remove common factors of powers of 2 from relevant
1897 * quantities.
1898 * 5. When converting floating-point integers less than 1e16,
1899 * we use floating-point arithmetic rather than resorting
1900 * to multiple-precision integers.
1901 * 6. When asked to produce fewer than 15 digits, we first try
1902 * to get by with floating-point arithmetic; we resort to
1903 * multiple-precision integer arithmetic only if we cannot
1904 * guarantee that the floating-point calculation has given
1905 * the correctly rounded result. For k requested digits and
1906 * "uniformly" distributed input, the probability is
1907 * something like 10^(k-15) that we must resort to the Long
1908 * calculation.
1909 */
1910
1911 char *
1912__dtoa
1913#ifdef KR_headers
1914 (_d, mode, ndigits, decpt, sign, rve)
1915 double _d; int mode, ndigits, *decpt, *sign; char **rve;
1916#else
1917 (double _d, int mode, int ndigits, int *decpt, int *sign, char **rve)
1918#endif
1919{
1920 /* Arguments ndigits, decpt, sign are similar to those
1921 of ecvt and fcvt; trailing zeros are suppressed from
1922 the returned string. If not null, *rve is set to point
1923 to the end of the return value. If d is +-Infinity or NaN,
1924 then *decpt is set to 9999.
1925
1926 mode:
1927 0 ==> shortest string that yields d when read in
1928 and rounded to nearest.
1929 1 ==> like 0, but with Steele & White stopping rule;
1930 e.g. with IEEE P754 arithmetic , mode 0 gives
1931 1e23 whereas mode 1 gives 9.999999999999999e22.
1932 2 ==> max(1,ndigits) significant digits. This gives a
1933 return value similar to that of ecvt, except
1934 that trailing zeros are suppressed.
1935 3 ==> through ndigits past the decimal point. This
1936 gives a return value similar to that from fcvt,
1937 except that trailing zeros are suppressed, and
1938 ndigits can be negative.
1939 4-9 should give the same return values as 2-3, i.e.,
1940 4 <= mode <= 9 ==> same return as mode
1941 2 + (mode & 1). These modes are mainly for
1942 debugging; often they run slower but sometimes
1943 faster than modes 2-3.
1944 4,5,8,9 ==> left-to-right digit generation.
1945 6-9 ==> don't try fast floating-point estimate
1946 (if applicable).
1947
1948 Values of mode other than 0-9 are treated as mode 0.
1949
1950 Sufficient space is allocated to the return value
1951 to hold the suppressed trailing zeros.
1952 */
1953
1954 int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1,
1955 j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
1956 spec_case, try_quick;
1957 Long L;
1958#ifndef Sudden_Underflow
1959 int denorm;
1960 ULong x;
1961#endif
1962 Bigint *b, *b1, *delta, *mlo, *mhi, *S;
1963 double ds;
1964 char *s, *s0;
1965 static Bigint *result;
1966 static int result_k;
1967 _double d, d2, eps;
1968
1969 value(d) = _d;
1970 if (result) {
1971 result->k = result_k;
1972 result->maxwds = 1 << result_k;
1973 Bfree(result);
1974 result = 0;
1975 }
1976
1977 if (word0(d) & Sign_bit) {
1978 /* set sign for everything, including 0's and NaNs */
1979 *sign = 1;
1980 word0(d) &= ~Sign_bit; /* clear sign bit */
1981 }
1982 else
1983 *sign = 0;
1984
1985#if defined(IEEE_Arith) + defined(VAX)
1986#ifdef IEEE_Arith
1987 if ((word0(d) & Exp_mask) == Exp_mask)
1988#else
1989 if (word0(d) == 0x8000)
1990#endif
1991 {
1992 /* Infinity or NaN */
1993 *decpt = 9999;
1994 s =
1995#ifdef IEEE_Arith
1996 !word1(d) && !(word0(d) & 0xfffff) ? ndigits < 8 ? "Inf" : "Infinity" :
1997#endif
1998 "NaN";
1999 if (rve)
2000 *rve =
2001#ifdef IEEE_Arith
2002 s[3] ? s + 8 :
2003#endif
2004 s + 3;
2005 return s;
2006 }
2007#endif
2008#ifdef IBM
2009 value(d) += 0; /* normalize */
2010#endif
2011 if (!value(d)) {
2012 *decpt = 1;
2013 s = "0";
2014 if (rve)
2015 *rve = s + 1;
2016 return s;
2017 }
2018
2019 b = d2b(value(d), &be, &bbits);
2020#ifdef Sudden_Underflow
2021 i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
2022#else
2023 if (i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) {
2024#endif
2025 value(d2) = value(d);
2026 word0(d2) &= Frac_mask1;
2027 word0(d2) |= Exp_11;
2028#ifdef IBM
2029 if (j = 11 - hi0bits(word0(d2) & Frac_mask))
2030 value(d2) /= 1 << j;
2031#endif
2032
2033 /* log(x) ~=~ log(1.5) + (x-1.5)/1.5
2034 * log10(x) = log(x) / log(10)
2035 * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
2036 * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
2037 *
2038 * This suggests computing an approximation k to log10(d) by
2039 *
2040 * k = (i - Bias)*0.301029995663981
2041 * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
2042 *
2043 * We want k to be too large rather than too small.
2044 * The error in the first-order Taylor series approximation
2045 * is in our favor, so we just round up the constant enough
2046 * to compensate for any error in the multiplication of
2047 * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
2048 * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
2049 * adding 1e-13 to the constant term more than suffices.
2050 * Hence we adjust the constant term to 0.1760912590558.
2051 * (We could get a more accurate k by invoking log10,
2052 * but this is probably not worthwhile.)
2053 */
2054
2055 i -= Bias;
2056#ifdef IBM
2057 i <<= 2;
2058 i += j;
2059#endif
2060#ifndef Sudden_Underflow
2061 denorm = 0;
2062 }
2063 else {
2064 /* d is denormalized */
2065
2066 i = bbits + be + (Bias + (P-1) - 1);
2067 x = i > 32 ? word0(d) << 64 - i | word1(d) >> i - 32
2068 : word1(d) << 32 - i;
2069 value(d2) = x;
2070 word0(d2) -= 31*Exp_msk1; /* adjust exponent */
2071 i -= (Bias + (P-1) - 1) + 1;
2072 denorm = 1;
2073 }
2074#endif
2075 ds = (value(d2)-1.5)*0.289529654602168 + 0.1760912590558 +
2076 i*0.301029995663981;
2077 k = (int)ds;
2078 if (ds < 0. && ds != k)
2079 k--; /* want k = floor(ds) */
2080 k_check = 1;
2081 if (k >= 0 && k <= Ten_pmax) {
2082 if (value(d) < tens[k])
2083 k--;
2084 k_check = 0;
2085 }
2086 j = bbits - i - 1;
2087 if (j >= 0) {
2088 b2 = 0;
2089 s2 = j;
2090 }
2091 else {
2092 b2 = -j;
2093 s2 = 0;
2094 }
2095 if (k >= 0) {
2096 b5 = 0;
2097 s5 = k;
2098 s2 += k;
2099 }
2100 else {
2101 b2 -= k;
2102 b5 = -k;
2103 s5 = 0;
2104 }
2105 if (mode < 0 || mode > 9)
2106 mode = 0;
2107 try_quick = 1;
2108 if (mode > 5) {
2109 mode -= 4;
2110 try_quick = 0;
2111 }
2112 leftright = 1;
2113 switch(mode) {
2114 case 0:
2115 case 1:
2116 ilim = ilim1 = -1;
2117 i = 18;
2118 ndigits = 0;
2119 break;
2120 case 2:
2121 leftright = 0;
2122 /* no break */
2123 case 4:
2124 if (ndigits <= 0)
2125 ndigits = 1;
2126 ilim = ilim1 = i = ndigits;
2127 break;
2128 case 3:
2129 leftright = 0;
2130 /* no break */
2131 case 5:
2132 i = ndigits + k + 1;
2133 ilim = i;
2134 ilim1 = i - 1;
2135 if (i <= 0)
2136 i = 1;
2137 }
2138 j = sizeof(ULong);
2139 for(result_k = 0; sizeof(Bigint) - sizeof(ULong) + j <= i;
2140 j <<= 1) result_k++;
2141 result = Balloc(result_k);
2142 s = s0 = (char *)result;
2143
2144 if (ilim >= 0 && ilim <= Quick_max && try_quick) {
2145
2146 /* Try to get by with floating-point arithmetic. */
2147
2148 i = 0;
2149 value(d2) = value(d);
2150 k0 = k;
2151 ilim0 = ilim;
2152 ieps = 2; /* conservative */
2153 if (k > 0) {
2154 ds = tens[k&0xf];
2155 j = k >> 4;
2156 if (j & Bletch) {
2157 /* prevent overflows */
2158 j &= Bletch - 1;
2159 value(d) /= bigtens[n_bigtens-1];
2160 ieps++;
2161 }
2162 for(; j; j >>= 1, i++)
2163 if (j & 1) {
2164 ieps++;
2165 ds *= bigtens[i];
2166 }
2167 value(d) /= ds;
2168 }
2169 else if (j1 = -k) {
2170 value(d) *= tens[j1 & 0xf];
2171 for(j = j1 >> 4; j; j >>= 1, i++)
2172 if (j & 1) {
2173 ieps++;
2174 value(d) *= bigtens[i];
2175 }
2176 }
2177 if (k_check && value(d) < 1. && ilim > 0) {
2178 if (ilim1 <= 0)
2179 goto fast_failed;
2180 ilim = ilim1;
2181 k--;
2182 value(d) *= 10.;
2183 ieps++;
2184 }
2185 value(eps) = ieps*value(d) + 7.;
2186 word0(eps) -= (P-1)*Exp_msk1;
2187 if (ilim == 0) {
2188 S = mhi = 0;
2189 value(d) -= 5.;
2190 if (value(d) > value(eps))
2191 goto one_digit;
2192 if (value(d) < -value(eps))
2193 goto no_digits;
2194 goto fast_failed;
2195 }
2196#ifndef No_leftright
2197 if (leftright) {
2198 /* Use Steele & White method of only
2199 * generating digits needed.
2200 */
2201 value(eps) = 0.5/tens[ilim-1] - value(eps);
2202 for(i = 0;;) {
2203 L = value(d);
2204 value(d) -= L;
2205 *s++ = '0' + (int)L;
2206 if (value(d) < value(eps))
2207 goto ret1;
2208 if (1. - value(d) < value(eps))
2209 goto bump_up;
2210 if (++i >= ilim)
2211 break;
2212 value(eps) *= 10.;
2213 value(d) *= 10.;
2214 }
2215 }
2216 else {
2217#endif
2218 /* Generate ilim digits, then fix them up. */
2219 value(eps) *= tens[ilim-1];
2220 for(i = 1;; i++, value(d) *= 10.) {
2221 L = value(d);
2222 value(d) -= L;
2223 *s++ = '0' + (int)L;
2224 if (i == ilim) {
2225 if (value(d) > 0.5 + value(eps))
2226 goto bump_up;
2227 else if (value(d) < 0.5 - value(eps)) {
2228 while(*--s == '0');
2229 s++;
2230 goto ret1;
2231 }
2232 break;
2233 }
2234 }
2235#ifndef No_leftright
2236 }
2237#endif
2238 fast_failed:
2239 s = s0;
2240 value(d) = value(d2);
2241 k = k0;
2242 ilim = ilim0;
2243 }
2244
2245 /* Do we have a "small" integer? */
2246
2247 if (be >= 0 && k <= Int_max) {
2248 /* Yes. */
2249 ds = tens[k];
2250 if (ndigits < 0 && ilim <= 0) {
2251 S = mhi = 0;
2252 if (ilim < 0 || value(d) <= 5*ds)
2253 goto no_digits;
2254 goto one_digit;
2255 }
2256 for(i = 1;; i++) {
2257 L = value(d) / ds;
2258 value(d) -= L*ds;
2259#ifdef Check_FLT_ROUNDS
2260 /* If FLT_ROUNDS == 2, L will usually be high by 1 */
2261 if (value(d) < 0) {
2262 L--;
2263 value(d) += ds;
2264 }
2265#endif
2266 *s++ = '0' + (int)L;
2267 if (i == ilim) {
2268 value(d) += value(d);
2269 if (value(d) > ds || value(d) == ds && L & 1) {
2270 bump_up:
2271 while(*--s == '9')
2272 if (s == s0) {
2273 k++;
2274 *s = '0';
2275 break;
2276 }
2277 ++*s++;
2278 }
2279 break;
2280 }
2281 if (!(value(d) *= 10.))
2282 break;
2283 }
2284 goto ret1;
2285 }
2286
2287 m2 = b2;
2288 m5 = b5;
2289 mhi = mlo = 0;
2290 if (leftright) {
2291 if (mode < 2) {
2292 i =
2293#ifndef Sudden_Underflow
2294 denorm ? be + (Bias + (P-1) - 1 + 1) :
2295#endif
2296#ifdef IBM
2297 1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3);
2298#else
2299 1 + P - bbits;
2300#endif
2301 }
2302 else {
2303 j = ilim - 1;
2304 if (m5 >= j)
2305 m5 -= j;
2306 else {
2307 s5 += j -= m5;
2308 b5 += j;
2309 m5 = 0;
2310 }
2311 if ((i = ilim) < 0) {
2312 m2 -= i;
2313 i = 0;
2314 }
2315 }
2316 b2 += i;
2317 s2 += i;
2318 mhi = i2b(1);
2319 }
2320 if (m2 > 0 && s2 > 0) {
2321 i = m2 < s2 ? m2 : s2;
2322 b2 -= i;
2323 m2 -= i;
2324 s2 -= i;
2325 }
2326 if (b5 > 0) {
2327 if (leftright) {
2328 if (m5 > 0) {
2329 mhi = pow5mult(mhi, m5);
2330 b1 = mult(mhi, b);
2331 Bfree(b);
2332 b = b1;
2333 }
2334 if (j = b5 - m5)
2335 b = pow5mult(b, j);
2336 }
2337 else
2338 b = pow5mult(b, b5);
2339 }
2340 S = i2b(1);
2341 if (s5 > 0)
2342 S = pow5mult(S, s5);
2343
2344 /* Check for special case that d is a normalized power of 2. */
2345
2346 if (mode < 2) {
2347 if (!word1(d) && !(word0(d) & Bndry_mask)
2348#ifndef Sudden_Underflow
2349 && word0(d) & Exp_mask
2350#endif
2351 ) {
2352 /* The special case */
2353 b2 += Log2P;
2354 s2 += Log2P;
2355 spec_case = 1;
2356 }
2357 else
2358 spec_case = 0;
2359 }
2360
2361 /* Arrange for convenient computation of quotients:
2362 * shift left if necessary so divisor has 4 leading 0 bits.
2363 *
2364 * Perhaps we should just compute leading 28 bits of S once
2365 * and for all and pass them and a shift to quorem, so it
2366 * can do shifts and ors to compute the numerator for q.
2367 */
2368#ifdef Pack_32
2369 if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f)
2370 i = 32 - i;
2371#else
2372 if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf)
2373 i = 16 - i;
2374#endif
2375 if (i > 4) {
2376 i -= 4;
2377 b2 += i;
2378 m2 += i;
2379 s2 += i;
2380 }
2381 else if (i < 4) {
2382 i += 28;
2383 b2 += i;
2384 m2 += i;
2385 s2 += i;
2386 }
2387 if (b2 > 0)
2388 b = lshift(b, b2);
2389 if (s2 > 0)
2390 S = lshift(S, s2);
2391 if (k_check) {
2392 if (cmp(b,S) < 0) {
2393 k--;
2394 b = multadd(b, 10, 0); /* we botched the k estimate */
2395 if (leftright)
2396 mhi = multadd(mhi, 10, 0);
2397 ilim = ilim1;
2398 }
2399 }
2400 if (ilim <= 0 && mode > 2) {
2401 if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) {
2402 /* no digits, fcvt style */
2403 no_digits:
2404 k = -1 - ndigits;
2405 goto ret;
2406 }
2407 one_digit:
2408 *s++ = '1';
2409 k++;
2410 goto ret;
2411 }
2412 if (leftright) {
2413 if (m2 > 0)
2414 mhi = lshift(mhi, m2);
2415
2416 /* Compute mlo -- check for special case
2417 * that d is a normalized power of 2.
2418 */
2419
2420 mlo = mhi;
2421 if (spec_case) {
2422 mhi = Balloc(mhi->k);
2423 Bcopy(mhi, mlo);
2424 mhi = lshift(mhi, Log2P);
2425 }
2426
2427 for(i = 1;;i++) {
2428 dig = quorem(b,S) + '0';
2429 /* Do we yet have the shortest decimal string
2430 * that will round to d?
2431 */
2432 j = cmp(b, mlo);
2433 delta = diff(S, mhi);
2434 j1 = delta->sign ? 1 : cmp(b, delta);
2435 Bfree(delta);
2436#ifndef ROUND_BIASED
2437 if (j1 == 0 && !mode && !(word1(d) & 1)) {
2438 if (dig == '9')
2439 goto round_9_up;
2440 if (j > 0)
2441 dig++;
2442 *s++ = dig;
2443 goto ret;
2444 }
2445#endif
2446 if (j < 0 || j == 0 && !mode
2447#ifndef ROUND_BIASED
2448 && !(word1(d) & 1)
2449#endif
2450 ) {
2451 if (j1 > 0) {
2452 b = lshift(b, 1);
2453 j1 = cmp(b, S);
2454 if ((j1 > 0 || j1 == 0 && dig & 1)
2455 && dig++ == '9')
2456 goto round_9_up;
2457 }
2458 *s++ = dig;
2459 goto ret;
2460 }
2461 if (j1 > 0) {
2462 if (dig == '9') { /* possible if i == 1 */
2463 round_9_up:
2464 *s++ = '9';
2465 goto roundoff;
2466 }
2467 *s++ = dig + 1;
2468 goto ret;
2469 }
2470 *s++ = dig;
2471 if (i == ilim)
2472 break;
2473 b = multadd(b, 10, 0);
2474 if (mlo == mhi)
2475 mlo = mhi = multadd(mhi, 10, 0);
2476 else {
2477 mlo = multadd(mlo, 10, 0);
2478 mhi = multadd(mhi, 10, 0);
2479 }
2480 }
2481 }
2482 else
2483 for(i = 1;; i++) {
2484 *s++ = dig = quorem(b,S) + '0';
2485 if (i >= ilim)
2486 break;
2487 b = multadd(b, 10, 0);
2488 }
2489
2490 /* Round off last digit */
2491
2492 b = lshift(b, 1);
2493 j = cmp(b, S);
2494 if (j > 0 || j == 0 && dig & 1) {
2495 roundoff:
2496 while(*--s == '9')
2497 if (s == s0) {
2498 k++;
2499 *s++ = '1';
2500 goto ret;
2501 }
2502 ++*s++;
2503 }
2504 else {
2505 while(*--s == '0');
2506 s++;
2507 }
2508 ret:
2509 Bfree(S);
2510 if (mhi) {
2511 if (mlo && mlo != mhi)
2512 Bfree(mlo);
2513 Bfree(mhi);
2514 }
2515 ret1:
2516 Bfree(b);
2517 if (s == s0) { /* don't return empty string */
2518 *s++ = '0';
2519 k = 0;
2520 }
2521 *s = 0;
2522 *decpt = k + 1;
2523 if (rve)
2524 *rve = s;
2525 return s0;
2526 }
2527#ifdef __cplusplus
2528}
2529#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}