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.inc72
-rw-r--r--src/lib/libc/stdlib/_Exit.c22
-rw-r--r--src/lib/libc/stdlib/_rand48.c47
-rw-r--r--src/lib/libc/stdlib/a64l.3133
-rw-r--r--src/lib/libc/stdlib/a64l.c42
-rw-r--r--src/lib/libc/stdlib/abort.363
-rw-r--r--src/lib/libc/stdlib/abort.c75
-rw-r--r--src/lib/libc/stdlib/abs.366
-rw-r--r--src/lib/libc/stdlib/abs.c37
-rw-r--r--src/lib/libc/stdlib/alloca.380
-rw-r--r--src/lib/libc/stdlib/atexit.377
-rw-r--r--src/lib/libc/stdlib/atexit.c133
-rw-r--r--src/lib/libc/stdlib/atexit.h41
-rw-r--r--src/lib/libc/stdlib/atof.369
-rw-r--r--src/lib/libc/stdlib/atof.c37
-rw-r--r--src/lib/libc/stdlib/atoi.386
-rw-r--r--src/lib/libc/stdlib/atoi.c37
-rw-r--r--src/lib/libc/stdlib/atol.370
-rw-r--r--src/lib/libc/stdlib/atol.c37
-rw-r--r--src/lib/libc/stdlib/atoll.370
-rw-r--r--src/lib/libc/stdlib/atoll.c38
-rw-r--r--src/lib/libc/stdlib/bsearch.384
-rw-r--r--src/lib/libc/stdlib/bsearch.c67
-rw-r--r--src/lib/libc/stdlib/calloc.c50
-rw-r--r--src/lib/libc/stdlib/cfree.c40
-rw-r--r--src/lib/libc/stdlib/div.365
-rw-r--r--src/lib/libc/stdlib/div.c71
-rw-r--r--src/lib/libc/stdlib/drand48.c23
-rw-r--r--src/lib/libc/stdlib/ecvt.3165
-rw-r--r--src/lib/libc/stdlib/ecvt.c99
-rw-r--r--src/lib/libc/stdlib/erand48.c24
-rw-r--r--src/lib/libc/stdlib/exit.3114
-rw-r--r--src/lib/libc/stdlib/exit.c69
-rw-r--r--src/lib/libc/stdlib/gcvt.c108
-rw-r--r--src/lib/libc/stdlib/getenv.3148
-rw-r--r--src/lib/libc/stdlib/getenv.c80
-rw-r--r--src/lib/libc/stdlib/getopt.3387
-rw-r--r--src/lib/libc/stdlib/getopt_long.3459
-rw-r--r--src/lib/libc/stdlib/getopt_long.c533
-rw-r--r--src/lib/libc/stdlib/getsubopt.3145
-rw-r--r--src/lib/libc/stdlib/getsubopt.c92
-rw-r--r--src/lib/libc/stdlib/hcreate.3191
-rw-r--r--src/lib/libc/stdlib/hcreate.c191
-rw-r--r--src/lib/libc/stdlib/heapsort.c173
-rw-r--r--src/lib/libc/stdlib/imaxabs.366
-rw-r--r--src/lib/libc/stdlib/imaxabs.c38
-rw-r--r--src/lib/libc/stdlib/imaxdiv.367
-rw-r--r--src/lib/libc/stdlib/imaxdiv.c50
-rw-r--r--src/lib/libc/stdlib/insque.3106
-rw-r--r--src/lib/libc/stdlib/insque.c48
-rw-r--r--src/lib/libc/stdlib/jrand48.c22
-rw-r--r--src/lib/libc/stdlib/l64a.c42
-rw-r--r--src/lib/libc/stdlib/labs.369
-rw-r--r--src/lib/libc/stdlib/labs.c37
-rw-r--r--src/lib/libc/stdlib/lcong48.c31
-rw-r--r--src/lib/libc/stdlib/ldiv.367
-rw-r--r--src/lib/libc/stdlib/ldiv.c50
-rw-r--r--src/lib/libc/stdlib/llabs.c42
-rw-r--r--src/lib/libc/stdlib/lldiv.367
-rw-r--r--src/lib/libc/stdlib/lldiv.c50
-rw-r--r--src/lib/libc/stdlib/lrand48.c24
-rw-r--r--src/lib/libc/stdlib/lsearch.3108
-rw-r--r--src/lib/libc/stdlib/lsearch.c88
-rw-r--r--src/lib/libc/stdlib/malloc.3466
-rw-r--r--src/lib/libc/stdlib/malloc.c1870
-rw-r--r--src/lib/libc/stdlib/merge.c333
-rw-r--r--src/lib/libc/stdlib/mrand48.c24
-rw-r--r--src/lib/libc/stdlib/nrand48.c22
-rw-r--r--src/lib/libc/stdlib/putenv.c50
-rw-r--r--src/lib/libc/stdlib/qabs.357
-rw-r--r--src/lib/libc/stdlib/qabs.c37
-rw-r--r--src/lib/libc/stdlib/qdiv.362
-rw-r--r--src/lib/libc/stdlib/qdiv.c50
-rw-r--r--src/lib/libc/stdlib/qsort.3233
-rw-r--r--src/lib/libc/stdlib/qsort.c161
-rw-r--r--src/lib/libc/stdlib/radixsort.3155
-rw-r--r--src/lib/libc/stdlib/radixsort.c294
-rw-r--r--src/lib/libc/stdlib/rand.398
-rw-r--r--src/lib/libc/stdlib/rand.c52
-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.3185
-rw-r--r--src/lib/libc/stdlib/random.c395
-rw-r--r--src/lib/libc/stdlib/realpath.3117
-rw-r--r--src/lib/libc/stdlib/realpath.c190
-rw-r--r--src/lib/libc/stdlib/remque.c44
-rw-r--r--src/lib/libc/stdlib/seed48.c37
-rw-r--r--src/lib/libc/stdlib/setenv.c103
-rw-r--r--src/lib/libc/stdlib/srand48.c31
-rw-r--r--src/lib/libc/stdlib/strtod.3113
-rw-r--r--src/lib/libc/stdlib/strtod.c2408
-rw-r--r--src/lib/libc/stdlib/strtoimax.c140
-rw-r--r--src/lib/libc/stdlib/strtol.3258
-rw-r--r--src/lib/libc/stdlib/strtol.c140
-rw-r--r--src/lib/libc/stdlib/strtoll.c153
-rw-r--r--src/lib/libc/stdlib/strtonum.3152
-rw-r--r--src/lib/libc/stdlib/strtonum.c65
-rw-r--r--src/lib/libc/stdlib/strtoul.3242
-rw-r--r--src/lib/libc/stdlib/strtoul.c102
-rw-r--r--src/lib/libc/stdlib/strtoull.c115
-rw-r--r--src/lib/libc/stdlib/strtoumax.c102
-rw-r--r--src/lib/libc/stdlib/system.399
-rw-r--r--src/lib/libc/stdlib/system.c74
-rw-r--r--src/lib/libc/stdlib/tfind.c41
-rw-r--r--src/lib/libc/stdlib/tsearch.3127
-rw-r--r--src/lib/libc/stdlib/tsearch.c121
106 files changed, 15497 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..c7ee0a80ec
--- /dev/null
+++ b/src/lib/libc/stdlib/Makefile.inc
@@ -0,0 +1,72 @@
1# $OpenBSD: Makefile.inc,v 1.35 2006/01/13 17:58:09 millert Exp $
2
3# stdlib sources
4.PATH: ${LIBCSRCDIR}/arch/${MACHINE_ARCH}/stdlib ${LIBCSRCDIR}/stdlib
5
6SRCS+= a64l.c abort.c atexit.c atoi.c atof.c atol.c atoll.c bsearch.c \
7 calloc.c cfree.c exit.c ecvt.c gcvt.c getenv.c getopt_long.c \
8 getsubopt.c hcreate.c heapsort.c imaxabs.c imaxdiv.c l64a.c llabs.c \
9 lldiv.c lsearch.c malloc.c merge.c putenv.c qsort.c radixsort.c rand.c \
10 random.c realpath.c setenv.c strtoimax.c strtod.c strtol.c strtoll.c \
11 strtonum.c strtoul.c strtoull.c strtoumax.c system.c \
12 tfind.c tsearch.c _rand48.c drand48.c erand48.c jrand48.c lcong48.c \
13 lrand48.c mrand48.c nrand48.c seed48.c srand48.c qabs.c qdiv.c _Exit.c
14
15.if (${MACHINE_ARCH} == "m68k")
16SRCS+= abs.S div.c labs.c ldiv.c
17LSRCS+= abs.c
18.elif (${MACHINE_ARCH} == "i386")
19SRCS+= abs.S div.S labs.S ldiv.S
20LSRCS+= abs.c div.c labs.c ldiv.c
21.elif (${MACHINE_ARCH} == "ns32k")
22SRCS+= abs.S div.c labs.c ldiv.c
23LSRCS+= abs.c
24.elif (${MACHINE_ARCH} == "tahoe")
25SRCS+= abs.S div.c labs.c ldiv.c
26LSRCS+= abs.c
27.elif (${MACHINE_ARCH} == "vax")
28SRCS+= abs.c div.c labs.c ldiv.c
29.elif (${MACHINE_ARCH} == "alpha")
30# XXX should be .S's
31SRCS+= abs.c div.c labs.c ldiv.c
32.else
33SRCS+= abs.c div.c labs.c ldiv.c
34.endif
35
36.if (${MACHINE_ARCH} == "vax") || (${MACHINE_ARCH} == "m68k")
37SRCS+= insque.S remque.S
38.else
39SRCS+= insque.c remque.c
40.endif
41
42MAN+= a64l.3 abort.3 abs.3 alloca.3 atexit.3 atof.3 atoi.3 atol.3 atoll.3 \
43 bsearch.3 div.3 ecvt.3 exit.3 getenv.3 getopt.3 getopt_long.3 \
44 getsubopt.3 hcreate.3 imaxabs.3 imaxdiv.3 insque.3 labs.3 ldiv.3 \
45 lldiv.3 lsearch.3 malloc.3 qabs.3 qdiv.3 qsort.3 radixsort.3 rand48.3 \
46 rand.3 random.3 realpath.3 strtod.3 strtonum.3 strtol.3 strtoul.3 \
47 system.3 tsearch.3
48
49MLINKS+=exit.3 _Exit.3
50MLINKS+=ecvt.3 fcvt.3 ecvt.3 gcvt.3
51MLINKS+=getenv.3 setenv.3 getenv.3 unsetenv.3 getenv.3 putenv.3
52MLINKS+=getopt_long.3 getopt_long_only.3
53MLINKS+=hcreate.3 hdestroy.3 hcreate.3 hsearch.3
54MLINKS+=insque.3 remque.3
55MLINKS+=labs.3 llabs.3
56MLINKS+=lsearch.3 lfind.3
57MLINKS+=malloc.3 free.3 malloc.3 realloc.3 malloc.3 calloc.3
58MLINKS+=malloc.3 cfree.3 malloc.3 malloc.conf.5
59MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3
60MLINKS+=radixsort.3 sradixsort.3
61MLINKS+=rand.3 srand.3 rand.3 rand_r.3
62MLINKS+=random.3 initstate.3 random.3 setstate.3
63MLINKS+=random.3 srandom.3 random.3 srandomdev.3
64MLINKS+=rand48.3 drand48.3 rand48.3 erand48.3 rand48.3 lrand48.3
65MLINKS+=rand48.3 mrand48.3 rand48.3 nrand48.3 rand48.3 jrand48.3
66MLINKS+=rand48.3 srand48.3 rand48.3 seed48.3 rand48.3 lcong48.3
67MLINKS+=strtol.3 strtoll.3 strtol.3 strtoq.3 strtol.3 strtoimax.3
68MLINKS+=strtoul.3 strtoull.3 strtoul.3 strtouq.3 strtoul.3 strtoumax.3
69MLINKS+=tsearch.3 tfind.3
70MLINKS+=tsearch.3 tdelete.3
71MLINKS+=tsearch.3 twalk.3
72MLINKS+=a64l.3 l64a.3
diff --git a/src/lib/libc/stdlib/_Exit.c b/src/lib/libc/stdlib/_Exit.c
new file mode 100644
index 0000000000..5a2291a931
--- /dev/null
+++ b/src/lib/libc/stdlib/_Exit.c
@@ -0,0 +1,22 @@
1/* $OpenBSD: _Exit.c,v 1.2 2005/08/08 08:05:36 espie Exp $ */
2
3/*
4 * Placed in the public domain by Todd C. Miller on January 21, 2004.
5 */
6
7#include <stdlib.h>
8#include <unistd.h>
9
10/*
11 * _Exit() is the ISO/ANSI C99 equivalent of the POSIX _exit() function.
12 * No atexit() handlers are called and no signal handlers are run.
13 * Whether or not stdio buffers are flushed or temporary files are removed
14 * is implementation-dependent. As such it is safest to *not* flush
15 * stdio buffers or remove temporary files. This is also consistent
16 * with most other implementations.
17 */
18void
19_Exit(int status)
20{
21 _exit(status);
22}
diff --git a/src/lib/libc/stdlib/_rand48.c b/src/lib/libc/stdlib/_rand48.c
new file mode 100644
index 0000000000..7c950f7cee
--- /dev/null
+++ b/src/lib/libc/stdlib/_rand48.c
@@ -0,0 +1,47 @@
1/* $OpenBSD: _rand48.c,v 1.3 2005/08/08 08:05:36 espie Exp $ */
2/*
3 * Copyright (c) 1993 Martin Birgmeier
4 * All rights reserved.
5 *
6 * You may redistribute unmodified or modified versions of this source
7 * code provided that the above copyright notice and this and the
8 * following conditions are retained.
9 *
10 * This software is provided ``as is'', and comes with no warranties
11 * of any kind. I shall in no event be liable for anything that happens
12 * to anyone/anything when using this software.
13 */
14
15#include "rand48.h"
16
17unsigned short __rand48_seed[3] = {
18 RAND48_SEED_0,
19 RAND48_SEED_1,
20 RAND48_SEED_2
21};
22unsigned short __rand48_mult[3] = {
23 RAND48_MULT_0,
24 RAND48_MULT_1,
25 RAND48_MULT_2
26};
27unsigned short __rand48_add = RAND48_ADD;
28
29void
30__dorand48(unsigned short xseed[3])
31{
32 unsigned long accu;
33 unsigned short temp[2];
34
35 accu = (unsigned long) __rand48_mult[0] * (unsigned long) xseed[0] +
36 (unsigned long) __rand48_add;
37 temp[0] = (unsigned short) accu; /* lower 16 bits */
38 accu >>= sizeof(unsigned short) * 8;
39 accu += (unsigned long) __rand48_mult[0] * (unsigned long) xseed[1] +
40 (unsigned long) __rand48_mult[1] * (unsigned long) xseed[0];
41 temp[1] = (unsigned short) accu; /* middle 16 bits */
42 accu >>= sizeof(unsigned short) * 8;
43 accu += __rand48_mult[0] * xseed[2] + __rand48_mult[1] * xseed[1] + __rand48_mult[2] * xseed[0];
44 xseed[0] = temp[0];
45 xseed[1] = temp[1];
46 xseed[2] = (unsigned short) accu;
47}
diff --git a/src/lib/libc/stdlib/a64l.3 b/src/lib/libc/stdlib/a64l.3
new file mode 100644
index 0000000000..f2957a7ad4
--- /dev/null
+++ b/src/lib/libc/stdlib/a64l.3
@@ -0,0 +1,133 @@
1.\" $OpenBSD: a64l.3,v 1.9 2005/02/25 03:12:44 cloder Exp $
2.\"
3.\" Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
4.\"
5.\" Permission to use, copy, modify, and distribute this software for any
6.\" purpose with or without fee is hereby granted, provided that the above
7.\" copyright notice and this permission notice appear in all copies.
8.\"
9.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16.\"
17.Dd August 17, 1997
18.Dt A64L 3
19.Os
20.Sh NAME
21.Nm a64l ,
22.Nm l64a
23.Nd convert between 32-bit integer and radix-64 ASCII string
24.Sh SYNOPSIS
25.Fd #include <stdlib.h>
26.Ft long
27.Fn a64l "const char *s"
28.Ft char *
29.Fn l64a "long l"
30.Sh DESCRIPTION
31The
32.Fn a64l
33and
34.Fn l64a
35functions are used to maintain numbers stored in radix-64
36.Tn ASCII
37characters.
38This is a notation by which 32-bit integers
39can be represented by up to six characters; each character represents a
40.Dq digit
41in a radix-64 notation.
42.Pp
43The characters used to represent digits are
44.Ql \&.
45for 0,
46.Ql /
47for 1,
48.Ql 0
49through
50.Ql 9
51for 2-11,
52.Ql A
53through
54.Ql Z
55for 12-37, and
56.Ql a
57through
58.Ql z
59for 38-63.
60.Pp
61The
62.Fn a64l
63function takes a pointer to a NUL-terminated radix-64 representation
64and returns a corresponding 32-bit value.
65If the string pointed to by
66.Fa s
67contains more than six characters,
68.Fn a64l
69will use the first six.
70.Fn a64l
71scans the character string from left to right, decoding
72each character as a 6-bit radix-64 number.
73If a long integer is
74larger than 32 bits, the return value will be sign-extended.
75.Pp
76.Fn l64a
77takes a long integer argument
78.Fa l
79and returns a pointer to the corresponding radix-64 representation.
80.Sh RETURN VALUES
81On success,
82.Fn a64l
83returns a 32-bit representation of
84.Fa s .
85If
86.Fa s
87is a null pointer or if it contains digits other than those described above,
88.Fn a64l
89returns \-1 and sets the global variable
90.Va errno
91to
92.Er EINVAL .
93.Pp
94On success,
95.Fn l64a
96returns a pointer to a string containing the radix-64 representation of
97.Fa l .
98If
99.Fa l
100is 0,
101.Fn l64a
102returns a pointer to the empty string.
103If
104.Fa l
105is negative,
106.Fn l64a
107returns a null pointer and sets the global variable
108.Va errno
109to
110.Er EINVAL .
111.Sh WARNINGS
112The value returned by
113.Fn l64a
114is a pointer into a static buffer, the contents of which
115will be overwritten by subsequent calls.
116.Pp
117The value returned by
118.Fn a64l
119may be incorrect if the value is too large; for that reason, only strings
120that resulted from a call to
121.Fn l64a
122should be used to call
123.Fn a64l .
124.Pp
125If a long integer is larger than 32 bits, only the low-order
12632 bits are used.
127.Sh STANDARDS
128The
129.Fn a64l
130and
131.Fn l64a
132functions conform to
133.St -xpg4.2 .
diff --git a/src/lib/libc/stdlib/a64l.c b/src/lib/libc/stdlib/a64l.c
new file mode 100644
index 0000000000..5312929c6f
--- /dev/null
+++ b/src/lib/libc/stdlib/a64l.c
@@ -0,0 +1,42 @@
1/* $OpenBSD: a64l.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
2/*
3 * Written by J.T. Conklin <jtc@netbsd.org>.
4 * Public domain.
5 */
6
7#include <errno.h>
8#include <stdlib.h>
9
10long
11a64l(const char *s)
12{
13 long value, digit, shift;
14 int i;
15
16 if (s == NULL) {
17 errno = EINVAL;
18 return(-1L);
19 }
20
21 value = 0;
22 shift = 0;
23 for (i = 0; *s && i < 6; i++, s++) {
24 if (*s >= '.' && *s <= '/')
25 digit = *s - '.';
26 else if (*s >= '0' && *s <= '9')
27 digit = *s - '0' + 2;
28 else if (*s >= 'A' && *s <= 'Z')
29 digit = *s - 'A' + 12;
30 else if (*s >= 'a' && *s <= 'z')
31 digit = *s - 'a' + 38;
32 else {
33 errno = EINVAL;
34 return(-1L);
35 }
36
37 value |= digit << shift;
38 shift += 6;
39 }
40
41 return(value);
42}
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..072a9fa8c1
--- /dev/null
+++ b/src/lib/libc/stdlib/abort.c
@@ -0,0 +1,75 @@
1/* $OpenBSD: abort.c,v 1.14 2005/08/08 08:05:36 espie Exp $ */
2/*
3 * Copyright (c) 1985 Regents of the University of California.
4 * 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
31#include <signal.h>
32#include <stdlib.h>
33#include <unistd.h>
34#include "thread_private.h"
35#include "atexit.h"
36
37void
38abort(void)
39{
40 struct atexit *p = __atexit;
41 static int cleanup_called = 0;
42 sigset_t mask;
43
44
45 sigfillset(&mask);
46 /*
47 * don't block SIGABRT to give any handler a chance; we ignore
48 * any errors -- X311J doesn't allow abort to return anyway.
49 */
50 sigdelset(&mask, SIGABRT);
51 (void)_thread_sys_sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
52
53 /*
54 * POSIX requires we flush stdio buffers on abort
55 */
56 if (cleanup_called == 0) {
57 while (p != NULL && p->next != NULL)
58 p = p->next;
59 if (p != NULL && p->fns[0] != NULL) {
60 cleanup_called = 1;
61 (*p->fns[0])();
62 }
63 }
64
65 (void)kill(getpid(), SIGABRT);
66
67 /*
68 * if SIGABRT ignored, or caught and the handler returns, do
69 * it again, only harder.
70 */
71 (void)signal(SIGABRT, SIG_DFL);
72 (void)_thread_sys_sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
73 (void)kill(getpid(), SIGABRT);
74 _exit(1);
75}
diff --git a/src/lib/libc/stdlib/abs.3 b/src/lib/libc/stdlib/abs.3
new file mode 100644
index 0000000000..fc0b20b7d5
--- /dev/null
+++ b/src/lib/libc/stdlib/abs.3
@@ -0,0 +1,66 @@
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.7 2006/01/13 17:58:09 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 imaxabs 3 ,
58.Xr labs 3 ,
59.Xr math 3
60.Sh STANDARDS
61The
62.Fn abs
63function conforms to
64.St -ansiC .
65.Sh BUGS
66The 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..5d2fbae69f
--- /dev/null
+++ b/src/lib/libc/stdlib/abs.c
@@ -0,0 +1,37 @@
1/* $OpenBSD: abs.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
2/*-
3 * Copyright (c) 1990 The Regents of the University of California.
4 * 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
31#include <stdlib.h>
32
33int
34abs(int j)
35{
36 return(j < 0 ? -j : j);
37}
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..4272c8b66d
--- /dev/null
+++ b/src/lib/libc/stdlib/atexit.3
@@ -0,0 +1,77 @@
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.7 2005/08/22 14:17:31 jmc 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.Pp
58.Fn atexit
59is very difficult to use correctly without creating
60.Xr exit 3 Ns -time
61races.
62Unless absolutely necessary, please avoid using it.
63.Sh RETURN VALUES
64.Rv -std atexit
65.Sh ERRORS
66.Bl -tag -width Er
67.It Bq Er ENOMEM
68No memory was available to add the function to the list.
69The existing list of functions is unmodified.
70.El
71.Sh SEE ALSO
72.Xr exit 3
73.Sh STANDARDS
74The
75.Fn atexit
76function conforms to
77.St -ansiC .
diff --git a/src/lib/libc/stdlib/atexit.c b/src/lib/libc/stdlib/atexit.c
new file mode 100644
index 0000000000..50f8ec9372
--- /dev/null
+++ b/src/lib/libc/stdlib/atexit.c
@@ -0,0 +1,133 @@
1/* $OpenBSD: atexit.c,v 1.12 2006/02/22 07:16:32 otto Exp $ */
2/*
3 * Copyright (c) 2002 Daniel Hartmeier
4 * 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 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials provided
15 * with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * 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
32#include <sys/types.h>
33#include <sys/mman.h>
34#include <stdlib.h>
35#include <unistd.h>
36#include "atexit.h"
37#include "thread_private.h"
38
39int __atexit_invalid = 1;
40struct atexit *__atexit;
41
42/*
43 * Function pointers are stored in a linked list of pages. The list
44 * is initially empty, and pages are allocated on demand. The first
45 * function pointer in the first allocated page (the last one in
46 * the linked list) is reserved for the cleanup function.
47 *
48 * Outside the following two functions, all pages are mprotect()'ed
49 * to prevent unintentional/malicious corruption.
50 */
51
52/*
53 * Register a function to be performed at exit.
54 */
55int
56atexit(void (*fn)(void))
57{
58 struct atexit *p;
59 int pgsize = getpagesize();
60 int ret = -1;
61
62 if (pgsize < sizeof(*p))
63 return (-1);
64 _ATEXIT_LOCK();
65 p = __atexit;
66 if (p != NULL) {
67 if (p->ind + 1 >= p->max)
68 p = NULL;
69 else if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
70 goto unlock;
71 }
72 if (p == NULL) {
73 p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
74 MAP_ANON | MAP_PRIVATE, -1, 0);
75 if (p == MAP_FAILED)
76 goto unlock;
77 if (__atexit == NULL) {
78 p->fns[0] = NULL;
79 p->ind = 1;
80 } else
81 p->ind = 0;
82 p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
83 sizeof(p->fns[0]);
84 p->next = __atexit;
85 __atexit = p;
86 if (__atexit_invalid)
87 __atexit_invalid = 0;
88 }
89 p->fns[p->ind++] = fn;
90 if (mprotect(p, pgsize, PROT_READ))
91 goto unlock;
92 ret = 0;
93unlock:
94 _ATEXIT_UNLOCK();
95 return (ret);
96}
97
98/*
99 * Register the cleanup function
100 */
101void
102__atexit_register_cleanup(void (*fn)(void))
103{
104 struct atexit *p;
105 int pgsize = getpagesize();
106
107 if (pgsize < sizeof(*p))
108 return;
109 _ATEXIT_LOCK();
110 p = __atexit;
111 while (p != NULL && p->next != NULL)
112 p = p->next;
113 if (p == NULL) {
114 p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
115 MAP_ANON | MAP_PRIVATE, -1, 0);
116 if (p == MAP_FAILED)
117 goto unlock;
118 p->ind = 1;
119 p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
120 sizeof(p->fns[0]);
121 p->next = NULL;
122 __atexit = p;
123 if (__atexit_invalid)
124 __atexit_invalid = 0;
125 } else {
126 if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
127 goto unlock;
128 }
129 p->fns[0] = fn;
130 mprotect(p, pgsize, PROT_READ);
131unlock:
132 _ATEXIT_UNLOCK();
133}
diff --git a/src/lib/libc/stdlib/atexit.h b/src/lib/libc/stdlib/atexit.h
new file mode 100644
index 0000000000..21b0c2e532
--- /dev/null
+++ b/src/lib/libc/stdlib/atexit.h
@@ -0,0 +1,41 @@
1/* $OpenBSD: atexit.h,v 1.6 2003/07/31 07:08:42 deraadt Exp $ */
2
3/*
4 * Copyright (c) 2002 Daniel Hartmeier
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * - Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 */
32
33struct atexit {
34 struct atexit *next; /* next in list */
35 int ind; /* next index in this table */
36 int max; /* max entries >= ATEXIT_SIZE */
37 void (*fns[1])(void); /* the table itself */
38};
39
40extern int __atexit_invalid;
41extern struct atexit *__atexit; /* points to head of LIFO stack */
diff --git a/src/lib/libc/stdlib/atof.3 b/src/lib/libc/stdlib/atof.3
new file mode 100644
index 0000000000..c60b9e9fd7
--- /dev/null
+++ b/src/lib/libc/stdlib/atof.3
@@ -0,0 +1,69 @@
1.\" Copyright (c) 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information
6.\" Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: atof.3,v 1.4 2003/06/02 20:18:37 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt ATOF 3
36.Os
37.Sh NAME
38.Nm atof
39.Nd convert
40.Tn ASCII
41string to double
42.Sh SYNOPSIS
43.Fd #include <stdlib.h>
44.Ft double
45.Fn atof "const char *nptr"
46.Sh DESCRIPTION
47The
48.Fn atof
49function converts the initial portion of the string pointed to by
50.Fa nptr
51to
52.Li double
53representation.
54.Pp
55It is equivalent to:
56.Bd -literal -offset indent
57strtod(nptr, (char **)NULL);
58.Ed
59.Sh SEE ALSO
60.Xr atoi 3 ,
61.Xr atol 3 ,
62.Xr strtod 3 ,
63.Xr strtol 3 ,
64.Xr strtoul 3
65.Sh STANDARDS
66The
67.Fn atof
68function conforms to
69.St -ansiC .
diff --git a/src/lib/libc/stdlib/atof.c b/src/lib/libc/stdlib/atof.c
new file mode 100644
index 0000000000..d14b58b070
--- /dev/null
+++ b/src/lib/libc/stdlib/atof.c
@@ -0,0 +1,37 @@
1/* $OpenBSD: atof.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
2/*
3 * Copyright (c) 1988 The Regents of the University of California.
4 * 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
31#include <stdlib.h>
32
33double
34atof(const char *ascii)
35{
36 return(strtod(ascii, (char **)NULL));
37}
diff --git a/src/lib/libc/stdlib/atoi.3 b/src/lib/libc/stdlib/atoi.3
new file mode 100644
index 0000000000..dee8b637a3
--- /dev/null
+++ b/src/lib/libc/stdlib/atoi.3
@@ -0,0 +1,86 @@
1.\" Copyright (c) 1990, 1991, 1993
2.\" The Regents of the University of California. All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information
6.\" Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: atoi.3,v 1.8 2004/08/22 21:47:41 jaredy Exp $
33.\"
34.Dd June 4, 1993
35.Dt ATOI 3
36.Os
37.Sh NAME
38.Nm atoi
39.Nd convert
40.Tn ASCII
41string to integer
42.Sh SYNOPSIS
43.Fd #include <stdlib.h>
44.Ft int
45.Fn atoi "const char *nptr"
46.Sh DESCRIPTION
47The
48.Fn atoi
49function converts the initial portion of the string pointed to by
50.Fa nptr
51to
52.Li integer
53representation.
54.Pp
55It is equivalent to:
56.Bd -literal -offset indent
57(int)strtol(nptr, (char **)NULL, 10);
58.Ed
59.Sh SEE ALSO
60.Xr atof 3 ,
61.Xr atol 3 ,
62.Xr strtod 3 ,
63.Xr strtol 3 ,
64.Xr strtonum 3 ,
65.Xr strtoul 3
66.Sh STANDARDS
67The
68.Fn atoi
69function conforms to
70.St -ansiC .
71.Sh CAVEATS
72.Nm
73does no overflow checking, handles unsigned numbers poorly,
74and handles strings containing trailing extra characters
75(like
76.Dq "123abc" )
77poorly.
78Careful use of
79.Xr strtol 3
80and
81.Xr strtoul 3
82can alleviate these problems,
83but
84.Xr strtonum 3
85can be used to convert numbers from strings much more safely
86and easily.
diff --git a/src/lib/libc/stdlib/atoi.c b/src/lib/libc/stdlib/atoi.c
new file mode 100644
index 0000000000..b0842678e2
--- /dev/null
+++ b/src/lib/libc/stdlib/atoi.c
@@ -0,0 +1,37 @@
1/* $OpenBSD: atoi.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
2/*
3 * Copyright (c) 1988 Regents of the University of California.
4 * 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
31#include <stdlib.h>
32
33int
34atoi(const char *str)
35{
36 return((int)strtol(str, (char **)NULL, 10));
37}
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..1970804401
--- /dev/null
+++ b/src/lib/libc/stdlib/atol.c
@@ -0,0 +1,37 @@
1/* $OpenBSD: atol.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
2/*
3 * Copyright (c) 1988 Regents of the University of California.
4 * 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
31#include <stdlib.h>
32
33long
34atol(const char *str)
35{
36 return(strtol(str, (char **)NULL, 10));
37}
diff --git a/src/lib/libc/stdlib/atoll.3 b/src/lib/libc/stdlib/atoll.3
new file mode 100644
index 0000000000..2b53e9b694
--- /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.4 2005/07/26 04:20:23 jaredy 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 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..a65e682cfb
--- /dev/null
+++ b/src/lib/libc/stdlib/atoll.c
@@ -0,0 +1,38 @@
1/* $OpenBSD: atoll.c,v 1.3 2005/08/08 08:05:36 espie Exp $ */
2/*
3 * Copyright (c) 1988 Regents of the University of California.
4 * 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
31#include <stdlib.h>
32
33long long
34atoll(str)
35 const char *str;
36{
37 return(strtoll(str, (char **)NULL, 10));
38}
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..8193d27c60
--- /dev/null
+++ b/src/lib/libc/stdlib/bsearch.c
@@ -0,0 +1,67 @@
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#include <stdlib.h>
31
32/*
33 * Perform a binary search.
34 *
35 * The code below is a bit sneaky. After a comparison fails, we
36 * divide the work in half by moving either left or right. If lim
37 * is odd, moving left simply involves halving lim: e.g., when lim
38 * is 5 we look at item 2, so we change lim to 2 so that we will
39 * look at items 0 & 1. If lim is even, the same applies. If lim
40 * is odd, moving right again involes halving lim, this time moving
41 * the base up one item past p: e.g., when lim is 5 we change base
42 * to item 3 and make lim 2 so that we will look at items 3 and 4.
43 * If lim is even, however, we have to shrink it by one before
44 * halving: e.g., when lim is 4, we still looked at item 2, so we
45 * have to make lim 3, then halve, obtaining 1, so that we will only
46 * look at item 3.
47 */
48void *
49bsearch(const void *key, const void *base0, size_t nmemb, size_t size,
50 int (*compar)(const void *, const void *))
51{
52 const char *base = base0;
53 int lim, cmp;
54 const void *p;
55
56 for (lim = nmemb; lim != 0; lim >>= 1) {
57 p = base + (lim >> 1) * size;
58 cmp = (*compar)(key, p);
59 if (cmp == 0)
60 return ((void *)p);
61 if (cmp > 0) { /* key > p: move right */
62 base = (char *)p + size;
63 lim--;
64 } /* else move left */
65 }
66 return (NULL);
67}
diff --git a/src/lib/libc/stdlib/calloc.c b/src/lib/libc/stdlib/calloc.c
new file mode 100644
index 0000000000..43a0d1632c
--- /dev/null
+++ b/src/lib/libc/stdlib/calloc.c
@@ -0,0 +1,50 @@
1/* $OpenBSD: calloc.c,v 1.11 2006/04/02 18:22:14 otto Exp $ */
2/*-
3 * Copyright (c) 1990 The Regents of the University of California.
4 * 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
31#include <stdlib.h>
32#include <string.h>
33#include <limits.h>
34#include <errno.h>
35
36void *
37calloc(size_t num, size_t size)
38{
39 void *p;
40
41 if (num && SIZE_MAX / num < size) {
42 errno = ENOMEM;
43 return NULL;
44 }
45 size *= num;
46 p = malloc(size);
47 if (p)
48 memset(p, 0, size);
49 return(p);
50}
diff --git a/src/lib/libc/stdlib/cfree.c b/src/lib/libc/stdlib/cfree.c
new file mode 100644
index 0000000000..373c7ff75d
--- /dev/null
+++ b/src/lib/libc/stdlib/cfree.c
@@ -0,0 +1,40 @@
1/* $OpenBSD: cfree.c,v 1.5 2005/08/08 08:05:36 espie 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#include <sys/cdefs.h>
29#include <stdlib.h>
30
31#ifdef __indr_reference
32__indr_reference(free, cfree);
33#else
34
35void
36cfree(void *p)
37{
38 free(p);
39}
40#endif
diff --git a/src/lib/libc/stdlib/div.3 b/src/lib/libc/stdlib/div.3
new file mode 100644
index 0000000000..d6a9a0029d
--- /dev/null
+++ b/src/lib/libc/stdlib/div.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.
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.8 2006/01/13 17:58:09 millert Exp $
31.\"
32.Dd April 19, 1991
33.Dt DIV 3
34.Os
35.Sh NAME
36.Nm div
37.Nd return quotient and remainder from division
38.Sh SYNOPSIS
39.Fd #include <stdlib.h>
40.Ft div_t
41.Fn div "int num" "int denom"
42.Sh DESCRIPTION
43The
44.Fn div
45function computes the value
46.Fa num Ns / 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 imaxdiv 3 ,
57.Xr ldiv 3 ,
58.Xr lldiv 3 ,
59.Xr math 3 ,
60.Xr qdiv 3
61.Sh STANDARDS
62The
63.Fn div
64function conforms to
65.St -ansiC .
diff --git a/src/lib/libc/stdlib/div.c b/src/lib/libc/stdlib/div.c
new file mode 100644
index 0000000000..f7ac2db4b0
--- /dev/null
+++ b/src/lib/libc/stdlib/div.c
@@ -0,0 +1,71 @@
1/* $OpenBSD: div.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
2/*
3 * Copyright (c) 1990 Regents of the University of California.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * Chris Torek.
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
34#include <stdlib.h> /* div_t */
35
36div_t
37div(int num, int denom)
38{
39 div_t r;
40
41 r.quot = num / denom;
42 r.rem = num % denom;
43 /*
44 * The ANSI standard says that |r.quot| <= |n/d|, where
45 * n/d is to be computed in infinite precision. In other
46 * words, we should always truncate the quotient towards
47 * 0, never -infinity.
48 *
49 * Machine division and remainer may work either way when
50 * one or both of n or d is negative. If only one is
51 * negative and r.quot has been truncated towards -inf,
52 * r.rem will have the same sign as denom and the opposite
53 * sign of num; if both are negative and r.quot has been
54 * truncated towards -inf, r.rem will be positive (will
55 * have the opposite sign of num). These are considered
56 * `wrong'.
57 *
58 * If both are num and denom are positive, r will always
59 * be positive.
60 *
61 * This all boils down to:
62 * if num >= 0, but r.rem < 0, we got the wrong answer.
63 * In that case, to get the right answer, add 1 to r.quot and
64 * subtract denom from r.rem.
65 */
66 if (num >= 0 && r.rem < 0) {
67 r.quot++;
68 r.rem -= denom;
69 }
70 return (r);
71}
diff --git a/src/lib/libc/stdlib/drand48.c b/src/lib/libc/stdlib/drand48.c
new file mode 100644
index 0000000000..b6c046c831
--- /dev/null
+++ b/src/lib/libc/stdlib/drand48.c
@@ -0,0 +1,23 @@
1/* $OpenBSD: drand48.c,v 1.3 2005/08/08 08:05:36 espie Exp $ */
2/*
3 * Copyright (c) 1993 Martin Birgmeier
4 * All rights reserved.
5 *
6 * You may redistribute unmodified or modified versions of this source
7 * code provided that the above copyright notice and this and the
8 * following conditions are retained.
9 *
10 * This software is provided ``as is'', and comes with no warranties
11 * of any kind. I shall in no event be liable for anything that happens
12 * to anyone/anything when using this software.
13 */
14
15#include "rand48.h"
16
17extern unsigned short __rand48_seed[3];
18
19double
20drand48(void)
21{
22 return erand48(__rand48_seed);
23}
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..eb0e428996
--- /dev/null
+++ b/src/lib/libc/stdlib/ecvt.c
@@ -0,0 +1,99 @@
1/* $OpenBSD: ecvt.c,v 1.5 2006/01/10 16:18:37 millert Exp $ */
2
3/*
4 * Copyright (c) 2002, 2006 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#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26
27extern char *__dtoa(double, int, int, int *, int *, char **);
28static char *__cvt(double, int, int *, int *, int, int);
29
30static char *
31__cvt(double value, int ndigit, int *decpt, int *sign, int fmode, int pad)
32{
33 static char *s;
34 char *p, *rve;
35 size_t siz;
36
37 if (ndigit == 0) {
38 *sign = value < 0.0;
39 *decpt = 0;
40 return ("");
41 }
42
43 if (s) {
44 free(s);
45 s = NULL;
46 }
47
48 if (ndigit < 0)
49 siz = -ndigit + 1;
50 else
51 siz = ndigit + 1;
52
53
54 /* __dtoa() doesn't allocate space for 0 so we do it by hand */
55 if (value == 0.0) {
56 *decpt = 1 - fmode; /* 1 for 'e', 0 for 'f' */
57 *sign = 0;
58 if ((rve = s = (char *)malloc(siz)) == NULL)
59 return(NULL);
60 *rve++ = '0';
61 *rve = '\0';
62 } else {
63 p = __dtoa(value, fmode + 2, ndigit, decpt, sign, &rve);
64 if (*decpt == 9999) {
65 /* Infinity or Nan, convert to inf or nan like printf */
66 *decpt = 0;
67 return(*p == 'I' ? "inf" : "nan");
68 }
69 /* Make a local copy and adjust rve to be in terms of s */
70 if (pad && fmode)
71 siz += *decpt;
72 if ((s = (char *)malloc(siz)) == NULL)
73 return(NULL);
74 (void) strlcpy(s, p, siz);
75 rve = s + (rve - p);
76 }
77
78 /* Add trailing zeros */
79 if (pad) {
80 siz -= rve - s;
81 while (--siz)
82 *rve++ = '0';
83 *rve = '\0';
84 }
85
86 return(s);
87}
88
89char *
90ecvt(double value, int ndigit, int *decpt, int *sign)
91{
92 return(__cvt(value, ndigit, decpt, sign, 0, 1));
93}
94
95char *
96fcvt(double value, int ndigit, int *decpt, int *sign)
97{
98 return(__cvt(value, ndigit, decpt, sign, 1, 1));
99}
diff --git a/src/lib/libc/stdlib/erand48.c b/src/lib/libc/stdlib/erand48.c
new file mode 100644
index 0000000000..2ffeaa6e71
--- /dev/null
+++ b/src/lib/libc/stdlib/erand48.c
@@ -0,0 +1,24 @@
1/* $OpenBSD: erand48.c,v 1.3 2005/08/08 08:05:36 espie Exp $ */
2/*
3 * Copyright (c) 1993 Martin Birgmeier
4 * All rights reserved.
5 *
6 * You may redistribute unmodified or modified versions of this source
7 * code provided that the above copyright notice and this and the
8 * following conditions are retained.
9 *
10 * This software is provided ``as is'', and comes with no warranties
11 * of any kind. I shall in no event be liable for anything that happens
12 * to anyone/anything when using this software.
13 */
14
15#include "rand48.h"
16
17double
18erand48(unsigned short xseed[3])
19{
20 __dorand48(xseed);
21 return ldexp((double) xseed[0], -48) +
22 ldexp((double) xseed[1], -32) +
23 ldexp((double) xseed[2], -16);
24}
diff --git a/src/lib/libc/stdlib/exit.3 b/src/lib/libc/stdlib/exit.3
new file mode 100644
index 0000000000..fa233ac75f
--- /dev/null
+++ b/src/lib/libc/stdlib/exit.3
@@ -0,0 +1,114 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information
6.\" Processing Systems.
7.\"
8.\" Redistribution and use in source and binary forms, with or without
9.\" modification, are permitted provided that the following conditions
10.\" are met:
11.\" 1. Redistributions of source code must retain the above copyright
12.\" notice, this list of conditions and the following disclaimer.
13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution.
16.\" 3. Neither the name of the University nor the names of its contributors
17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $OpenBSD: exit.3,v 1.10 2004/05/03 17:21:13 millert Exp $
33.\"
34.Dd January 21, 2004
35.Dt EXIT 3
36.Os
37.Sh NAME
38.Nm exit, _Exit
39.Nd perform normal program termination
40.Sh SYNOPSIS
41.Fd #include <stdlib.h>
42.Ft void
43.Fn exit "int status"
44.Ft void
45.Fn _Exit "int status"
46.Sh DESCRIPTION
47The
48.Fn exit
49and
50.Fn _Exit
51functions terminate a process.
52.Pp
53Before termination,
54.Fn exit
55performs the following operations in the order listed:
56.Bl -enum -offset indent
57.It
58Call the functions registered with the
59.Xr atexit 3
60function, in the reverse order of their registration.
61.It
62Flush all open output streams.
63.It
64Close all open streams.
65.It
66Unlink all files created with the
67.Xr tmpfile 3
68function.
69.El
70.Pp
71The
72.Fn _Exit
73function terminates without calling the functions registered with the
74.Xr atexit 3
75function.
76The
77.Ox
78implementation of
79.Fn _Exit
80does not flush open output streams or unlink files created with the
81.Xr tmpfile 3
82function.
83However, this behavior is implementation-specific.
84.Pp
85Lastly,
86.Fn exit
87and
88.Fn _Exit
89call
90.Xr _exit 2 .
91Note that typically
92.Xr _exit 2
93only passes the lower 8 bits of
94.Fa status
95on to the parent, thus negative values have less meaning.
96.Sh RETURN VALUES
97The
98.Fn exit
99and
100.Fn _Exit
101functions never return.
102.Sh SEE ALSO
103.Xr _exit 2 ,
104.Xr atexit 3 ,
105.Xr intro 3 ,
106.Xr sysexits 3 ,
107.Xr tmpfile 3
108.Sh STANDARDS
109The
110.Fn exit
111and
112.Fn _Exit
113functions conform to
114.St -ansiC-99 .
diff --git a/src/lib/libc/stdlib/exit.c b/src/lib/libc/stdlib/exit.c
new file mode 100644
index 0000000000..90b7d5adc2
--- /dev/null
+++ b/src/lib/libc/stdlib/exit.c
@@ -0,0 +1,69 @@
1/* $OpenBSD: exit.c,v 1.11 2005/08/08 08:05:36 espie Exp $ */
2/*-
3 * Copyright (c) 1990 The Regents of the University of California.
4 * 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
31#include <sys/types.h>
32#include <sys/mman.h>
33#include <stdlib.h>
34#include <unistd.h>
35#include "atexit.h"
36#include "thread_private.h"
37
38/*
39 * This variable is zero until a process has created a thread.
40 * It is used to avoid calling locking functions in libc when they
41 * are not required. By default, libc is intended to be(come)
42 * thread-safe, but without a (significant) penalty to non-threaded
43 * processes.
44 */
45int __isthreaded = 0;
46
47/*
48 * Exit, flushing stdio buffers if necessary.
49 */
50void
51exit(int status)
52{
53 struct atexit *p, *q;
54 int n, pgsize = getpagesize();
55
56 if (!__atexit_invalid) {
57 p = __atexit;
58 while (p != NULL) {
59 for (n = p->ind; --n >= 0;)
60 if (p->fns[n] != NULL)
61 (*p->fns[n])();
62 q = p;
63 p = p->next;
64 munmap(q, pgsize);
65 }
66 }
67 /* cleanup, if registered, was called through fns[0] in the last page */
68 _exit(status);
69}
diff --git a/src/lib/libc/stdlib/gcvt.c b/src/lib/libc/stdlib/gcvt.c
new file mode 100644
index 0000000000..bc6295c03d
--- /dev/null
+++ b/src/lib/libc/stdlib/gcvt.c
@@ -0,0 +1,108 @@
1/* $OpenBSD: gcvt.c,v 1.9 2006/01/10 16:18:37 millert Exp $ */
2
3/*
4 * Copyright (c) 2002, 2003, 2006 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#include <locale.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27
28extern char *__dtoa(double, int, int, int *, int *, char **);
29
30char *
31gcvt(double value, int ndigit, char *buf)
32{
33 char *digits, *dst, *src;
34 int i, decpt, sign;
35 struct lconv *lconv;
36
37 lconv = localeconv();
38 if (ndigit == 0) {
39 buf[0] = '\0';
40 return (buf);
41 }
42
43 digits = __dtoa(value, 2, ndigit, &decpt, &sign, NULL);
44 if (decpt == 9999) {
45 /*
46 * Infinity or NaN, convert to inf or nan with sign.
47 * We assume the buffer is at least ndigit long.
48 */
49 snprintf(buf, ndigit + 1, "%s%s", sign ? "-" : "",
50 *digits == 'I' ? "inf" : "nan");
51 return (buf);
52 }
53
54 dst = buf;
55 if (sign)
56 *dst++ = '-';
57
58 if (decpt < 0 || decpt > ndigit) {
59 /* exponential format (e.g. 1.2345e+13) */
60 if (--decpt < 0) {
61 sign = 1;
62 decpt = -decpt;
63 } else
64 sign = 0;
65 src = digits;
66 *dst++ = *src++;
67 *dst++ = *lconv->decimal_point;
68 while (*src != '\0')
69 *dst++ = *src++;
70 *dst++ = 'e';
71 if (sign)
72 *dst++ = '-';
73 else
74 *dst++ = '+';
75 if (decpt < 10) {
76 *dst++ = '0';
77 *dst++ = '0' + decpt;
78 *dst = '\0';
79 } else {
80 /* XXX - optimize */
81 for (sign = decpt, i = 0; (sign /= 10) != 0; i++)
82 continue;
83 dst[i + 1] = '\0';
84 while (decpt != 0) {
85 dst[i--] = '0' + decpt % 10;
86 decpt /= 10;
87 }
88 }
89 } else {
90 /* standard format */
91 for (i = 0, src = digits; i < decpt; i++) {
92 if (*src != '\0')
93 *dst++ = *src++;
94 else
95 *dst++ = '0';
96 }
97 if (*src != '\0') {
98 if (src == digits)
99 *dst++ = '0'; /* zero before decimal point */
100 *dst++ = *lconv->decimal_point;
101 for (i = decpt; digits[i] != '\0'; i++) {
102 *dst++ = digits[i];
103 }
104 }
105 *dst = '\0';
106 }
107 return (buf);
108}
diff --git a/src/lib/libc/stdlib/getenv.3 b/src/lib/libc/stdlib/getenv.3
new file mode 100644
index 0000000000..f131bbf513
--- /dev/null
+++ b/src/lib/libc/stdlib/getenv.3
@@ -0,0 +1,148 @@
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.11 2005/07/26 04:20:23 jaredy 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 Er
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 function
134.Fn getenv
135appeared in
136.At v7
137and
138.Bx 3 .
139The functions
140.Fn setenv
141and
142.Fn unsetenv
143appeared in
144.Bx 4.3 Tahoe .
145The
146.Fn putenv
147function appeared in
148.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..72367b34e2
--- /dev/null
+++ b/src/lib/libc/stdlib/getenv.c
@@ -0,0 +1,80 @@
1/* $OpenBSD: getenv.c,v 1.8 2005/08/08 08:05:36 espie Exp $ */
2/*
3 * Copyright (c) 1987, 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
31#include <stdlib.h>
32#include <string.h>
33
34char *__findenv(const char *name, int *offset);
35
36/*
37 * __findenv --
38 * Returns pointer to value associated with name, if any, else NULL.
39 * Sets offset to be the offset of the name/value combination in the
40 * environmental array, for use by setenv(3) and unsetenv(3).
41 * Explicitly removes '=' in argument name.
42 *
43 * This routine *should* be a static; don't use it.
44 */
45char *
46__findenv(const char *name, int *offset)
47{
48 extern char **environ;
49 int len, i;
50 const char *np;
51 char **p, *cp;
52
53 if (name == NULL || environ == NULL)
54 return (NULL);
55 for (np = name; *np && *np != '='; ++np)
56 ;
57 len = np - name;
58 for (p = environ; (cp = *p) != NULL; ++p) {
59 for (np = name, i = len; i && *cp; i--)
60 if (*cp++ != *np++)
61 break;
62 if (i == 0 && *cp++ == '=') {
63 *offset = p - environ;
64 return (cp);
65 }
66 }
67 return (NULL);
68}
69
70/*
71 * getenv --
72 * Returns ptr to value associated with name, if any, else NULL.
73 */
74char *
75getenv(const char *name)
76{
77 int offset;
78
79 return (__findenv(name, &offset));
80}
diff --git a/src/lib/libc/stdlib/getopt.3 b/src/lib/libc/stdlib/getopt.3
new file mode 100644
index 0000000000..796541184f
--- /dev/null
+++ b/src/lib/libc/stdlib/getopt.3
@@ -0,0 +1,387 @@
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.38 2006/03/15 02:50:25 ray Exp $
29.\"
30.Dd December 17, 2002
31.Dt GETOPT 3
32.Os
33.Sh NAME
34.Nm getopt
35.Nd get option character from command line argument list
36.Sh SYNOPSIS
37.Fd #include <unistd.h>
38.Vt extern char *optarg;
39.Vt extern int opterr;
40.Vt extern int optind;
41.Vt extern int optopt;
42.Vt extern int optreset;
43.Ft int
44.Fn getopt "int argc" "char * const *argv" "const char *optstring"
45.Sh DESCRIPTION
46The
47.Fn getopt
48function incrementally parses a command line argument list
49.Fa argv
50and returns the next
51.Em known
52option character.
53An option character is
54.Em known
55if it has been specified in the string of accepted option characters,
56.Fa optstring .
57.Pp
58The option string
59.Fa optstring
60may contain the following elements: individual characters,
61characters followed by a colon, and characters followed by two colons.
62A character followed by a single colon indicates that an argument
63is to follow the option on the command line.
64Two colons indicates that the argument is optional \- this is an
65extension not covered by POSIX.
66For example, an option string
67.Qq x
68recognizes an option
69.Fl x ,
70and an option string
71.Qq Li x:
72recognizes an option and argument
73.Fl x Ar argument .
74It does not matter to
75.Fn getopt
76if a following argument has leading whitespace.
77.Pp
78On return from
79.Fn getopt ,
80.Va optarg
81points to an option argument, if it is anticipated,
82and the variable
83.Va optind
84contains the index to the next
85.Fa argv
86argument for a subsequent call
87to
88.Fn getopt .
89.Pp
90The variables
91.Va opterr
92and
93.Va optind
94are both initialized to 1.
95The
96.Va optind
97variable may be set to another value larger than 0 before a set of calls to
98.Fn getopt
99in order to skip over more or less
100.Fa argv
101entries.
102An
103.Va optind
104value of 0 is reserved for compatibility with GNU
105.Fn getopt .
106.Pp
107In order to use
108.Fn getopt
109to evaluate multiple sets of arguments, or to evaluate a single set of
110arguments multiple times,
111the variable
112.Va optreset
113must be set to 1 before the second and each additional set of calls to
114.Fn getopt ,
115and the variable
116.Va optind
117must be reinitialized.
118.Pp
119The
120.Fn getopt
121function returns \-1 when the argument list is exhausted.
122The interpretation of options in the argument list may be cancelled
123by the option
124.Ql --
125(double dash) which causes
126.Fn getopt
127to signal the end of argument processing and return \-1.
128When all options have been processed (i.e., up to the first non-option
129argument),
130.Fn getopt
131returns \-1.
132.Sh RETURN VALUES
133The
134.Fn getopt
135function returns the next known option character in
136.Fa optstring .
137If
138.Fn getopt
139encounters a character not found in
140.Fa optstring
141or if it detects a missing option argument,
142it returns
143.Sq \&?
144(question mark).
145If
146.Fa optstring
147has a leading
148.Sq \&:
149then a missing option argument causes
150.Sq \&:
151to be returned instead of
152.Sq \&? .
153In either case, the variable
154.Va optopt
155is set to the character that caused the error.
156The
157.Fn getopt
158function returns \-1 when the argument list is exhausted.
159.Sh ENVIRONMENT
160.Bl -tag -width POSIXLY_CORRECTXX
161.It Ev POSIXLY_CORRECT
162If set, a leading
163.Sq -
164in
165.Ar optstring
166is ignored.
167.El
168.Sh EXAMPLES
169The following code accepts the options
170.Fl b
171and
172.Fl f Ar argument
173and adjusts
174.Va argc
175and
176.Va argv
177after option argument processing has completed.
178.Bd -literal -offset indent
179int bflag, ch, fd;
180
181bflag = 0;
182while ((ch = getopt(argc, argv, "bf:")) != -1) {
183 switch (ch) {
184 case 'b':
185 bflag = 1;
186 break;
187 case 'f':
188 if ((fd = open(optarg, O_RDONLY, 0)) == -1)
189 err(1, "%s", optarg);
190 break;
191 default:
192 usage();
193 /* NOTREACHED */
194 }
195}
196argc -= optind;
197argv += optind;
198.Ed
199.Sh DIAGNOSTICS
200If the
201.Fn getopt
202function encounters a character not found in the string
203.Fa optstring
204or detects
205a missing option argument, it writes an error message to
206.Em stderr
207and returns
208.Ql \&? .
209Setting
210.Va opterr
211to a zero will disable these error messages.
212If
213.Fa optstring
214has a leading
215.Ql \&:
216then a missing option argument causes a
217.Ql \&:
218to be returned in addition to suppressing any error messages.
219.Pp
220Option arguments are allowed to begin with
221.Ql - ;
222this is reasonable but reduces the amount of error checking possible.
223.Sh SEE ALSO
224.Xr getopt 1 ,
225.Xr getopt_long 3 ,
226.Xr getsubopt 3
227.Sh STANDARDS
228The
229.Fn getopt
230function implements a superset of the functionality specified by
231.St -p1003.1 .
232.Pp
233The following extensions are supported:
234.Bl -tag -width "xxx"
235.It Li o
236The
237.Va optreset
238variable was added to make it possible to call the
239.Fn getopt
240function multiple times.
241.It Li o
242If the
243.Va optind
244variable is set to 0,
245.Fn getopt
246will behave as if the
247.Va optreset
248variable has been set.
249This is for compatibility with
250.Tn GNU
251.Fn getopt .
252New code should use
253.Va optreset
254instead.
255.It Li o
256If the first character of
257.Fa optstring
258is a plus sign
259.Pq Ql + ,
260it will be ignored.
261This is for compatibility with
262.Tn GNU
263.Fn getopt .
264.It Li o
265If the first character of
266.Fa optstring
267is a dash
268.Pq Ql - ,
269non-options will be returned as arguments to the option character
270.Ql \e1 .
271This is for compatibility with
272.Tn GNU
273.Fn getopt .
274.It Li o
275A single dash
276.Pq Ql -
277may be specified as a character in
278.Fa optstring ,
279however it should
280.Em never
281have an argument associated with it.
282This allows
283.Fn getopt
284to be used with programs that expect
285.Ql -
286as an option flag.
287This practice is wrong, and should not be used in any current development.
288It is provided for backward compatibility
289.Em only .
290Care should be taken not to use
291.Ql -
292as the first character in
293.Fa optstring
294to avoid a semantic conflict with
295.Tn GNU
296.Fn getopt
297semantics (see above).
298By default, a single dash causes
299.Fn getopt
300to return \-1.
301.El
302.Pp
303Unlike
304.Tn GNU
305.Fn getopt ,
306.Ox
307does not permute the argument vector to allow non-options to be
308interspersed with options on the command line.
309Programs requiring this behavior should use
310.Xr getopt_long 3
311instead.
312Because of this (and unlike
313.Tn GNU ) ,
314the
315.Ox
316.Fn getopt
317supports optional arguments separated by whitespace.
318.Pp
319Historic
320.Bx
321versions of
322.Fn getopt
323set
324.Fa optopt
325to the last option character processed.
326However, this conflicts with
327.St -p1003.1
328which stipulates that
329.Fa optopt
330be set to the last character that caused an error.
331.Sh HISTORY
332The
333.Fn getopt
334function appeared in
335.Bx 4.3 .
336.Sh BUGS
337The
338.Fn getopt
339function was once specified to return
340.Dv EOF
341instead of \-1.
342This was changed by
343.St -p1003.2-92
344to decouple
345.Fn getopt
346from
347.Aq Pa stdio.h .
348.Pp
349It is possible to handle digits as option letters.
350This allows
351.Fn getopt
352to be used with programs that expect a number
353.Pq Dq Li \-3
354as an option.
355This practice is wrong, and should not be used in any current development.
356It is provided for backward compatibility
357.Em only .
358The following code fragment works in most cases and can handle mixed
359number and letter arguments.
360.Bd -literal -offset indent
361int aflag = 0, bflag = 0, ch, lastch = '\e0';
362int length = -1, newarg = 1, prevoptind = 1;
363
364while ((ch = getopt(argc, argv, "0123456789ab")) != -1) {
365 switch (ch) {
366 case '0': case '1': case '2': case '3': case '4':
367 case '5': case '6': case '7': case '8': case '9':
368 if (newarg || !isdigit(lastch))
369 length = 0;
370 else if (length > INT_MAX / 10)
371 usage();
372 length = (length * 10) + (ch - '0');
373 break;
374 case 'a':
375 aflag = 1;
376 break;
377 case 'b':
378 bflag = 1;
379 break;
380 default:
381 usage();
382 }
383 lastch = ch;
384 newarg = optind != prevoptind;
385 prevoptind = optind;
386}
387.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..bf5ba22ece
--- /dev/null
+++ b/src/lib/libc/stdlib/getopt_long.3
@@ -0,0 +1,459 @@
1.\" $OpenBSD: getopt_long.3,v 1.12 2005/10/11 01:23:41 jaredy 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 -offset indent
82$ myprogram --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 -offset indent
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.Pp
118.Bl -tag -width "optional_argument" -compact -offset indent
119.It Dv no_argument
120no argument to the option is expected.
121.It Dv required_argument
122an argument to the option is required.
123.It Dv optional_argument
124an argument to the option may be presented.
125.El
126.Pp
127If
128.Fa flag
129is not
130.Dv NULL ,
131then the integer pointed to by it will be set to the value in the
132.Fa val
133field.
134If the
135.Fa flag
136field is
137.Dv NULL ,
138then the
139.Fa val
140field will be returned.
141Setting
142.Fa flag
143to
144.Dv NULL
145and setting
146.Fa val
147to the corresponding short option will make this function act just
148like
149.Xr getopt 3 .
150.Pp
151If the
152.Fa longindex
153field is not
154.Dv NULL ,
155then the integer pointed to by it will be set to the index of the long
156option relative to
157.Fa longopts .
158.Pp
159The last element of the
160.Fa longopts
161array has to be filled with zeroes.
162.Pp
163The
164.Fn getopt_long_only
165function behaves identically to
166.Fn getopt_long
167with the exception that long options may start with
168.Sq -
169in addition to
170.Sq -- .
171If an option starting with
172.Sq -
173does not match a long option but does match a single-character option,
174the single-character option is returned.
175.Sh RETURN VALUES
176If the
177.Fa flag
178field in
179.Li struct option
180is
181.Dv NULL ,
182.Fn getopt_long
183and
184.Fn getopt_long_only
185return the value specified in the
186.Fa val
187field, which is usually just the corresponding short option.
188If
189.Fa flag
190is not
191.Dv NULL ,
192these functions return 0 and store
193.Fa val
194in the location pointed to by
195.Fa flag .
196These functions return
197.Sq \:
198if there was a missing option argument,
199.Sq \&?
200if the user specified an unknown or ambiguous option, and
201\-1 when the argument list has been exhausted.
202.Sh EXAMPLES
203.Bd -literal -compact
204int bflag, ch, fd;
205int daggerset;
206
207/* options descriptor */
208static struct option longopts[] = {
209 { "buffy", no_argument, NULL, 'b' },
210 { "fluoride", required_argument, NULL, 'f' },
211 { "daggerset", no_argument, &daggerset, 1 },
212 { NULL, 0, NULL, 0 }
213};
214
215bflag = 0;
216while ((ch = getopt_long(argc, argv, "bf:", longopts, NULL)) != -1)
217 switch (ch) {
218 case 'b':
219 bflag = 1;
220 break;
221 case 'f':
222 if ((fd = open(optarg, O_RDONLY, 0)) == -1)
223 err(1, "unable to open %s", optarg);
224 break;
225 case 0:
226 if (daggerset)
227 fprintf(stderr, "Buffy will use her dagger to "
228 "apply fluoride to dracula's teeth\en");
229 break;
230 default:
231 usage();
232 /* NOTREACHED */
233 }
234argc -= optind;
235argv += optind;
236.Ed
237.Sh IMPLEMENTATION DIFFERENCES
238This section describes differences to the GNU implementation
239found in glibc-2.1.3:
240.Bl -bullet
241.It
242handling of
243.Ql -
244as the first character of the option string in the presence of the
245environment variable
246.Ev POSIXLY_CORRECT :
247.Bl -tag -width "OpenBSD"
248.It GNU
249ignores
250.Ev POSIXLY_CORRECT
251and returns non-options as arguments to option
252.Ql \e1 .
253.It OpenBSD
254honors
255.Ev POSIXLY_CORRECT
256and stops at the first non-option.
257.El
258.It
259handling of
260.Ql -
261within the option string (not the first character):
262.Bl -tag -width "OpenBSD"
263.It GNU
264treats a
265.Ql -
266on the command line as a non-argument.
267.It OpenBSD
268a
269.Ql -
270within the option string matches a
271.Ql -
272(single dash) on the command line.
273This functionality is provided for backward compatibility with
274programs, such as
275.Xr su 1 ,
276that use
277.Ql -
278as an option flag.
279This practice is wrong, and should not be used in any current development.
280.El
281.It
282handling of
283.Ql ::
284in the option string in the presence of
285.Ev POSIXLY_CORRECT :
286.Bl -tag -width "OpenBSD"
287.It Both
288GNU and
289.Ox
290ignore
291.Ev POSIXLY_CORRECT
292here and take
293.Ql ::
294to mean the preceding option takes an optional argument.
295.El
296.It
297return value in case of missing argument if first character
298(after
299.Ql +
300or
301.Ql - )
302in the option string is not
303.Ql \&: :
304.Bl -tag -width "OpenBSD"
305.It GNU
306returns
307.Ql \&?
308.It OpenBSD
309returns
310.Ql \&:
311(since
312.Ox Ns 's
313.Xr getopt 3
314does).
315.El
316.It
317handling of
318.Ql --a
319in
320.Xr getopt 3 :
321.Bl -tag -width "OpenBSD"
322.It GNU
323parses this as option
324.Ql - ,
325option
326.Ql a .
327.It OpenBSD
328parses this as
329.Ql -- ,
330and returns \-1 (ignoring the
331.Ql a )
332(because the original
333.Fn getopt
334did.)
335.El
336.It
337setting of
338.Va optopt
339for long options with
340.Va flag
341.No non- Ns Dv NULL :
342.Bl -tag -width "OpenBSD"
343.It GNU
344sets
345.Va optopt
346to
347.Va val .
348.It OpenBSD
349sets
350.Va optopt
351to 0 (since
352.Va val
353would never be returned).
354.El
355.It
356handling of
357.Ql -W
358with
359.Ql W;
360in the option string in
361.Xr getopt 3
362(not
363.Fn getopt_long ) :
364.Bl -tag -width "OpenBSD"
365.It GNU
366causes a segmentation fault.
367.It OpenBSD
368no special handling is done;
369.Ql W;
370is interpreted as two separate options, neither of which take an argument.
371.El
372.It
373setting of
374.Va optarg
375for long options without an argument that are invoked via
376.Ql -W
377(with
378.Ql W;
379in the option string):
380.Bl -tag -width "OpenBSD"
381.It GNU
382sets
383.Va optarg
384to the option name (the argument of
385.Ql -W ) .
386.It OpenBSD
387sets
388.Va optarg
389to
390.Dv NULL
391(the argument of the long option).
392.El
393.It
394handling of
395.Ql -W
396with an argument that is not (a prefix to) a known long option
397(with
398.Ql W;
399in the option string):
400.Bl -tag -width "OpenBSD"
401.It GNU
402returns
403.Ql -W
404with
405.Va optarg
406set to the unknown option.
407.It OpenBSD
408treats this as an error (unknown option) and returns
409.Ql \&?
410with
411.Va optopt
412set to 0 and
413.Va optarg
414set to
415.Dv NULL
416(as GNU's man page documents).
417.El
418.It
419The error messages are different.
420.It
421.Ox
422does not permute the argument vector at the same points in
423the calling sequence as GNU does.
424The aspects normally used by the caller
425(ordering after \-1 is returned, value of
426.Va optind
427relative to current positions) are the same, though.
428(We do fewer variable swaps.)
429.El
430.Sh ENVIRONMENT
431.Bl -tag -width Ev
432.It Ev POSIXLY_CORRECT
433If set, option processing stops when the first non-option is found and
434a leading
435.Sq -
436or
437.Sq +
438in the
439.Ar optstring
440is ignored.
441.El
442.Sh SEE ALSO
443.Xr getopt 3
444.Sh HISTORY
445The
446.Fn getopt_long
447and
448.Fn getopt_long_only
449functions first appeared in GNU libiberty.
450This implementation first appeared in
451.Ox 3.3 .
452.Sh BUGS
453The
454.Ar argv
455argument is not really
456.Dv const
457as its elements may be permuted (unless
458.Ev POSIXLY_CORRECT
459is 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..41b6cd9f8d
--- /dev/null
+++ b/src/lib/libc/stdlib/getopt_long.c
@@ -0,0 +1,533 @@
1/* $OpenBSD: getopt_long.c,v 1.20 2005/10/25 15:49:37 jmc 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#include <err.h>
60#include <errno.h>
61#include <getopt.h>
62#include <stdlib.h>
63#include <string.h>
64
65#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */
66
67#ifdef REPLACE_GETOPT
68int opterr = 1; /* if error message should be printed */
69int optind = 1; /* index into parent argv vector */
70int optopt = '?'; /* character checked for validity */
71int optreset; /* reset getopt */
72char *optarg; /* argument associated with option */
73#endif
74
75#define PRINT_ERROR ((opterr) && (*options != ':'))
76
77#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
78#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
79#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
80
81/* return values */
82#define BADCH (int)'?'
83#define BADARG ((*options == ':') ? (int)':' : (int)'?')
84#define INORDER (int)1
85
86#define EMSG ""
87
88static int getopt_internal(int, char * const *, const char *,
89 const struct option *, int *, int);
90static int parse_long_options(char * const *, const char *,
91 const struct option *, int *, int);
92static int gcd(int, int);
93static void permute_args(int, int, int, char * const *);
94
95static char *place = EMSG; /* option letter processing */
96
97/* XXX: set optreset to 1 rather than these two */
98static int nonopt_start = -1; /* first non option argument (for permute) */
99static int nonopt_end = -1; /* first option after non options (for permute) */
100
101/* Error messages */
102static const char recargchar[] = "option requires an argument -- %c";
103static const char recargstring[] = "option requires an argument -- %s";
104static const char ambig[] = "ambiguous option -- %.*s";
105static const char noarg[] = "option doesn't take an argument -- %.*s";
106static const char illoptchar[] = "unknown option -- %c";
107static const char illoptstring[] = "unknown option -- %s";
108
109/*
110 * Compute the greatest common divisor of a and b.
111 */
112static int
113gcd(int a, int b)
114{
115 int c;
116
117 c = a % b;
118 while (c != 0) {
119 a = b;
120 b = c;
121 c = a % b;
122 }
123
124 return (b);
125}
126
127/*
128 * Exchange the block from nonopt_start to nonopt_end with the block
129 * from nonopt_end to opt_end (keeping the same order of arguments
130 * in each block).
131 */
132static void
133permute_args(int panonopt_start, int panonopt_end, int opt_end,
134 char * const *nargv)
135{
136 int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
137 char *swap;
138
139 /*
140 * compute lengths of blocks and number and size of cycles
141 */
142 nnonopts = panonopt_end - panonopt_start;
143 nopts = opt_end - panonopt_end;
144 ncycle = gcd(nnonopts, nopts);
145 cyclelen = (opt_end - panonopt_start) / ncycle;
146
147 for (i = 0; i < ncycle; i++) {
148 cstart = panonopt_end+i;
149 pos = cstart;
150 for (j = 0; j < cyclelen; j++) {
151 if (pos >= panonopt_end)
152 pos -= nnonopts;
153 else
154 pos += nopts;
155 swap = nargv[pos];
156 /* LINTED const cast */
157 ((char **) nargv)[pos] = nargv[cstart];
158 /* LINTED const cast */
159 ((char **)nargv)[cstart] = swap;
160 }
161 }
162}
163
164/*
165 * parse_long_options --
166 * Parse long options in argc/argv argument vector.
167 * Returns -1 if short_too is set and the option does not match long_options.
168 */
169static int
170parse_long_options(char * const *nargv, const char *options,
171 const struct option *long_options, int *idx, int short_too)
172{
173 char *current_argv, *has_equal;
174 size_t current_argv_len;
175 int i, match;
176
177 current_argv = place;
178 match = -1;
179
180 optind++;
181
182 if ((has_equal = strchr(current_argv, '=')) != NULL) {
183 /* argument found (--option=arg) */
184 current_argv_len = has_equal - current_argv;
185 has_equal++;
186 } else
187 current_argv_len = strlen(current_argv);
188
189 for (i = 0; long_options[i].name; i++) {
190 /* find matching long option */
191 if (strncmp(current_argv, long_options[i].name,
192 current_argv_len))
193 continue;
194
195 if (strlen(long_options[i].name) == current_argv_len) {
196 /* exact match */
197 match = i;
198 break;
199 }
200 /*
201 * If this is a known short option, don't allow
202 * a partial match of a single character.
203 */
204 if (short_too && current_argv_len == 1)
205 continue;
206
207 if (match == -1) /* partial match */
208 match = i;
209 else {
210 /* ambiguous abbreviation */
211 if (PRINT_ERROR)
212 warnx(ambig, (int)current_argv_len,
213 current_argv);
214 optopt = 0;
215 return (BADCH);
216 }
217 }
218 if (match != -1) { /* option found */
219 if (long_options[match].has_arg == no_argument
220 && has_equal) {
221 if (PRINT_ERROR)
222 warnx(noarg, (int)current_argv_len,
223 current_argv);
224 /*
225 * XXX: GNU sets optopt to val regardless of flag
226 */
227 if (long_options[match].flag == NULL)
228 optopt = long_options[match].val;
229 else
230 optopt = 0;
231 return (BADARG);
232 }
233 if (long_options[match].has_arg == required_argument ||
234 long_options[match].has_arg == optional_argument) {
235 if (has_equal)
236 optarg = has_equal;
237 else if (long_options[match].has_arg ==
238 required_argument) {
239 /*
240 * optional argument doesn't use next nargv
241 */
242 optarg = nargv[optind++];
243 }
244 }
245 if ((long_options[match].has_arg == required_argument)
246 && (optarg == NULL)) {
247 /*
248 * Missing argument; leading ':' indicates no error
249 * should be generated.
250 */
251 if (PRINT_ERROR)
252 warnx(recargstring,
253 current_argv);
254 /*
255 * XXX: GNU sets optopt to val regardless of flag
256 */
257 if (long_options[match].flag == NULL)
258 optopt = long_options[match].val;
259 else
260 optopt = 0;
261 --optind;
262 return (BADARG);
263 }
264 } else { /* unknown option */
265 if (short_too) {
266 --optind;
267 return (-1);
268 }
269 if (PRINT_ERROR)
270 warnx(illoptstring, current_argv);
271 optopt = 0;
272 return (BADCH);
273 }
274 if (idx)
275 *idx = match;
276 if (long_options[match].flag) {
277 *long_options[match].flag = long_options[match].val;
278 return (0);
279 } else
280 return (long_options[match].val);
281}
282
283/*
284 * getopt_internal --
285 * Parse argc/argv argument vector. Called by user level routines.
286 */
287static int
288getopt_internal(int nargc, char * const *nargv, const char *options,
289 const struct option *long_options, int *idx, int flags)
290{
291 char *oli; /* option letter list index */
292 int optchar, short_too;
293 static int posixly_correct = -1;
294
295 if (options == NULL)
296 return (-1);
297
298 /*
299 * Disable GNU extensions if POSIXLY_CORRECT is set or options
300 * string begins with a '+'.
301 */
302 if (posixly_correct == -1)
303 posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
304 if (posixly_correct || *options == '+')
305 flags &= ~FLAG_PERMUTE;
306 else if (*options == '-')
307 flags |= FLAG_ALLARGS;
308 if (*options == '+' || *options == '-')
309 options++;
310
311 /*
312 * XXX Some GNU programs (like cvs) set optind to 0 instead of
313 * XXX using optreset. Work around this braindamage.
314 */
315 if (optind == 0)
316 optind = optreset = 1;
317
318 optarg = NULL;
319 if (optreset)
320 nonopt_start = nonopt_end = -1;
321start:
322 if (optreset || !*place) { /* update scanning pointer */
323 optreset = 0;
324 if (optind >= nargc) { /* end of argument vector */
325 place = EMSG;
326 if (nonopt_end != -1) {
327 /* do permutation, if we have to */
328 permute_args(nonopt_start, nonopt_end,
329 optind, nargv);
330 optind -= nonopt_end - nonopt_start;
331 }
332 else if (nonopt_start != -1) {
333 /*
334 * If we skipped non-options, set optind
335 * to the first of them.
336 */
337 optind = nonopt_start;
338 }
339 nonopt_start = nonopt_end = -1;
340 return (-1);
341 }
342 if (*(place = nargv[optind]) != '-' ||
343 (place[1] == '\0' && strchr(options, '-') == NULL)) {
344 place = EMSG; /* found non-option */
345 if (flags & FLAG_ALLARGS) {
346 /*
347 * GNU extension:
348 * return non-option as argument to option 1
349 */
350 optarg = nargv[optind++];
351 return (INORDER);
352 }
353 if (!(flags & FLAG_PERMUTE)) {
354 /*
355 * If no permutation wanted, stop parsing
356 * at first non-option.
357 */
358 return (-1);
359 }
360 /* do permutation */
361 if (nonopt_start == -1)
362 nonopt_start = optind;
363 else if (nonopt_end != -1) {
364 permute_args(nonopt_start, nonopt_end,
365 optind, nargv);
366 nonopt_start = optind -
367 (nonopt_end - nonopt_start);
368 nonopt_end = -1;
369 }
370 optind++;
371 /* process next argument */
372 goto start;
373 }
374 if (nonopt_start != -1 && nonopt_end == -1)
375 nonopt_end = optind;
376
377 /*
378 * If we have "-" do nothing, if "--" we are done.
379 */
380 if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
381 optind++;
382 place = EMSG;
383 /*
384 * We found an option (--), so if we skipped
385 * non-options, we have to permute.
386 */
387 if (nonopt_end != -1) {
388 permute_args(nonopt_start, nonopt_end,
389 optind, nargv);
390 optind -= nonopt_end - nonopt_start;
391 }
392 nonopt_start = nonopt_end = -1;
393 return (-1);
394 }
395 }
396
397 /*
398 * Check long options if:
399 * 1) we were passed some
400 * 2) the arg is not just "-"
401 * 3) either the arg starts with -- we are getopt_long_only()
402 */
403 if (long_options != NULL && place != nargv[optind] &&
404 (*place == '-' || (flags & FLAG_LONGONLY))) {
405 short_too = 0;
406 if (*place == '-')
407 place++; /* --foo long option */
408 else if (*place != ':' && strchr(options, *place) != NULL)
409 short_too = 1; /* could be short option too */
410
411 optchar = parse_long_options(nargv, options, long_options,
412 idx, short_too);
413 if (optchar != -1) {
414 place = EMSG;
415 return (optchar);
416 }
417 }
418
419 if ((optchar = (int)*place++) == (int)':' ||
420 optchar == (int)'-' && *place != '\0' ||
421 (oli = strchr(options, optchar)) == NULL) {
422 /*
423 * If the user specified "-" and '-' isn't listed in
424 * options, return -1 (non-option) as per POSIX.
425 * Otherwise, it is an unknown option character (or ':').
426 */
427 if (optchar == (int)'-' && *place == '\0')
428 return (-1);
429 if (!*place)
430 ++optind;
431 if (PRINT_ERROR)
432 warnx(illoptchar, optchar);
433 optopt = optchar;
434 return (BADCH);
435 }
436 if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
437 /* -W long-option */
438 if (*place) /* no space */
439 /* NOTHING */;
440 else if (++optind >= nargc) { /* no arg */
441 place = EMSG;
442 if (PRINT_ERROR)
443 warnx(recargchar, optchar);
444 optopt = optchar;
445 return (BADARG);
446 } else /* white space */
447 place = nargv[optind];
448 optchar = parse_long_options(nargv, options, long_options,
449 idx, 0);
450 place = EMSG;
451 return (optchar);
452 }
453 if (*++oli != ':') { /* doesn't take argument */
454 if (!*place)
455 ++optind;
456 } else { /* takes (optional) argument */
457 optarg = NULL;
458 if (*place) /* no white space */
459 optarg = place;
460 /* XXX: disable test for :: if PC? (GNU doesn't) */
461 else if (oli[1] != ':') { /* arg not optional */
462 if (++optind >= nargc) { /* no arg */
463 place = EMSG;
464 if (PRINT_ERROR)
465 warnx(recargchar, optchar);
466 optopt = optchar;
467 return (BADARG);
468 } else
469 optarg = nargv[optind];
470 } else if (!(flags & FLAG_PERMUTE)) {
471 /*
472 * If permutation is disabled, we can accept an
473 * optional arg separated by whitespace so long
474 * as it does not start with a dash (-).
475 */
476 if (optind + 1 < nargc && *nargv[optind + 1] != '-')
477 optarg = nargv[++optind];
478 }
479 place = EMSG;
480 ++optind;
481 }
482 /* dump back option letter */
483 return (optchar);
484}
485
486#ifdef REPLACE_GETOPT
487/*
488 * getopt --
489 * Parse argc/argv argument vector.
490 *
491 * [eventually this will replace the BSD getopt]
492 */
493int
494getopt(int nargc, char * const *nargv, const char *options)
495{
496
497 /*
498 * We don't pass FLAG_PERMUTE to getopt_internal() since
499 * the BSD getopt(3) (unlike GNU) has never done this.
500 *
501 * Furthermore, since many privileged programs call getopt()
502 * before dropping privileges it makes sense to keep things
503 * as simple (and bug-free) as possible.
504 */
505 return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
506}
507#endif /* REPLACE_GETOPT */
508
509/*
510 * getopt_long --
511 * Parse argc/argv argument vector.
512 */
513int
514getopt_long(int nargc, char * const *nargv, const char *options,
515 const struct option *long_options, int *idx)
516{
517
518 return (getopt_internal(nargc, nargv, options, long_options, idx,
519 FLAG_PERMUTE));
520}
521
522/*
523 * getopt_long_only --
524 * Parse argc/argv argument vector.
525 */
526int
527getopt_long_only(int nargc, char * const *nargv, const char *options,
528 const struct option *long_options, int *idx)
529{
530
531 return (getopt_internal(nargc, nargv, options, long_options, idx,
532 FLAG_PERMUTE|FLAG_LONGONLY));
533}
diff --git a/src/lib/libc/stdlib/getsubopt.3 b/src/lib/libc/stdlib/getsubopt.3
new file mode 100644
index 0000000000..6a7c28ff4d
--- /dev/null
+++ b/src/lib/libc/stdlib/getsubopt.3
@@ -0,0 +1,145 @@
1.\" $OpenBSD: getsubopt.3,v 1.11 2005/10/11 01:23:41 jaredy Exp $
2.\"
3.\" Copyright (c) 1990, 1991, 1993
4.\" The Regents of the University of California. All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. Neither the name of the University nor the names of its contributors
15.\" may be used to endorse or promote products derived from this software
16.\" without specific prior written permission.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28.\" SUCH DAMAGE.
29.\"
30.\" @(#)getsubopt.3 8.1 (Berkeley) 6/9/93
31.\"
32.Dd June 9, 1993
33.Dt GETSUBOPT 3
34.Os
35.Sh NAME
36.Nm getsubopt
37.Nd get sub options from an argument
38.Sh SYNOPSIS
39.Fd #include <stdlib.h>
40.Vt extern char *suboptarg;
41.Ft int
42.Fn getsubopt "char **optionp" "char * const *tokens" "char **valuep"
43.Sh DESCRIPTION
44The
45.Fn getsubopt
46function parses a string containing tokens delimited by one or more
47tab, space, or comma
48.Pq Ql \&,
49characters.
50It is intended for use in parsing groups of option arguments provided
51as part of a utility command line.
52.Pp
53The argument
54.Fa optionp
55is a pointer to a pointer to the string.
56The argument
57.Fa tokens
58is a pointer to a null-terminated array of pointers to strings.
59.Pp
60The
61.Fn getsubopt
62function returns the zero-based offset of the pointer in the
63.Fa tokens
64array referencing a string which matches the first token
65in the string, or \-1 if the string contains no tokens or
66.Fa tokens
67does not contain a matching string.
68.Pp
69If the token is of the form
70.Ar name Ns = Ns Ar value ,
71the location referenced by
72.Fa valuep
73will be set to point to the start of the
74.Dq value
75portion of the token.
76.Pp
77On return from
78.Fn getsubopt ,
79.Fa optionp
80will be set to point to the start of the next token in the string,
81or the NUL at the end of the string if no more tokens are present.
82The external variable
83.Fa suboptarg
84will be set to point to the start of the current token, or
85.Dv NULL
86if no tokens were present.
87The argument
88.Fa valuep
89will be set to point to the value portion of the token, or
90.Dv NULL
91if no value portion was present.
92.Sh EXAMPLES
93.Bd -literal
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 }
134 break;
135 }
136}
137.Ed
138.Sh SEE ALSO
139.Xr getopt 3 ,
140.Xr strsep 3
141.Sh HISTORY
142The
143.Fn getsubopt
144function first appeared in
145.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..735c85ba8a
--- /dev/null
+++ b/src/lib/libc/stdlib/getsubopt.c
@@ -0,0 +1,92 @@
1/* $OpenBSD: getsubopt.c,v 1.4 2005/08/08 08:05:36 espie 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#include <unistd.h>
33#include <stdlib.h>
34#include <string.h>
35
36/*
37 * The SVID interface to getsubopt provides no way of figuring out which
38 * part of the suboptions list wasn't matched. This makes error messages
39 * tricky... The extern variable suboptarg is a pointer to the token
40 * which didn't match.
41 */
42char *suboptarg;
43
44int
45getsubopt(char **optionp, char * const *tokens, char **valuep)
46{
47 int cnt;
48 char *p;
49
50 suboptarg = *valuep = NULL;
51
52 if (!optionp || !*optionp)
53 return(-1);
54
55 /* skip leading white-space, commas */
56 for (p = *optionp; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p);
57
58 if (!*p) {
59 *optionp = p;
60 return(-1);
61 }
62
63 /* save the start of the token, and skip the rest of the token. */
64 for (suboptarg = p;
65 *++p && *p != ',' && *p != '=' && *p != ' ' && *p != '\t';);
66
67 if (*p) {
68 /*
69 * If there's an equals sign, set the value pointer, and
70 * skip over the value part of the token. Terminate the
71 * token.
72 */
73 if (*p == '=') {
74 *p = '\0';
75 for (*valuep = ++p;
76 *p && *p != ',' && *p != ' ' && *p != '\t'; ++p);
77 if (*p)
78 *p++ = '\0';
79 } else
80 *p++ = '\0';
81 /* Skip any whitespace or commas after this token. */
82 for (; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p);
83 }
84
85 /* set optionp for next round. */
86 *optionp = p;
87
88 for (cnt = 0; *tokens; ++tokens, ++cnt)
89 if (!strcmp(suboptarg, *tokens))
90 return(cnt);
91 return(-1);
92}
diff --git a/src/lib/libc/stdlib/hcreate.3 b/src/lib/libc/stdlib/hcreate.3
new file mode 100644
index 0000000000..66b1dd126d
--- /dev/null
+++ b/src/lib/libc/stdlib/hcreate.3
@@ -0,0 +1,191 @@
1.\" $OpenBSD: hcreate.3,v 1.3 2006/01/30 19:50:41 jmc Exp $
2.\" $NetBSD: hcreate.3,v 1.6 2003/04/16 13:34:46 wiz Exp $
3.\"
4.\" Copyright (c) 1999 The NetBSD Foundation, Inc.
5.\" All rights reserved.
6.\"
7.\" This code is derived from software contributed to The NetBSD Foundation
8.\" by Klaus Klein.
9.\"
10.\" Redistribution and use in source and binary forms, with or without
11.\" modification, are permitted provided that the following conditions
12.\" are met:
13.\" 1. Redistributions of source code must retain the above copyright
14.\" notice, this list of conditions and the following disclaimer.
15.\" 2. Redistributions in binary form must reproduce the above copyright
16.\" notice, this list of conditions and the following disclaimer in the
17.\" documentation and/or other materials provided with the distribution.
18.\" 3. All advertising materials mentioning features or use of this software
19.\" must display the following acknowledgement:
20.\" This product includes software developed by the NetBSD
21.\" Foundation, Inc. and its contributors.
22.\" 4. Neither the name of The NetBSD Foundation nor the names of its
23.\" contributors may be used to endorse or promote products derived
24.\" from this software without specific prior written permission.
25.\"
26.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36.\" POSSIBILITY OF SUCH DAMAGE.
37.\"
38.Dd February 13, 2001
39.Dt HCREATE 3
40.Os
41.Sh NAME
42.Nm hcreate ,
43.Nm hdestroy ,
44.Nm hsearch
45.Nd manage hash search table
46.Sh SYNOPSIS
47.In search.h
48.Ft int
49.Fn hcreate "size_t nel"
50.Ft void
51.Fn hdestroy "void"
52.Ft ENTRY *
53.Fn hsearch "ENTRY item" "ACTION action"
54.Sh DESCRIPTION
55The
56.Fn hcreate ,
57.Fn hdestroy ,
58and
59.Fn hsearch
60functions manage hash search tables.
61.Pp
62The
63.Fn hcreate
64function allocates and initializes the table.
65The
66.Fa nel
67argument specifies an estimate of the maximum number of entries to be held
68by the table.
69Unless further memory allocation fails, supplying an insufficient
70.Fa nel
71value will not result in functional harm, although a performance degradation
72may occur.
73Initialization using the
74.Fn hcreate
75function is mandatory prior to any access operations using
76.Fn hsearch .
77.Pp
78The
79.Fn hdestroy
80function destroys a table previously created using
81.Fn hcreate .
82After a call to
83.Fn hdestroy ,
84the data can no longer be accessed.
85.Pp
86The
87.Fn hsearch
88function is used to search to the hash table.
89It returns a pointer into the
90hash table indicating the address of an item.
91The
92.Fa item
93argument is of type
94.Dv ENTRY ,
95a structural type which contains the following members:
96.Pp
97.Bl -tag -compact -offset indent -width voidX*dataXX
98.It Fa char *key
99comparison key.
100.It Fa void *data
101pointer to data associated with
102.Fa key .
103.El
104.Pp
105The key comparison function used by
106.Fn hsearch
107is
108.Xr strcmp 3 .
109.Pp
110The
111.Fa action
112argument is of type
113.Dv ACTION ,
114an enumeration type which defines the following values:
115.Bl -tag -offset indent -width ENTERXX
116.It Dv ENTER
117Insert
118.Fa item
119into the hash table.
120If an existing item with the same key is found, it is not replaced.
121Note that the
122.Fa key
123and
124.Fa data
125elements of
126.Fa item
127are used directly by the new table entry.
128The storage for the
129key must not be modified during the lifetime of the hash table.
130.It Dv FIND
131Search the hash table without inserting
132.Fa item .
133.El
134.Sh RETURN VALUES
135If successful, the
136.Fn hcreate
137function returns a non-zero value.
138Otherwise, a value of 0 is returned and
139.Va errno
140is set to indicate the error.
141.Pp
142The
143.Fn hdestroy
144functions
145returns no value.
146.Pp
147If successful, the
148.Fn hsearch
149function returns a pointer to a hash table entry matching
150the provided key.
151If the action is
152.Dv FIND
153and the item was not found, or if the action is
154.Dv ENTER
155and the insertion failed,
156.Dv NULL
157is returned and
158.Va errno
159is set to indicate the error.
160If the action is
161.Dv ENTER
162and an entry already existed in the table matching the given
163key, the existing entry is returned and is not replaced.
164.Sh ERRORS
165The
166.Fn hcreate
167and
168.Fn hsearch
169functions will fail if:
170.Bl -tag -width Er
171.It Bq Er ENOMEM
172Insufficient memory is available.
173.El
174.Sh SEE ALSO
175.Xr bsearch 3 ,
176.Xr lsearch 3 ,
177.Xr malloc 3 ,
178.Xr strcmp 3
179.Sh STANDARDS
180These functions conform to
181.St -p1003.1-2004 .
182.Sh HISTORY
183The
184.Fn hcreate ,
185.Fn hdestroy
186and
187.Fn hsearch
188functions first appeared in
189.At V .
190.Sh BUGS
191The interface permits the use of only one hash table at a time.
diff --git a/src/lib/libc/stdlib/hcreate.c b/src/lib/libc/stdlib/hcreate.c
new file mode 100644
index 0000000000..f8df1bcd7c
--- /dev/null
+++ b/src/lib/libc/stdlib/hcreate.c
@@ -0,0 +1,191 @@
1/* $OpenBSD: hcreate.c,v 1.3 2005/10/10 17:37:44 espie Exp $ */
2/* $NetBSD: hcreate.c,v 1.5 2004/04/23 02:48:12 simonb Exp $ */
3
4/*
5 * Copyright (c) 2001 Christopher G. Demetriou
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed for the
19 * NetBSD Project. See http://www.NetBSD.org/ for
20 * information about NetBSD.
21 * 4. The name of the author may not be used to endorse or promote products
22 * derived from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *
35 * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>>
36 */
37
38/*
39 * hcreate() / hsearch() / hdestroy()
40 *
41 * SysV/XPG4 hash table functions.
42 *
43 * Implementation done based on NetBSD manual page and Solaris manual page,
44 * plus my own personal experience about how they're supposed to work.
45 *
46 * I tried to look at Knuth (as cited by the Solaris manual page), but
47 * nobody had a copy in the office, so...
48 */
49
50#include "namespace.h"
51#include <assert.h>
52#include <errno.h>
53#include <inttypes.h>
54#include <search.h>
55#include <stdlib.h>
56#include <string.h>
57#include <sys/queue.h>
58
59#ifndef _DIAGASSERT
60#define _DIAGASSERT(x)
61#endif
62
63/*
64 * DO NOT MAKE THIS STRUCTURE LARGER THAN 32 BYTES (4 ptrs on 64-bit
65 * ptr machine) without adjusting MAX_BUCKETS_LG2 below.
66 */
67struct internal_entry {
68 SLIST_ENTRY(internal_entry) link;
69 ENTRY ent;
70};
71SLIST_HEAD(internal_head, internal_entry);
72
73#define MIN_BUCKETS_LG2 4
74#define MIN_BUCKETS (1 << MIN_BUCKETS_LG2)
75
76/*
77 * max * sizeof internal_entry must fit into size_t.
78 * assumes internal_entry is <= 32 (2^5) bytes.
79 */
80#define MAX_BUCKETS_LG2 (sizeof (size_t) * 8 - 1 - 5)
81#define MAX_BUCKETS ((size_t)1 << MAX_BUCKETS_LG2)
82
83/* Default hash function, from db/hash/hash_func.c */
84extern u_int32_t (*__default_hash)(const void *, size_t);
85
86static struct internal_head *htable;
87static size_t htablesize;
88
89int
90hcreate(size_t nel)
91{
92 size_t idx;
93 unsigned int p2;
94
95 /* Make sure this isn't called when a table already exists. */
96 _DIAGASSERT(htable == NULL);
97 if (htable != NULL) {
98 errno = EINVAL;
99 return 0;
100 }
101
102 /* If nel is too small, make it min sized. */
103 if (nel < MIN_BUCKETS)
104 nel = MIN_BUCKETS;
105
106 /* If it's too large, cap it. */
107 if (nel > MAX_BUCKETS)
108 nel = MAX_BUCKETS;
109
110 /* If it's is not a power of two in size, round up. */
111 if ((nel & (nel - 1)) != 0) {
112 for (p2 = 0; nel != 0; p2++)
113 nel >>= 1;
114 _DIAGASSERT(p2 <= MAX_BUCKETS_LG2);
115 nel = 1 << p2;
116 }
117
118 /* Allocate the table. */
119 htablesize = nel;
120 htable = malloc(htablesize * sizeof htable[0]);
121 if (htable == NULL) {
122 errno = ENOMEM;
123 return 0;
124 }
125
126 /* Initialize it. */
127 for (idx = 0; idx < htablesize; idx++)
128 SLIST_INIT(&htable[idx]);
129
130 return 1;
131}
132
133void
134hdestroy(void)
135{
136 struct internal_entry *ie;
137 size_t idx;
138
139 _DIAGASSERT(htable != NULL);
140 if (htable == NULL)
141 return;
142
143 for (idx = 0; idx < htablesize; idx++) {
144 while (!SLIST_EMPTY(&htable[idx])) {
145 ie = SLIST_FIRST(&htable[idx]);
146 SLIST_REMOVE_HEAD(&htable[idx], link);
147 free(ie->ent.key);
148 free(ie);
149 }
150 }
151 free(htable);
152 htable = NULL;
153}
154
155ENTRY *
156hsearch(ENTRY item, ACTION action)
157{
158 struct internal_head *head;
159 struct internal_entry *ie;
160 uint32_t hashval;
161 size_t len;
162
163 _DIAGASSERT(htable != NULL);
164 _DIAGASSERT(item.key != NULL);
165 _DIAGASSERT(action == ENTER || action == FIND);
166
167 len = strlen(item.key);
168 hashval = (*__default_hash)(item.key, len);
169
170 head = &htable[hashval & (htablesize - 1)];
171 ie = SLIST_FIRST(head);
172 while (ie != NULL) {
173 if (strcmp(ie->ent.key, item.key) == 0)
174 break;
175 ie = SLIST_NEXT(ie, link);
176 }
177
178 if (ie != NULL)
179 return &ie->ent;
180 else if (action == FIND)
181 return NULL;
182
183 ie = malloc(sizeof *ie);
184 if (ie == NULL)
185 return NULL;
186 ie->ent.key = item.key;
187 ie->ent.data = item.data;
188
189 SLIST_INSERT_HEAD(head, ie, link);
190 return &ie->ent;
191}
diff --git a/src/lib/libc/stdlib/heapsort.c b/src/lib/libc/stdlib/heapsort.c
new file mode 100644
index 0000000000..e6fb61ba2f
--- /dev/null
+++ b/src/lib/libc/stdlib/heapsort.c
@@ -0,0 +1,173 @@
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#include <sys/types.h>
34#include <errno.h>
35#include <stdlib.h>
36
37/*
38 * Swap two areas of size number of bytes. Although qsort(3) permits random
39 * blocks of memory to be sorted, sorting pointers is almost certainly the
40 * common case (and, were it not, could easily be made so). Regardless, it
41 * isn't worth optimizing; the SWAP's get sped up by the cache, and pointer
42 * arithmetic gets lost in the time required for comparison function calls.
43 */
44#define SWAP(a, b, count, size, tmp) { \
45 count = size; \
46 do { \
47 tmp = *a; \
48 *a++ = *b; \
49 *b++ = tmp; \
50 } while (--count); \
51}
52
53/* Copy one block of size size to another. */
54#define COPY(a, b, count, size, tmp1, tmp2) { \
55 count = size; \
56 tmp1 = a; \
57 tmp2 = b; \
58 do { \
59 *tmp1++ = *tmp2++; \
60 } while (--count); \
61}
62
63/*
64 * Build the list into a heap, where a heap is defined such that for
65 * the records K1 ... KN, Kj/2 >= Kj for 1 <= j/2 <= j <= N.
66 *
67 * There are two cases. If j == nmemb, select largest of Ki and Kj. If
68 * j < nmemb, select largest of Ki, Kj and Kj+1.
69 */
70#define CREATE(initval, nmemb, par_i, child_i, par, child, size, count, tmp) { \
71 for (par_i = initval; (child_i = par_i * 2) <= nmemb; \
72 par_i = child_i) { \
73 child = base + child_i * size; \
74 if (child_i < nmemb && compar(child, child + size) < 0) { \
75 child += size; \
76 ++child_i; \
77 } \
78 par = base + par_i * size; \
79 if (compar(child, par) <= 0) \
80 break; \
81 SWAP(par, child, count, size, tmp); \
82 } \
83}
84
85/*
86 * Select the top of the heap and 'heapify'. Since by far the most expensive
87 * action is the call to the compar function, a considerable optimization
88 * in the average case can be achieved due to the fact that k, the displaced
89 * element, is usually quite small, so it would be preferable to first
90 * heapify, always maintaining the invariant that the larger child is copied
91 * over its parent's record.
92 *
93 * Then, starting from the *bottom* of the heap, finding k's correct place,
94 * again maintaining the invariant. As a result of the invariant no element
95 * is 'lost' when k is assigned its correct place in the heap.
96 *
97 * The time savings from this optimization are on the order of 15-20% for the
98 * average case. See Knuth, Vol. 3, page 158, problem 18.
99 *
100 * XXX Don't break the #define SELECT line, below. Reiser cpp gets upset.
101 */
102#define SELECT(par_i, child_i, nmemb, par, child, size, k, count, tmp1, tmp2) { \
103 for (par_i = 1; (child_i = par_i * 2) <= nmemb; par_i = child_i) { \
104 child = base + child_i * size; \
105 if (child_i < nmemb && compar(child, child + size) < 0) { \
106 child += size; \
107 ++child_i; \
108 } \
109 par = base + par_i * size; \
110 COPY(par, child, count, size, tmp1, tmp2); \
111 } \
112 for (;;) { \
113 child_i = par_i; \
114 par_i = child_i / 2; \
115 child = base + child_i * size; \
116 par = base + par_i * size; \
117 if (child_i == 1 || compar(k, par) < 0) { \
118 COPY(child, k, count, size, tmp1, tmp2); \
119 break; \
120 } \
121 COPY(child, par, count, size, tmp1, tmp2); \
122 } \
123}
124
125/*
126 * Heapsort -- Knuth, Vol. 3, page 145. Runs in O (N lg N), both average
127 * and worst. While heapsort is faster than the worst case of quicksort,
128 * the BSD quicksort does median selection so that the chance of finding
129 * a data set that will trigger the worst case is nonexistent. Heapsort's
130 * only advantage over quicksort is that it requires little additional memory.
131 */
132int
133heapsort(void *vbase, size_t nmemb, size_t size,
134 int (*compar)(const void *, const void *))
135{
136 int cnt, i, j, l;
137 char tmp, *tmp1, *tmp2;
138 char *base, *k, *p, *t;
139
140 if (nmemb <= 1)
141 return (0);
142
143 if (!size) {
144 errno = EINVAL;
145 return (-1);
146 }
147
148 if ((k = malloc(size)) == NULL)
149 return (-1);
150
151 /*
152 * Items are numbered from 1 to nmemb, so offset from size bytes
153 * below the starting address.
154 */
155 base = (char *)vbase - size;
156
157 for (l = nmemb / 2 + 1; --l;)
158 CREATE(l, nmemb, i, j, t, p, size, cnt, tmp);
159
160 /*
161 * For each element of the heap, save the largest element into its
162 * final slot, save the displaced element (k), then recreate the
163 * heap.
164 */
165 while (nmemb > 1) {
166 COPY(k, base + nmemb * size, cnt, size, tmp1, tmp2);
167 COPY(base + nmemb * size, base + size, cnt, size, tmp1, tmp2);
168 --nmemb;
169 SELECT(i, j, nmemb, t, p, size, k, cnt, tmp1, tmp2);
170 }
171 free(k);
172 return (0);
173}
diff --git a/src/lib/libc/stdlib/imaxabs.3 b/src/lib/libc/stdlib/imaxabs.3
new file mode 100644
index 0000000000..5384d0c9a6
--- /dev/null
+++ b/src/lib/libc/stdlib/imaxabs.3
@@ -0,0 +1,66 @@
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: imaxabs.3,v 1.1 2006/01/13 17:58:09 millert Exp $
33.\"
34.Dd January 6, 2005
35.Dt IMAXABS 3
36.Os
37.Sh NAME
38.Nm imaxabs
39.Nd integer absolute value function
40.Sh SYNOPSIS
41.Fd #include <inttypes.h>
42.Ft int
43.Fn imaxabs "int j"
44.Sh DESCRIPTION
45The
46.Fn imaxabs
47function computes the absolute value of the intmax_t variable
48.Fa j .
49.Sh RETURN VALUES
50The
51.Fn imaxabs
52function returns the absolute value.
53.Sh SEE ALSO
54.Xr abs 3 ,
55.Xr cabs 3 ,
56.Xr floor 3 ,
57.Xr hypot 3 ,
58.Xr labs 3 ,
59.Xr math 3
60.Sh STANDARDS
61The
62.Fn abs
63function conforms to
64.St -ansiC-99 .
65.Sh BUGS
66The absolute value of the most negative integer remains negative.
diff --git a/src/lib/libc/stdlib/imaxabs.c b/src/lib/libc/stdlib/imaxabs.c
new file mode 100644
index 0000000000..b7e910eefd
--- /dev/null
+++ b/src/lib/libc/stdlib/imaxabs.c
@@ -0,0 +1,38 @@
1/* $OpenBSD: imaxabs.c,v 1.1 2006/01/13 17:58:09 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. 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#include <inttypes.h>
33
34intmax_t
35imaxabs(intmax_t j)
36{
37 return (j < 0 ? -j : j);
38}
diff --git a/src/lib/libc/stdlib/imaxdiv.3 b/src/lib/libc/stdlib/imaxdiv.3
new file mode 100644
index 0000000000..63f25d52de
--- /dev/null
+++ b/src/lib/libc/stdlib/imaxdiv.3
@@ -0,0 +1,67 @@
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: imaxdiv.3,v 1.2 2006/01/14 13:04:53 jmc Exp $
33.\"
34.Dd January 3, 2006
35.Dt IMAXDIV 3
36.Os
37.Sh NAME
38.Nm imaxdiv
39.Nd return quotient and remainder from division
40.Sh SYNOPSIS
41.Fd #include <inttypes.h>
42.Ft imaxdiv_t
43.Fn imaxdiv "intmax_t num" "intmax_t denom"
44.Sh DESCRIPTION
45The
46.Fn imaxdiv
47function computes the value
48.Fa num Ns / Ns Fa denom
49and returns the quotient and remainder in a structure named
50.Li imaxdiv_t
51that contains two
52.Li intmax_t
53members named
54.Fa quot
55and
56.Fa rem .
57.Sh SEE ALSO
58.Xr div 3 ,
59.Xr ldiv 3 ,
60.Xr lldiv 3 ,
61.Xr math 3 ,
62.Xr qdiv 3
63.Sh STANDARDS
64The
65.Fn imaxdiv
66function conforms to
67.St -ansiC-99 .
diff --git a/src/lib/libc/stdlib/imaxdiv.c b/src/lib/libc/stdlib/imaxdiv.c
new file mode 100644
index 0000000000..0515a94b96
--- /dev/null
+++ b/src/lib/libc/stdlib/imaxdiv.c
@@ -0,0 +1,50 @@
1/* $OpenBSD: imaxdiv.c,v 1.1 2006/01/13 17:58:09 millert Exp $ */
2/*
3 * Copyright (c) 1990 Regents of the University of California.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * Chris Torek.
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
34#include <inttypes.h> /* imaxdiv_t */
35
36imaxdiv_t
37imaxdiv(intmax_t num, intmax_t denom)
38{
39 imaxdiv_t r;
40
41 /* see div.c for comments */
42
43 r.quot = num / denom;
44 r.rem = num % denom;
45 if (num >= 0 && r.rem < 0) {
46 r.quot++;
47 r.rem -= denom;
48 }
49 return (r);
50}
diff --git a/src/lib/libc/stdlib/insque.3 b/src/lib/libc/stdlib/insque.3
new file mode 100644
index 0000000000..fb4f55112d
--- /dev/null
+++ b/src/lib/libc/stdlib/insque.3
@@ -0,0 +1,106 @@
1.\" $OpenBSD: insque.3,v 1.6 2005/07/26 04:20:23 jaredy 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 -offset indent
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.Pp
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 insque
87and
88.Fn remque
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
100.Li insque
101and
102.Li remque
103instructions on the
104.Tn VAX .
105They first appeared in
106.Bx 4.2 .
diff --git a/src/lib/libc/stdlib/insque.c b/src/lib/libc/stdlib/insque.c
new file mode 100644
index 0000000000..8724efec74
--- /dev/null
+++ b/src/lib/libc/stdlib/insque.c
@@ -0,0 +1,48 @@
1/* $OpenBSD: insque.c,v 1.2 2005/08/08 08:05:36 espie 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#include <search.h>
32
33struct qelem {
34 struct qelem *q_forw;
35 struct qelem *q_back;
36};
37
38void
39insque(void *entry, void *pred)
40{
41 struct qelem *e = (struct qelem *) entry;
42 struct qelem *p = (struct qelem *) pred;
43
44 e->q_forw = p->q_forw;
45 e->q_back = p;
46 p->q_forw->q_back = e;
47 p->q_forw = e;
48}
diff --git a/src/lib/libc/stdlib/jrand48.c b/src/lib/libc/stdlib/jrand48.c
new file mode 100644
index 0000000000..cb8c592750
--- /dev/null
+++ b/src/lib/libc/stdlib/jrand48.c
@@ -0,0 +1,22 @@
1/* $OpenBSD: jrand48.c,v 1.3 2005/08/08 08:05:36 espie Exp $ */
2/*
3 * Copyright (c) 1993 Martin Birgmeier
4 * All rights reserved.
5 *
6 * You may redistribute unmodified or modified versions of this source
7 * code provided that the above copyright notice and this and the
8 * following conditions are retained.
9 *
10 * This software is provided ``as is'', and comes with no warranties
11 * of any kind. I shall in no event be liable for anything that happens
12 * to anyone/anything when using this software.
13 */
14
15#include "rand48.h"
16
17long
18jrand48(unsigned short xseed[3])
19{
20 __dorand48(xseed);
21 return ((long) xseed[2] << 16) + (long) xseed[1];
22}
diff --git a/src/lib/libc/stdlib/l64a.c b/src/lib/libc/stdlib/l64a.c
new file mode 100644
index 0000000000..4f33df37b2
--- /dev/null
+++ b/src/lib/libc/stdlib/l64a.c
@@ -0,0 +1,42 @@
1/* $OpenBSD: l64a.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
2/*
3 * Written by J.T. Conklin <jtc@netbsd.org>.
4 * Public domain.
5 */
6
7#include <errno.h>
8#include <stdlib.h>
9
10char *
11l64a(long value)
12{
13 static char buf[8];
14 char *s = buf;
15 int digit;
16 int i;
17
18 if (value < 0) {
19 errno = EINVAL;
20 return(NULL);
21 }
22
23 for (i = 0; value != 0 && i < 6; i++) {
24 digit = value & 0x3f;
25
26 if (digit < 2)
27 *s = digit + '.';
28 else if (digit < 12)
29 *s = digit + '0' - 2;
30 else if (digit < 38)
31 *s = digit + 'A' - 12;
32 else
33 *s = digit + 'a' - 38;
34
35 value >>= 6;
36 s++;
37 }
38
39 *s = '\0';
40
41 return(buf);
42}
diff --git a/src/lib/libc/stdlib/labs.3 b/src/lib/libc/stdlib/labs.3
new file mode 100644
index 0000000000..ab1ccaaf53
--- /dev/null
+++ b/src/lib/libc/stdlib/labs.3
@@ -0,0 +1,69 @@
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.8 2006/01/13 17:58:09 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 imaxabs 3 ,
60.Xr math 3
61.Sh STANDARDS
62The
63.Fn labs
64and
65.Fn llabs
66functions conform to
67.St -ansiC-99 .
68.Sh BUGS
69The 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..ca60b9aba2
--- /dev/null
+++ b/src/lib/libc/stdlib/labs.c
@@ -0,0 +1,37 @@
1/* $OpenBSD: labs.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
2/*-
3 * Copyright (c) 1990 The Regents of the University of California.
4 * 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
31#include <stdlib.h>
32
33long
34labs(long j)
35{
36 return(j < 0 ? -j : j);
37}
diff --git a/src/lib/libc/stdlib/lcong48.c b/src/lib/libc/stdlib/lcong48.c
new file mode 100644
index 0000000000..2cf5c271ba
--- /dev/null
+++ b/src/lib/libc/stdlib/lcong48.c
@@ -0,0 +1,31 @@
1/* $OpenBSD: lcong48.c,v 1.3 2005/08/08 08:05:36 espie Exp $ */
2/*
3 * Copyright (c) 1993 Martin Birgmeier
4 * All rights reserved.
5 *
6 * You may redistribute unmodified or modified versions of this source
7 * code provided that the above copyright notice and this and the
8 * following conditions are retained.
9 *
10 * This software is provided ``as is'', and comes with no warranties
11 * of any kind. I shall in no event be liable for anything that happens
12 * to anyone/anything when using this software.
13 */
14
15#include "rand48.h"
16
17extern unsigned short __rand48_seed[3];
18extern unsigned short __rand48_mult[3];
19extern unsigned short __rand48_add;
20
21void
22lcong48(unsigned short p[7])
23{
24 __rand48_seed[0] = p[0];
25 __rand48_seed[1] = p[1];
26 __rand48_seed[2] = p[2];
27 __rand48_mult[0] = p[3];
28 __rand48_mult[1] = p[4];
29 __rand48_mult[2] = p[5];
30 __rand48_add = p[6];
31}
diff --git a/src/lib/libc/stdlib/ldiv.3 b/src/lib/libc/stdlib/ldiv.3
new file mode 100644
index 0000000000..951a5807e0
--- /dev/null
+++ b/src/lib/libc/stdlib/ldiv.3
@@ -0,0 +1,67 @@
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.8 2006/01/13 17:58:09 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt LDIV 3
36.Os
37.Sh NAME
38.Nm ldiv
39.Nd return quotient and remainder from division
40.Sh SYNOPSIS
41.Fd #include <stdlib.h>
42.Ft ldiv_t
43.Fn ldiv "long num" "long denom"
44.Sh DESCRIPTION
45The
46.Fn ldiv
47function computes the value
48.Fa num Ns / 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 imaxdiv 3 ,
60.Xr lldiv 3 ,
61.Xr math 3 ,
62.Xr qdiv 3
63.Sh STANDARDS
64The
65.Fn ldiv
66function conforms to
67.St -ansiC .
diff --git a/src/lib/libc/stdlib/ldiv.c b/src/lib/libc/stdlib/ldiv.c
new file mode 100644
index 0000000000..775065f525
--- /dev/null
+++ b/src/lib/libc/stdlib/ldiv.c
@@ -0,0 +1,50 @@
1/* $OpenBSD: ldiv.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
2/*
3 * Copyright (c) 1990 Regents of the University of California.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * Chris Torek.
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
34#include <stdlib.h> /* ldiv_t */
35
36ldiv_t
37ldiv(long num, long denom)
38{
39 ldiv_t r;
40
41 /* see div.c for comments */
42
43 r.quot = num / denom;
44 r.rem = num % denom;
45 if (num >= 0 && r.rem < 0) {
46 r.quot++;
47 r.rem -= denom;
48 }
49 return (r);
50}
diff --git a/src/lib/libc/stdlib/llabs.c b/src/lib/libc/stdlib/llabs.c
new file mode 100644
index 0000000000..0a0ff784af
--- /dev/null
+++ b/src/lib/libc/stdlib/llabs.c
@@ -0,0 +1,42 @@
1/* $OpenBSD: llabs.c,v 1.2 2005/08/08 08:05:36 espie 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#include <stdlib.h>
37
38long long
39llabs(long long j)
40{
41 return (j < 0 ? -j : j);
42}
diff --git a/src/lib/libc/stdlib/lldiv.3 b/src/lib/libc/stdlib/lldiv.3
new file mode 100644
index 0000000000..53bb3d35ae
--- /dev/null
+++ b/src/lib/libc/stdlib/lldiv.3
@@ -0,0 +1,67 @@
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: lldiv.3,v 1.1 2006/01/13 17:58:09 millert Exp $
33.\"
34.Dd January 3, 2006
35.Dt LLDIV 3
36.Os
37.Sh NAME
38.Nm lldiv
39.Nd return quotient and remainder from division
40.Sh SYNOPSIS
41.Fd #include <stdlib.h>
42.Ft lldiv_t
43.Fn lldiv "long long num" "long long denom"
44.Sh DESCRIPTION
45The
46.Fn lldiv
47function computes the value
48.Fa num Ns / Ns Fa denom
49and returns the quotient and remainder in a structure named
50.Li lldiv_t
51that contains two
52.Li long long integer
53members named
54.Fa quot
55and
56.Fa rem .
57.Sh SEE ALSO
58.Xr div 3 ,
59.Xr imaxdiv 3 ,
60.Xr ldiv 3 ,
61.Xr math 3 ,
62.Xr qdiv 3
63.Sh STANDARDS
64The
65.Fn lldiv
66function conforms to
67.St -ansiC-99 .
diff --git a/src/lib/libc/stdlib/lldiv.c b/src/lib/libc/stdlib/lldiv.c
new file mode 100644
index 0000000000..e8d6c978b3
--- /dev/null
+++ b/src/lib/libc/stdlib/lldiv.c
@@ -0,0 +1,50 @@
1/* $OpenBSD: lldiv.c,v 1.1 2006/01/13 17:58:09 millert Exp $ */
2/*
3 * Copyright (c) 1990 Regents of the University of California.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * Chris Torek.
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
34#include <stdlib.h> /* lldiv_t */
35
36lldiv_t
37lldiv(long long num, long long denom)
38{
39 lldiv_t r;
40
41 /* see div.c for comments */
42
43 r.quot = num / denom;
44 r.rem = num % denom;
45 if (num >= 0 && r.rem < 0) {
46 r.quot++;
47 r.rem -= denom;
48 }
49 return (r);
50}
diff --git a/src/lib/libc/stdlib/lrand48.c b/src/lib/libc/stdlib/lrand48.c
new file mode 100644
index 0000000000..21beb858ca
--- /dev/null
+++ b/src/lib/libc/stdlib/lrand48.c
@@ -0,0 +1,24 @@
1/* $OpenBSD: lrand48.c,v 1.3 2005/08/08 08:05:36 espie Exp $ */
2/*
3 * Copyright (c) 1993 Martin Birgmeier
4 * All rights reserved.
5 *
6 * You may redistribute unmodified or modified versions of this source
7 * code provided that the above copyright notice and this and the
8 * following conditions are retained.
9 *
10 * This software is provided ``as is'', and comes with no warranties
11 * of any kind. I shall in no event be liable for anything that happens
12 * to anyone/anything when using this software.
13 */
14
15#include "rand48.h"
16
17extern unsigned short __rand48_seed[3];
18
19long
20lrand48(void)
21{
22 __dorand48(__rand48_seed);
23 return ((long) __rand48_seed[2] << 15) + ((long) __rand48_seed[1] >> 1);
24}
diff --git a/src/lib/libc/stdlib/lsearch.3 b/src/lib/libc/stdlib/lsearch.3
new file mode 100644
index 0000000000..eda67ada01
--- /dev/null
+++ b/src/lib/libc/stdlib/lsearch.3
@@ -0,0 +1,108 @@
1.\" $OpenBSD: lsearch.3,v 1.7 2005/12/23 21:34:16 millert Exp $
2.\"
3.\" Copyright (c) 1989, 1991, 1993
4.\" The Regents of the University of California. All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. Neither the name of the University nor the names of its contributors
15.\" may be used to endorse or promote products derived from this software
16.\" without specific prior written permission.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28.\" SUCH DAMAGE.
29.\"
30.\" @(#)lsearch.3 8.1 (Berkeley) 6/4/93
31.\"
32.Dd June 4, 1993
33.Dt LSEARCH 3
34.Os
35.Sh NAME
36.Nm lsearch ,
37.Nm lfind
38.Nd linear searching routines
39.Sh SYNOPSIS
40.Fd #include <search.h>
41.Ft char *
42.Fn lsearch "const void *key" "const void *base" "size_t *nelp" \
43 "size_t width" "int (*compar)(void *, void *)"
44.Ft char *
45.Fn lfind "const void *key" "const void *base" "size_t *nelp" \
46 "size_t width" "int (*compar)(void *, void *)"
47.Sh DESCRIPTION
48The functions
49.Fn lsearch
50and
51.Fn lfind
52provide basic linear searching functionality.
53.Pp
54.Fa base
55is the pointer to the beginning of an array.
56The argument
57.Fa nelp
58is the current number of elements in the array, where each element
59is
60.Fa width
61bytes long.
62The
63.Fa compar
64function
65is a comparison routine which is used to compare two elements.
66It takes two arguments which point to the
67.Fa key
68object and to an array member, in that order, and must return an integer
69less than, equivalent to, or greater than zero if the
70.Fa key
71object is considered, respectively, to be less than, equal to, or greater
72than the array member.
73.Pp
74The
75.Fn lsearch
76and
77.Fn lfind
78functions
79return a pointer into the array referenced by
80.Fa base
81where
82.Fa key
83is located.
84If
85.Fa key
86does not exist,
87.Fn lfind
88will return a null pointer and
89.Fn lsearch
90will add it to the array.
91When an element is added to the array by
92.Fn lsearch ,
93the location referenced by the argument
94.Fa nelp
95is incremented by one.
96.Sh SEE ALSO
97.Xr bsearch 3 ,
98.Xr db 3
99.Sh STANDARDS
100The
101.Fn lsearch
102and
103.Fn lfind
104functions conform to the
105.St -p1003.1-2001
106and
107.St -xpg4.3
108specifications.
diff --git a/src/lib/libc/stdlib/lsearch.c b/src/lib/libc/stdlib/lsearch.c
new file mode 100644
index 0000000000..0815430199
--- /dev/null
+++ b/src/lib/libc/stdlib/lsearch.c
@@ -0,0 +1,88 @@
1/* $OpenBSD: lsearch.c,v 1.3 2004/10/01 04:08:45 jsg Exp $ */
2
3/*
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Roger L. Snyder.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#if defined(LIBC_SCCS) && !defined(lint)
36static char sccsid[] = "@(#)lsearch.c 8.1 (Berkeley) 6/4/93";
37#endif /* LIBC_SCCS and not lint */
38
39#include <sys/types.h>
40#include <string.h>
41#include <search.h>
42
43typedef int (*cmp_fn_t)(const void *, const void *);
44static void *linear_base(const void *, const void *, size_t *, size_t,
45 cmp_fn_t, int);
46
47void *
48lsearch(const void *key, const void *base, size_t *nelp, size_t width,
49 cmp_fn_t compar)
50{
51
52 return(linear_base(key, base, nelp, width, compar, 1));
53}
54
55void *
56lfind(const void *key, const void *base, size_t *nelp, size_t width,
57 cmp_fn_t compar)
58{
59 return(linear_base(key, base, nelp, width, compar, 0));
60}
61
62static void *
63linear_base(const void *key, const void *base, size_t *nelp, size_t width,
64 cmp_fn_t compar, int add_flag)
65{
66 const char *element, *end;
67
68 end = (const char *)base + *nelp * width;
69 for (element = base; element < end; element += width)
70 if (!compar(key, element)) /* key found */
71 return((void *)element);
72
73 if (!add_flag) /* key not found */
74 return(NULL);
75
76 /*
77 * The UNIX System User's Manual, 1986 edition claims that
78 * a NULL pointer is returned by lsearch with errno set
79 * appropriately, if there is not enough room in the table
80 * to add a new item. This can't be done as none of these
81 * routines have any method of determining the size of the
82 * table. This comment isn't in the 1986-87 System V
83 * manual.
84 */
85 ++*nelp;
86 memcpy((void *)end, key, width);
87 return((void *)end);
88}
diff --git a/src/lib/libc/stdlib/malloc.3 b/src/lib/libc/stdlib/malloc.3
new file mode 100644
index 0000000000..e5bb1315df
--- /dev/null
+++ b/src/lib/libc/stdlib/malloc.3
@@ -0,0 +1,466 @@
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.45 2006/06/06 14:49:26 pedro 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
86When using
87.Fn malloc
88be careful to avoid the following idiom:
89.Bd -literal -offset indent
90if ((p = malloc(num * size)) == NULL)
91 err(1, "malloc");
92.Ed
93.Pp
94The multiplication may lead to an integer overflow.
95To avoid this,
96.Fn calloc
97is recommended.
98.Pp
99If
100.Fn malloc
101must be used, be sure to test for overflow:
102.Bd -literal -offset indent
103if (num && SIZE_MAX / num < size) {
104 errno = ENOMEM;
105 err(1, "overflow");
106}
107.Ed
108.Pp
109The
110.Fn calloc
111function allocates space for an array of
112.Fa nmemb
113objects, each of whose size is
114.Fa size .
115The space is initialized to all bits zero.
116The use of
117.Fn calloc
118is strongly encouraged when allocating multiple sized objects
119in order to avoid possible integer overflows.
120.Pp
121The
122.Fn free
123function causes the space pointed to by
124.Fa ptr
125to be deallocated, that is, at least made available for further allocation,
126but if possible, it will be passed back to the kernel with
127.Xr sbrk 2 .
128If
129.Fa ptr
130is a null pointer, no action occurs.
131.Pp
132A
133.Fn cfree
134function is also provided for compatibility with old systems and other
135.Nm malloc
136libraries; it is simply an alias for
137.Fn free .
138.Pp
139The
140.Fn realloc
141function changes the size of the object pointed to by
142.Fa ptr
143to
144.Fa size
145bytes and returns a pointer to the (possibly moved) object.
146The contents of the object are unchanged up to the lesser
147of the new and old sizes.
148If the new size is larger, the value of the newly allocated portion
149of the object is indeterminate and uninitialized.
150If
151.Fa ptr
152is a null pointer, the
153.Fn realloc
154function behaves like the
155.Fn malloc
156function for the specified size.
157If the space cannot be allocated, the object
158pointed to by
159.Fa ptr
160is unchanged.
161If
162.Fa size
163is zero and
164.Fa ptr
165is not a null pointer, the object it points to is freed and a new zero size
166object is returned.
167.Pp
168When using
169.Fn realloc
170be careful to avoid the following idiom:
171.Bd -literal -offset indent
172size += 50;
173if ((p = realloc(p, size)) == NULL)
174 return (NULL);
175.Ed
176.Pp
177Do not adjust the variable describing how much memory has been allocated
178until the allocation has been successful.
179This can cause aberrant program behavior if the incorrect size value is used.
180In most cases, the above sample will also result in a leak of memory.
181As stated earlier, a return value of
182.Dv NULL
183indicates that the old object still remains allocated.
184Better code looks like this:
185.Bd -literal -offset indent
186newsize = size + 50;
187if ((newp = realloc(p, newsize)) == NULL) {
188 free(p);
189 p = NULL;
190 size = 0;
191 return (NULL);
192}
193p = newp;
194size = newsize;
195.Ed
196.Pp
197As with
198.Fn malloc
199it is important to ensure the new size value will not overflow;
200i.e. avoid allocations like the following:
201.Bd -literal -offset indent
202if ((newp = realloc(p, num * size)) == NULL) {
203 ...
204.Ed
205.Pp
206Malloc will first look for a symbolic link called
207.Pa /etc/malloc.conf
208and next check the environment for a variable called
209.Ev MALLOC_OPTIONS
210and finally for the global variable
211.Va malloc_options
212and scan them for flags in that order.
213Flags are single letters, uppercase means on, lowercase means off.
214.Bl -tag -width indent
215.It Cm A
216.Dq Abort .
217.Fn malloc
218will coredump the process, rather than tolerate failure.
219This is a very handy debugging aid, since the core file will represent the
220time of failure, rather than when the null pointer was accessed.
221.It Cm D
222.Dq Dump .
223.Fn malloc
224will dump statistics in a file called
225.Pa malloc.out
226at exit.
227This option requires the library to have been compiled with -DMALLOC_STATS in
228order to have any effect.
229.It Cm F
230.Dq Freeguard .
231Enable use after free protection.
232Unused pages on the freelist are read and write protected to
233cause a segmentation fault upon access.
234.It Cm G
235.Dq Guard .
236Enable guard pages and chunk randomization.
237Each page size or larger allocation is followed by a guard page that will
238cause a segmentation fault upon any access.
239Smaller than page size chunks are returned in a random order.
240.It Cm H
241.Dq Hint .
242Pass a hint to the kernel about pages we don't use.
243If the machine is paging a lot this may help a bit.
244.It Cm J
245.Dq Junk .
246Fill some junk into the area allocated.
247Currently junk is bytes of 0xd0; this is pronounced
248.Dq Duh .
249\&:-)
250.It Cm N
251Do not output warning messages when encountering possible corruption
252or bad pointers.
253.It Cm P
254.Dq Pointer Protection .
255Pointer sized allocations are aligned to the end of a page to catch
256sizeof(ptr) errors where sizeof(*ptr) is meant.
257.It Cm R
258.Dq realloc .
259Always reallocate when
260.Fn realloc
261is called, even if the initial allocation was big enough.
262This can substantially aid in compacting memory.
263.\".Pp
264.\".It Cm U
265.\".Dq utrace .
266.\"Generate entries for
267.\".Xr ktrace 1
268.\"for all operations.
269.\"Consult the source for this one.
270.It Cm X
271.Dq xmalloc .
272Rather than return failure,
273.Xr abort 3
274the program with a diagnostic message on stderr.
275It is the intention that this option be set at compile time by
276including in the source:
277.Bd -literal -offset indent
278extern char *malloc_options;
279malloc_options = "X";
280.Ed
281.It Cm Z
282.Dq Zero .
283Fill some junk into the area allocated (see
284.Cm J ) ,
285except for the exact length the user asked for, which is zeroed.
286.It Cm <
287.Dq Half the cache size .
288Decrease the size of the free page cache by a factor of two.
289.It Cm >
290.Dq Double the cache size .
291Increase the size of the free page cache by a factor of two.
292.El
293.Pp
294So to set a systemwide reduction of cache size and coredumps on problems:
295.Li ln -s 'A<' /etc/malloc.conf
296.Pp
297The
298.Cm J
299and
300.Cm Z
301flags are mostly for testing and debugging.
302If a program changes behavior if either of these options are used,
303it is buggy.
304.Pp
305The default number of free pages cached is 16.
306.Sh RETURN VALUES
307The
308.Fn malloc
309and
310.Fn calloc
311functions return a pointer to the allocated space if successful; otherwise,
312a null pointer is returned and
313.Va errno
314is set to
315.Er ENOMEM .
316.Pp
317The
318.Fn free
319and
320.Fn cfree
321functions return no value.
322.Pp
323The
324.Fn realloc
325function returns a pointer to the (possibly moved) allocated space
326if successful; otherwise, a null pointer is returned and
327.Va errno
328is set to
329.Er ENOMEM .
330.Sh ENVIRONMENT
331.Bl -tag -width Ev
332.It Ev MALLOC_OPTIONS
333See above.
334.El
335.Sh FILES
336.Bl -tag -width "/etc/malloc.conf"
337.It Pa /etc/malloc.conf
338symbolic link to filename containing option flags
339.El
340.Sh DIAGNOSTICS
341If
342.Fn malloc ,
343.Fn calloc ,
344.Fn realloc ,
345or
346.Fn free
347detect an error or warning condition,
348a message will be printed to file descriptor
3492 (not using stdio).
350Errors will always result in the process being
351.Xr abort 3 'ed.
352If the
353.Cm A
354option has been specified, warnings will also
355.Xr abort 3
356the process.
357.Pp
358Here is a brief description of the error messages and what they mean:
359.Bl -tag -width Ds
360.It Dq (ES): mumble mumble mumble
361.Fn malloc
362has been compiled with
363.Dv \&-DEXTRA_SANITY
364and something looks fishy in there.
365Consult sources and/or wizards.
366.It Dq allocation failed
367If the
368.Cm A
369option is specified it is an error for
370.Fn malloc ,
371.Fn calloc ,
372or
373.Fn realloc
374to return
375.Dv NULL .
376.It Dq mmap(2) failed, check limits.
377This is a rather weird condition that is most likely to indicate a
378seriously overloaded system or a
379.Xr ulimit 1
380restriction.
381.It Dq freelist is destroyed.
382.Fn malloc Ns 's
383internal freelist has been stomped on.
384.El
385.Pp
386Here is a brief description of the warning messages and what they mean:
387.Bl -tag -width Ds
388.It Dq chunk/page is already free.
389There was an attempt to free a chunk that had already been freed.
390.It Dq junk pointer, too high to make sense.
391The pointer doesn't make sense.
392It's above the area of memory that
393.Fn malloc
394knows something about.
395This could be a pointer from some
396.Xr mmap 2 'ed
397memory.
398.It Dq junk pointer, too low to make sense.
399The pointer doesn't make sense.
400It's below the area of memory that
401.Fn malloc
402knows something about.
403This pointer probably came from your data or bss segments.
404.It Dq malloc() has never been called.
405Nothing has ever been allocated, yet something is being freed or
406realloc'ed.
407.It Dq modified (chunk-/page-) pointer.
408The pointer passed to
409.Fn free
410or
411.Fn realloc
412has been modified.
413.It Dq pointer to wrong page.
414The pointer that
415.Fn malloc
416is trying to free is not pointing to
417a sensible page.
418.It Dq recursive call.
419An attempt was made to call recursively into these functions, i.e., from a
420signal handler.
421This behavior is not supported.
422In particular, signal handlers should
423.Em not
424use any of the
425.Fn malloc
426functions nor utilize any other functions which may call
427.Fn malloc
428(e.g.,
429.Xr stdio 3
430routines).
431.It Dq unknown char in MALLOC_OPTIONS
432We found something we didn't understand.
433.El
434.Sh SEE ALSO
435.Xr brk 2 ,
436.Xr alloca 3 ,
437.Xr getpagesize 3
438.Sh STANDARDS
439The
440.Fn malloc
441function conforms to
442.St -ansiC .
443.Sh HISTORY
444The present implementation of
445.Fn malloc
446started out as a filesystem on a drum
447attached to a 20-bit binary challenged computer built with discrete germanium
448transistors, and it has since graduated to handle primary storage rather than
449secondary.
450.Pp
451The main difference from other
452.Fn malloc
453implementations are believed to be that
454the free pages are not accessed until allocated.
455Most
456.Fn malloc
457implementations will store a data structure containing a,
458possibly double-, linked list in the free chunks of memory, used to tie
459all the free memory together.
460That is a quite suboptimal thing to do.
461Every time the free-list is traversed, all the otherwise unused, and very
462likely paged out, pages get faulted into primary memory, just to see what
463lies after them in the list.
464.Pp
465On systems which are paging, this can increase the page-faults
466of 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..028eff2b2d
--- /dev/null
+++ b/src/lib/libc/stdlib/malloc.c
@@ -0,0 +1,1870 @@
1/* $OpenBSD: malloc.c,v 1.83 2006/05/14 19:53:40 otto Exp $ */
2
3/*
4 * ----------------------------------------------------------------------------
5 * "THE BEER-WARE LICENSE" (Revision 42):
6 * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you
7 * can do whatever you want with this stuff. If we meet some day, and you think
8 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
9 * ----------------------------------------------------------------------------
10 */
11
12/*
13 * Defining MALLOC_EXTRA_SANITY will enable extra checks which are
14 * related to internal conditions and consistency in malloc.c. This has
15 * a noticeable runtime performance hit, and generally will not do you
16 * any good unless you fiddle with the internals of malloc or want
17 * to catch random pointer corruption as early as possible.
18 */
19#ifndef MALLOC_EXTRA_SANITY
20#undef MALLOC_EXTRA_SANITY
21#endif
22
23/*
24 * Defining MALLOC_STATS will enable you to call malloc_dump() and set
25 * the [dD] options in the MALLOC_OPTIONS environment variable.
26 * It has no run-time performance hit, but does pull in stdio...
27 */
28#ifndef MALLOC_STATS
29#undef MALLOC_STATS
30#endif
31
32/*
33 * What to use for Junk. This is the byte value we use to fill with
34 * when the 'J' option is enabled.
35 */
36#define SOME_JUNK 0xd0 /* as in "Duh" :-) */
37
38#include <sys/types.h>
39#include <sys/time.h>
40#include <sys/resource.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#include <err.h>
52
53#include "thread_private.h"
54
55/*
56 * The basic parameters you can tweak.
57 *
58 * malloc_pageshift pagesize = 1 << malloc_pageshift
59 * It's probably best if this is the native
60 * page size, but it shouldn't have to be.
61 *
62 * malloc_minsize minimum size of an allocation in bytes.
63 * If this is too small it's too much work
64 * to manage them. This is also the smallest
65 * unit of alignment used for the storage
66 * returned by malloc/realloc.
67 *
68 */
69
70#if defined(__sparc__)
71#define malloc_pageshift 13U
72#endif /* __sparc__ */
73
74#ifndef malloc_pageshift
75#define malloc_pageshift (PGSHIFT)
76#endif
77
78/*
79 * No user serviceable parts behind this point.
80 *
81 * This structure describes a page worth of chunks.
82 */
83struct pginfo {
84 struct pginfo *next; /* next on the free list */
85 void *page; /* Pointer to the page */
86 u_short size; /* size of this page's chunks */
87 u_short shift; /* How far to shift for this size chunks */
88 u_short free; /* How many free chunks */
89 u_short total; /* How many chunk */
90 u_long bits[1];/* Which chunks are free */
91};
92
93/* How many bits per u_long in the bitmap */
94#define MALLOC_BITS (NBBY * sizeof(u_long))
95
96/*
97 * This structure describes a number of free pages.
98 */
99struct pgfree {
100 struct pgfree *next; /* next run of free pages */
101 struct pgfree *prev; /* prev run of free pages */
102 void *page; /* pointer to free pages */
103 void *pdir; /* pointer to the base page's dir */
104 size_t size; /* number of bytes free */
105};
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_minsize
117#define malloc_minsize 16UL
118#endif
119
120#if !defined(malloc_pagesize)
121#define malloc_pagesize (1UL<<malloc_pageshift)
122#endif
123
124#if ((1UL<<malloc_pageshift) != malloc_pagesize)
125#error "(1UL<<malloc_pageshift) != malloc_pagesize"
126#endif
127
128#ifndef malloc_maxsize
129#define malloc_maxsize ((malloc_pagesize)>>1)
130#endif
131
132/* A mask for the offset inside a page. */
133#define malloc_pagemask ((malloc_pagesize)-1)
134
135#define pageround(foo) (((foo) + (malloc_pagemask)) & ~malloc_pagemask)
136#define ptr2index(foo) (((u_long)(foo) >> malloc_pageshift)+malloc_pageshift)
137#define index2ptr(idx) ((void*)(((idx)-malloc_pageshift)<<malloc_pageshift))
138
139/* Set when initialization has been done */
140static unsigned int malloc_started;
141
142/* Number of free pages we cache */
143static unsigned int malloc_cache = 16;
144
145/* Structure used for linking discrete directory pages. */
146struct pdinfo {
147 struct pginfo **base;
148 struct pdinfo *prev;
149 struct pdinfo *next;
150 u_long dirnum;
151};
152static struct pdinfo *last_dir; /* Caches to the last and previous */
153static struct pdinfo *prev_dir; /* referenced directory pages. */
154
155static size_t pdi_off;
156static u_long pdi_mod;
157#define PD_IDX(num) ((num) / (malloc_pagesize/sizeof(struct pginfo *)))
158#define PD_OFF(num) ((num) & ((malloc_pagesize/sizeof(struct pginfo *))-1))
159#define PI_IDX(index) ((index) / pdi_mod)
160#define PI_OFF(index) ((index) % pdi_mod)
161
162/* The last index in the page directory we care about */
163static u_long last_index;
164
165/* Pointer to page directory. Allocated "as if with" malloc */
166static struct pginfo **page_dir;
167
168/* Free pages line up here */
169static struct pgfree free_list;
170
171/* Abort(), user doesn't handle problems. */
172static int malloc_abort = 2;
173
174/* Are we trying to die ? */
175static int suicide;
176
177#ifdef MALLOC_STATS
178/* dump statistics */
179static int malloc_stats;
180#endif
181
182/* avoid outputting warnings? */
183static int malloc_silent;
184
185/* always realloc ? */
186static int malloc_realloc;
187
188/* mprotect free pages PROT_NONE? */
189static int malloc_freeprot;
190
191/* use guard pages after allocations? */
192static size_t malloc_guard = 0;
193static size_t malloc_guarded;
194/* align pointers to end of page? */
195static int malloc_ptrguard;
196
197static int malloc_hint;
198
199/* xmalloc behaviour ? */
200static int malloc_xmalloc;
201
202/* zero fill ? */
203static int malloc_zero;
204
205/* junk fill ? */
206static int malloc_junk;
207
208#ifdef __FreeBSD__
209/* utrace ? */
210static int malloc_utrace;
211
212struct ut {
213 void *p;
214 size_t s;
215 void *r;
216};
217
218void utrace(struct ut *, int);
219
220#define UTRACE(a, b, c) \
221 if (malloc_utrace) \
222 {struct ut u; u.p=a; u.s = b; u.r=c; utrace(&u, sizeof u);}
223#else /* !__FreeBSD__ */
224#define UTRACE(a,b,c)
225#endif
226
227/* Status of malloc. */
228static int malloc_active;
229
230/* Allocated memory. */
231static size_t malloc_used;
232
233/* My last break. */
234static caddr_t malloc_brk;
235
236/* One location cache for free-list holders. */
237static struct pgfree *px;
238
239/* Compile-time options. */
240char *malloc_options;
241
242/* Name of the current public function. */
243static char *malloc_func;
244
245#define MMAP(size) \
246 mmap((void *)0, (size), PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, \
247 -1, (off_t)0)
248
249/*
250 * Necessary function declarations.
251 */
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/*
258 * Function for page directory lookup.
259 */
260static int
261pdir_lookup(u_long index, struct pdinfo ** pdi)
262{
263 struct pdinfo *spi;
264 u_long pidx = PI_IDX(index);
265
266 if (last_dir != NULL && PD_IDX(last_dir->dirnum) == pidx)
267 *pdi = last_dir;
268 else if (prev_dir != NULL && PD_IDX(prev_dir->dirnum) == pidx)
269 *pdi = prev_dir;
270 else if (last_dir != NULL && prev_dir != NULL) {
271 if ((PD_IDX(last_dir->dirnum) > pidx) ?
272 (PD_IDX(last_dir->dirnum) - pidx) :
273 (pidx - PD_IDX(last_dir->dirnum))
274 < (PD_IDX(prev_dir->dirnum) > pidx) ?
275 (PD_IDX(prev_dir->dirnum) - pidx) :
276 (pidx - PD_IDX(prev_dir->dirnum)))
277 *pdi = last_dir;
278 else
279 *pdi = prev_dir;
280
281 if (PD_IDX((*pdi)->dirnum) > pidx) {
282 for (spi = (*pdi)->prev;
283 spi != NULL && PD_IDX(spi->dirnum) > pidx;
284 spi = spi->prev)
285 *pdi = spi;
286 if (spi != NULL)
287 *pdi = spi;
288 } else
289 for (spi = (*pdi)->next;
290 spi != NULL && PD_IDX(spi->dirnum) <= pidx;
291 spi = spi->next)
292 *pdi = spi;
293 } else {
294 *pdi = (struct pdinfo *) ((caddr_t) page_dir + pdi_off);
295 for (spi = *pdi;
296 spi != NULL && PD_IDX(spi->dirnum) <= pidx;
297 spi = spi->next)
298 *pdi = spi;
299 }
300
301 return ((PD_IDX((*pdi)->dirnum) == pidx) ? 0 :
302 (PD_IDX((*pdi)->dirnum) > pidx) ? 1 : -1);
303}
304
305#ifdef MALLOC_STATS
306void
307malloc_dump(int fd)
308{
309 char buf[1024];
310 struct pginfo **pd;
311 struct pgfree *pf;
312 struct pdinfo *pi;
313 u_long j;
314
315 pd = page_dir;
316 pi = (struct pdinfo *) ((caddr_t) pd + pdi_off);
317
318 /* print out all the pages */
319 for (j = 0; j <= last_index;) {
320 snprintf(buf, sizeof buf, "%08lx %5lu ", j << malloc_pageshift, j);
321 write(fd, buf, strlen(buf));
322 if (pd[PI_OFF(j)] == MALLOC_NOT_MINE) {
323 for (j++; j <= last_index && pd[PI_OFF(j)] == MALLOC_NOT_MINE;) {
324 if (!PI_OFF(++j)) {
325 if ((pi = pi->next) == NULL ||
326 PD_IDX(pi->dirnum) != PI_IDX(j))
327 break;
328 pd = pi->base;
329 j += pdi_mod;
330 }
331 }
332 j--;
333 snprintf(buf, sizeof buf, ".. %5lu not mine\n", j);
334 write(fd, buf, strlen(buf));
335 } else if (pd[PI_OFF(j)] == MALLOC_FREE) {
336 for (j++; j <= last_index && pd[PI_OFF(j)] == MALLOC_FREE;) {
337 if (!PI_OFF(++j)) {
338 if ((pi = pi->next) == NULL ||
339 PD_IDX(pi->dirnum) != PI_IDX(j))
340 break;
341 pd = pi->base;
342 j += pdi_mod;
343 }
344 }
345 j--;
346 snprintf(buf, sizeof buf, ".. %5lu free\n", j);
347 write(fd, buf, strlen(buf));
348 } else if (pd[PI_OFF(j)] == MALLOC_FIRST) {
349 for (j++; j <= last_index && pd[PI_OFF(j)] == MALLOC_FOLLOW;) {
350 if (!PI_OFF(++j)) {
351 if ((pi = pi->next) == NULL ||
352 PD_IDX(pi->dirnum) != PI_IDX(j))
353 break;
354 pd = pi->base;
355 j += pdi_mod;
356 }
357 }
358 j--;
359 snprintf(buf, sizeof buf, ".. %5lu in use\n", j);
360 write(fd, buf, strlen(buf));
361 } else if (pd[PI_OFF(j)] < MALLOC_MAGIC) {
362 snprintf(buf, sizeof buf, "(%p)\n", pd[PI_OFF(j)]);
363 write(fd, buf, strlen(buf));
364 } else {
365 snprintf(buf, sizeof buf, "%p %d (of %d) x %d @ %p --> %p\n",
366 pd[PI_OFF(j)], pd[PI_OFF(j)]->free,
367 pd[PI_OFF(j)]->total, pd[PI_OFF(j)]->size,
368 pd[PI_OFF(j)]->page, pd[PI_OFF(j)]->next);
369 write(fd, buf, strlen(buf));
370 }
371 if (!PI_OFF(++j)) {
372 if ((pi = pi->next) == NULL)
373 break;
374 pd = pi->base;
375 j += (1 + PD_IDX(pi->dirnum) - PI_IDX(j)) * pdi_mod;
376 }
377 }
378
379 for (pf = free_list.next; pf; pf = pf->next) {
380 snprintf(buf, sizeof buf, "Free: @%p [%p...%p[ %ld ->%p <-%p\n",
381 pf, pf->page, (char *)pf->page + pf->size,
382 pf->size, pf->prev, pf->next);
383 write(fd, buf, strlen(buf));
384 if (pf == pf->next) {
385 snprintf(buf, sizeof buf, "Free_list loops\n");
386 write(fd, buf, strlen(buf));
387 break;
388 }
389 }
390
391 /* print out various info */
392 snprintf(buf, sizeof buf, "Minsize\t%lu\n", malloc_minsize);
393 write(fd, buf, strlen(buf));
394 snprintf(buf, sizeof buf, "Maxsize\t%lu\n", malloc_maxsize);
395 write(fd, buf, strlen(buf));
396 snprintf(buf, sizeof buf, "Pagesize\t%lu\n", malloc_pagesize);
397 write(fd, buf, strlen(buf));
398 snprintf(buf, sizeof buf, "Pageshift\t%u\n", malloc_pageshift);
399 write(fd, buf, strlen(buf));
400 snprintf(buf, sizeof buf, "In use\t%lu\n", (u_long) malloc_used);
401 write(fd, buf, strlen(buf));
402 snprintf(buf, sizeof buf, "Guarded\t%lu\n", (u_long) malloc_guarded);
403 write(fd, buf, strlen(buf));
404}
405#endif /* MALLOC_STATS */
406
407extern char *__progname;
408
409static void
410wrterror(char *p)
411{
412 char *q = " error: ";
413 struct iovec iov[5];
414
415 iov[0].iov_base = __progname;
416 iov[0].iov_len = strlen(__progname);
417 iov[1].iov_base = malloc_func;
418 iov[1].iov_len = strlen(malloc_func);
419 iov[2].iov_base = q;
420 iov[2].iov_len = strlen(q);
421 iov[3].iov_base = p;
422 iov[3].iov_len = strlen(p);
423 iov[4].iov_base = "\n";
424 iov[4].iov_len = 1;
425 writev(STDERR_FILENO, iov, 5);
426
427 suicide = 1;
428#ifdef MALLOC_STATS
429 if (malloc_stats)
430 malloc_dump(STDERR_FILENO);
431#endif /* MALLOC_STATS */
432 malloc_active--;
433 if (malloc_abort)
434 abort();
435}
436
437static void
438wrtwarning(char *p)
439{
440 char *q = " warning: ";
441 struct iovec iov[5];
442
443 if (malloc_abort)
444 wrterror(p);
445 else if (malloc_silent)
446 return;
447
448 iov[0].iov_base = __progname;
449 iov[0].iov_len = strlen(__progname);
450 iov[1].iov_base = malloc_func;
451 iov[1].iov_len = strlen(malloc_func);
452 iov[2].iov_base = q;
453 iov[2].iov_len = strlen(q);
454 iov[3].iov_base = p;
455 iov[3].iov_len = strlen(p);
456 iov[4].iov_base = "\n";
457 iov[4].iov_len = 1;
458
459 writev(STDERR_FILENO, iov, 5);
460}
461
462#ifdef MALLOC_STATS
463static void
464malloc_exit(void)
465{
466 char *q = "malloc() warning: Couldn't dump stats\n";
467 int save_errno = errno, fd;
468
469 fd = open("malloc.out", O_RDWR|O_APPEND);
470 if (fd != -1) {
471 malloc_dump(fd);
472 close(fd);
473 } else
474 write(STDERR_FILENO, q, strlen(q));
475 errno = save_errno;
476}
477#endif /* MALLOC_STATS */
478
479/*
480 * Allocate a number of pages from the OS
481 */
482static void *
483map_pages(size_t pages)
484{
485 struct pdinfo *pi, *spi;
486 struct pginfo **pd;
487 u_long idx, pidx, lidx;
488 caddr_t result, tail;
489 u_long index, lindex;
490 void *pdregion = NULL;
491 size_t dirs, cnt;
492
493 pages <<= malloc_pageshift;
494 result = MMAP(pages + malloc_guard);
495 if (result == MAP_FAILED) {
496#ifdef MALLOC_EXTRA_SANITY
497 wrtwarning("(ES): map_pages fails");
498#endif /* MALLOC_EXTRA_SANITY */
499 errno = ENOMEM;
500 return (NULL);
501 }
502 index = ptr2index(result);
503 tail = result + pages + malloc_guard;
504 lindex = ptr2index(tail) - 1;
505 if (malloc_guard)
506 mprotect(result + pages, malloc_guard, PROT_NONE);
507
508 pidx = PI_IDX(index);
509 lidx = PI_IDX(lindex);
510
511 if (tail > malloc_brk) {
512 malloc_brk = tail;
513 last_index = lindex;
514 }
515
516 dirs = lidx - pidx;
517
518 /* Insert directory pages, if needed. */
519 if (pdir_lookup(index, &pi) != 0)
520 dirs++;
521
522 if (dirs > 0) {
523 pdregion = MMAP(malloc_pagesize * dirs);
524 if (pdregion == MAP_FAILED) {
525 munmap(result, tail - result);
526#ifdef MALLOC_EXTRA_SANITY
527 wrtwarning("(ES): map_pages fails");
528#endif
529 errno = ENOMEM;
530 return (NULL);
531 }
532 }
533
534 cnt = 0;
535 for (idx = pidx, spi = pi; idx <= lidx; idx++) {
536 if (pi == NULL || PD_IDX(pi->dirnum) != idx) {
537 pd = (struct pginfo **)((char *)pdregion +
538 cnt * malloc_pagesize);
539 cnt++;
540 memset(pd, 0, malloc_pagesize);
541 pi = (struct pdinfo *) ((caddr_t) pd + pdi_off);
542 pi->base = pd;
543 pi->prev = spi;
544 pi->next = spi->next;
545 pi->dirnum = idx * (malloc_pagesize /
546 sizeof(struct pginfo *));
547
548 if (spi->next != NULL)
549 spi->next->prev = pi;
550 spi->next = pi;
551 }
552 if (idx > pidx && idx < lidx) {
553 pi->dirnum += pdi_mod;
554 } else if (idx == pidx) {
555 if (pidx == lidx) {
556 pi->dirnum += (u_long)(tail - result) >>
557 malloc_pageshift;
558 } else {
559 pi->dirnum += pdi_mod - PI_OFF(index);
560 }
561 } else {
562 pi->dirnum += PI_OFF(ptr2index(tail - 1)) + 1;
563 }
564#ifdef MALLOC_EXTRA_SANITY
565 if (PD_OFF(pi->dirnum) > pdi_mod || PD_IDX(pi->dirnum) > idx) {
566 wrterror("(ES): pages directory overflow");
567 errno = EFAULT;
568 return (NULL);
569 }
570#endif /* MALLOC_EXTRA_SANITY */
571 if (idx == pidx && pi != last_dir) {
572 prev_dir = last_dir;
573 last_dir = pi;
574 }
575 spi = pi;
576 pi = spi->next;
577 }
578#ifdef MALLOC_EXTRA_SANITY
579 if (cnt > dirs)
580 wrtwarning("(ES): cnt > dirs");
581#endif /* MALLOC_EXTRA_SANITY */
582 if (cnt < dirs)
583 munmap((char *)pdregion + cnt * malloc_pagesize,
584 (dirs - cnt) * malloc_pagesize);
585
586 return (result);
587}
588
589/*
590 * Initialize the world
591 */
592static void
593malloc_init(void)
594{
595 char *p, b[64];
596 int i, j, save_errno = errno;
597
598 _MALLOC_LOCK_INIT();
599
600#ifdef MALLOC_EXTRA_SANITY
601 malloc_junk = 1;
602#endif /* MALLOC_EXTRA_SANITY */
603
604 for (i = 0; i < 3; i++) {
605 switch (i) {
606 case 0:
607 j = readlink("/etc/malloc.conf", b, sizeof b - 1);
608 if (j <= 0)
609 continue;
610 b[j] = '\0';
611 p = b;
612 break;
613 case 1:
614 if (issetugid() == 0)
615 p = getenv("MALLOC_OPTIONS");
616 else
617 continue;
618 break;
619 case 2:
620 p = malloc_options;
621 break;
622 default:
623 p = NULL;
624 }
625
626 for (; p != NULL && *p != '\0'; p++) {
627 switch (*p) {
628 case '>':
629 malloc_cache <<= 1;
630 break;
631 case '<':
632 malloc_cache >>= 1;
633 break;
634 case 'a':
635 malloc_abort = 0;
636 break;
637 case 'A':
638 malloc_abort = 1;
639 break;
640#ifdef MALLOC_STATS
641 case 'd':
642 malloc_stats = 0;
643 break;
644 case 'D':
645 malloc_stats = 1;
646 break;
647#endif /* MALLOC_STATS */
648 case 'f':
649 malloc_freeprot = 0;
650 break;
651 case 'F':
652 malloc_freeprot = 1;
653 break;
654 case 'g':
655 malloc_guard = 0;
656 break;
657 case 'G':
658 malloc_guard = malloc_pagesize;
659 break;
660 case 'h':
661 malloc_hint = 0;
662 break;
663 case 'H':
664 malloc_hint = 1;
665 break;
666 case 'j':
667 malloc_junk = 0;
668 break;
669 case 'J':
670 malloc_junk = 1;
671 break;
672 case 'n':
673 malloc_silent = 0;
674 break;
675 case 'N':
676 malloc_silent = 1;
677 break;
678 case 'p':
679 malloc_ptrguard = 0;
680 break;
681 case 'P':
682 malloc_ptrguard = 1;
683 break;
684 case 'r':
685 malloc_realloc = 0;
686 break;
687 case 'R':
688 malloc_realloc = 1;
689 break;
690#ifdef __FreeBSD__
691 case 'u':
692 malloc_utrace = 0;
693 break;
694 case 'U':
695 malloc_utrace = 1;
696 break;
697#endif /* __FreeBSD__ */
698 case 'x':
699 malloc_xmalloc = 0;
700 break;
701 case 'X':
702 malloc_xmalloc = 1;
703 break;
704 case 'z':
705 malloc_zero = 0;
706 break;
707 case 'Z':
708 malloc_zero = 1;
709 break;
710 default:
711 j = malloc_abort;
712 malloc_abort = 0;
713 wrtwarning("unknown char in MALLOC_OPTIONS");
714 malloc_abort = j;
715 break;
716 }
717 }
718 }
719
720 UTRACE(0, 0, 0);
721
722 /*
723 * We want junk in the entire allocation, and zero only in the part
724 * the user asked for.
725 */
726 if (malloc_zero)
727 malloc_junk = 1;
728
729#ifdef MALLOC_STATS
730 if (malloc_stats && (atexit(malloc_exit) == -1))
731 wrtwarning("atexit(2) failed."
732 " Will not be able to dump malloc stats on exit");
733#endif /* MALLOC_STATS */
734
735 /* Allocate one page for the page directory. */
736 page_dir = (struct pginfo **)MMAP(malloc_pagesize);
737
738 if (page_dir == MAP_FAILED) {
739 wrterror("mmap(2) failed, check limits");
740 errno = ENOMEM;
741 return;
742 }
743 pdi_off = (malloc_pagesize - sizeof(struct pdinfo)) & ~(malloc_minsize - 1);
744 pdi_mod = pdi_off / sizeof(struct pginfo *);
745
746 last_dir = (struct pdinfo *) ((caddr_t) page_dir + pdi_off);
747 last_dir->base = page_dir;
748 last_dir->prev = last_dir->next = NULL;
749 last_dir->dirnum = malloc_pageshift;
750
751 /* Been here, done that. */
752 malloc_started++;
753
754 /* Recalculate the cache size in bytes, and make sure it's nonzero. */
755 if (!malloc_cache)
756 malloc_cache++;
757 malloc_cache <<= malloc_pageshift;
758 errno = save_errno;
759}
760
761/*
762 * Allocate a number of complete pages
763 */
764static void *
765malloc_pages(size_t size)
766{
767 void *p, *delay_free = NULL, *tp;
768 int i;
769 struct pginfo **pd;
770 struct pdinfo *pi;
771 u_long pidx, index;
772 struct pgfree *pf;
773
774 size = pageround(size) + malloc_guard;
775
776 p = NULL;
777 /* Look for free pages before asking for more */
778 for (pf = free_list.next; pf; pf = pf->next) {
779
780#ifdef MALLOC_EXTRA_SANITY
781 if (pf->size & malloc_pagemask) {
782 wrterror("(ES): junk length entry on free_list");
783 errno = EFAULT;
784 return (NULL);
785 }
786 if (!pf->size) {
787 wrterror("(ES): zero length entry on free_list");
788 errno = EFAULT;
789 return (NULL);
790 }
791 if (pf->page > (pf->page + pf->size)) {
792 wrterror("(ES): sick entry on free_list");
793 errno = EFAULT;
794 return (NULL);
795 }
796 if ((pi = pf->pdir) == NULL) {
797 wrterror("(ES): invalid page directory on free-list");
798 errno = EFAULT;
799 return (NULL);
800 }
801 if ((pidx = PI_IDX(ptr2index(pf->page))) != PD_IDX(pi->dirnum)) {
802 wrterror("(ES): directory index mismatch on free-list");
803 errno = EFAULT;
804 return (NULL);
805 }
806 pd = pi->base;
807 if (pd[PI_OFF(ptr2index(pf->page))] != MALLOC_FREE) {
808 wrterror("(ES): non-free first page on free-list");
809 errno = EFAULT;
810 return (NULL);
811 }
812 pidx = PI_IDX(ptr2index((pf->page) + (pf->size)) - 1);
813 for (pi = pf->pdir; pi != NULL && PD_IDX(pi->dirnum) < pidx;
814 pi = pi->next)
815 ;
816 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
817 wrterror("(ES): last page not referenced in page directory");
818 errno = EFAULT;
819 return (NULL);
820 }
821 pd = pi->base;
822 if (pd[PI_OFF(ptr2index((pf->page) + (pf->size)) - 1)] != MALLOC_FREE) {
823 wrterror("(ES): non-free last page on free-list");
824 errno = EFAULT;
825 return (NULL);
826 }
827#endif /* MALLOC_EXTRA_SANITY */
828
829 if (pf->size < size)
830 continue;
831
832 if (pf->size == size) {
833 p = pf->page;
834 pi = pf->pdir;
835 if (pf->next != NULL)
836 pf->next->prev = pf->prev;
837 pf->prev->next = pf->next;
838 delay_free = pf;
839 break;
840 }
841 p = pf->page;
842 pf->page = (char *) pf->page + size;
843 pf->size -= size;
844 pidx = PI_IDX(ptr2index(pf->page));
845 for (pi = pf->pdir; pi != NULL && PD_IDX(pi->dirnum) < pidx;
846 pi = pi->next)
847 ;
848 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
849 wrterror("(ES): hole in directories");
850 errno = EFAULT;
851 return (NULL);
852 }
853 tp = pf->pdir;
854 pf->pdir = pi;
855 pi = tp;
856 break;
857 }
858
859 size -= malloc_guard;
860
861#ifdef MALLOC_EXTRA_SANITY
862 if (p != NULL && pi != NULL) {
863 pidx = PD_IDX(pi->dirnum);
864 pd = pi->base;
865 }
866 if (p != NULL && pd[PI_OFF(ptr2index(p))] != MALLOC_FREE) {
867 wrterror("(ES): allocated non-free page on free-list");
868 errno = EFAULT;
869 return (NULL);
870 }
871#endif /* MALLOC_EXTRA_SANITY */
872
873 if (p != NULL && (malloc_guard || malloc_freeprot))
874 mprotect(p, size, PROT_READ | PROT_WRITE);
875
876 size >>= malloc_pageshift;
877
878 /* Map new pages */
879 if (p == NULL)
880 p = map_pages(size);
881
882 if (p != NULL) {
883 index = ptr2index(p);
884 pidx = PI_IDX(index);
885 pdir_lookup(index, &pi);
886#ifdef MALLOC_EXTRA_SANITY
887 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
888 wrterror("(ES): mapped pages not found in directory");
889 errno = EFAULT;
890 return (NULL);
891 }
892#endif /* MALLOC_EXTRA_SANITY */
893 if (pi != last_dir) {
894 prev_dir = last_dir;
895 last_dir = pi;
896 }
897 pd = pi->base;
898 pd[PI_OFF(index)] = MALLOC_FIRST;
899 for (i = 1; i < size; i++) {
900 if (!PI_OFF(index + i)) {
901 pidx++;
902 pi = pi->next;
903#ifdef MALLOC_EXTRA_SANITY
904 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
905 wrterror("(ES): hole in mapped pages directory");
906 errno = EFAULT;
907 return (NULL);
908 }
909#endif /* MALLOC_EXTRA_SANITY */
910 pd = pi->base;
911 }
912 pd[PI_OFF(index + i)] = MALLOC_FOLLOW;
913 }
914 if (malloc_guard) {
915 if (!PI_OFF(index + i)) {
916 pidx++;
917 pi = pi->next;
918#ifdef MALLOC_EXTRA_SANITY
919 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
920 wrterror("(ES): hole in mapped pages directory");
921 errno = EFAULT;
922 return (NULL);
923 }
924#endif /* MALLOC_EXTRA_SANITY */
925 pd = pi->base;
926 }
927 pd[PI_OFF(index + i)] = MALLOC_FIRST;
928 }
929 malloc_used += size << malloc_pageshift;
930 malloc_guarded += malloc_guard;
931
932 if (malloc_junk)
933 memset(p, SOME_JUNK, size << malloc_pageshift);
934 }
935 if (delay_free) {
936 if (px == NULL)
937 px = delay_free;
938 else
939 ifree(delay_free);
940 }
941 return (p);
942}
943
944/*
945 * Allocate a page of fragments
946 */
947
948static __inline__ int
949malloc_make_chunks(int bits)
950{
951 struct pginfo *bp, **pd;
952 struct pdinfo *pi;
953#ifdef MALLOC_EXTRA_SANITY
954 u_long pidx;
955#endif /* MALLOC_EXTRA_SANITY */
956 void *pp;
957 long i, k;
958 size_t l;
959
960 /* Allocate a new bucket */
961 pp = malloc_pages((size_t) malloc_pagesize);
962 if (pp == NULL)
963 return (0);
964
965 /* Find length of admin structure */
966 l = sizeof *bp - sizeof(u_long);
967 l += sizeof(u_long) *
968 (((malloc_pagesize >> bits) + MALLOC_BITS - 1) / MALLOC_BITS);
969
970 /* Don't waste more than two chunks on this */
971
972 /*
973 * If we are to allocate a memory protected page for the malloc(0)
974 * case (when bits=0), it must be from a different page than the
975 * pginfo page.
976 * --> Treat it like the big chunk alloc, get a second data page.
977 */
978 if (bits != 0 && (1UL << (bits)) <= l + l) {
979 bp = (struct pginfo *) pp;
980 } else {
981 bp = (struct pginfo *) imalloc(l);
982 if (bp == NULL) {
983 ifree(pp);
984 return (0);
985 }
986 }
987
988 /* memory protect the page allocated in the malloc(0) case */
989 if (bits == 0) {
990 bp->size = 0;
991 bp->shift = 1;
992 i = malloc_minsize - 1;
993 while (i >>= 1)
994 bp->shift++;
995 bp->total = bp->free = malloc_pagesize >> bp->shift;
996 bp->page = pp;
997
998 k = mprotect(pp, malloc_pagesize, PROT_NONE);
999 if (k < 0) {
1000 ifree(pp);
1001 ifree(bp);
1002 return (0);
1003 }
1004 } else {
1005 bp->size = (1UL << bits);
1006 bp->shift = bits;
1007 bp->total = bp->free = malloc_pagesize >> bits;
1008 bp->page = pp;
1009 }
1010
1011 /* set all valid bits in the bitmap */
1012 k = bp->total;
1013 i = 0;
1014
1015 /* Do a bunch at a time */
1016 for (; (k - i) >= MALLOC_BITS; i += MALLOC_BITS)
1017 bp->bits[i / MALLOC_BITS] = ~0UL;
1018
1019 for (; i < k; i++)
1020 bp->bits[i / MALLOC_BITS] |= 1UL << (i % MALLOC_BITS);
1021
1022 k = (long)l;
1023 if (bp == bp->page) {
1024 /* Mark the ones we stole for ourselves */
1025 for (i = 0; k > 0; i++) {
1026 bp->bits[i / MALLOC_BITS] &= ~(1UL << (i % MALLOC_BITS));
1027 bp->free--;
1028 bp->total--;
1029 k -= (1 << bits);
1030 }
1031 }
1032 /* MALLOC_LOCK */
1033
1034 pdir_lookup(ptr2index(pp), &pi);
1035#ifdef MALLOC_EXTRA_SANITY
1036 pidx = PI_IDX(ptr2index(pp));
1037 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1038 wrterror("(ES): mapped pages not found in directory");
1039 errno = EFAULT;
1040 return (0);
1041 }
1042#endif /* MALLOC_EXTRA_SANITY */
1043 if (pi != last_dir) {
1044 prev_dir = last_dir;
1045 last_dir = pi;
1046 }
1047 pd = pi->base;
1048 pd[PI_OFF(ptr2index(pp))] = bp;
1049
1050 bp->next = page_dir[bits];
1051 page_dir[bits] = bp;
1052
1053 /* MALLOC_UNLOCK */
1054 return (1);
1055}
1056
1057/*
1058 * Allocate a fragment
1059 */
1060static void *
1061malloc_bytes(size_t size)
1062{
1063 int i, j;
1064 size_t k;
1065 u_long u, *lp;
1066 struct pginfo *bp;
1067
1068 /* Don't bother with anything less than this */
1069 /* unless we have a malloc(0) requests */
1070 if (size != 0 && size < malloc_minsize)
1071 size = malloc_minsize;
1072
1073 /* Find the right bucket */
1074 if (size == 0)
1075 j = 0;
1076 else {
1077 j = 1;
1078 i = size - 1;
1079 while (i >>= 1)
1080 j++;
1081 }
1082
1083 /* If it's empty, make a page more of that size chunks */
1084 if (page_dir[j] == NULL && !malloc_make_chunks(j))
1085 return (NULL);
1086
1087 bp = page_dir[j];
1088
1089 /* Find first word of bitmap which isn't empty */
1090 for (lp = bp->bits; !*lp; lp++);
1091
1092 /* Find that bit, and tweak it */
1093 u = 1;
1094 k = 0;
1095 while (!(*lp & u)) {
1096 u += u;
1097 k++;
1098 }
1099
1100 if (malloc_guard) {
1101 /* Walk to a random position. */
1102 i = arc4random() % bp->free;
1103 while (i > 0) {
1104 u += u;
1105 k++;
1106 if (k >= MALLOC_BITS) {
1107 lp++;
1108 u = 1;
1109 k = 0;
1110 }
1111#ifdef MALLOC_EXTRA_SANITY
1112 if (lp - bp->bits > (bp->total - 1) / MALLOC_BITS) {
1113 wrterror("chunk overflow");
1114 errno = EFAULT;
1115 return (NULL);
1116 }
1117#endif /* MALLOC_EXTRA_SANITY */
1118 if (*lp & u)
1119 i--;
1120 }
1121 }
1122 *lp ^= u;
1123
1124 /* If there are no more free, remove from free-list */
1125 if (!--bp->free) {
1126 page_dir[j] = bp->next;
1127 bp->next = NULL;
1128 }
1129 /* Adjust to the real offset of that chunk */
1130 k += (lp - bp->bits) * MALLOC_BITS;
1131 k <<= bp->shift;
1132
1133 if (malloc_junk && bp->size != 0)
1134 memset((char *)bp->page + k, SOME_JUNK, (size_t)bp->size);
1135
1136 return ((u_char *) bp->page + k);
1137}
1138
1139/*
1140 * Magic so that malloc(sizeof(ptr)) is near the end of the page.
1141 */
1142#define PTR_GAP (malloc_pagesize - sizeof(void *))
1143#define PTR_SIZE (sizeof(void *))
1144#define PTR_ALIGNED(p) (((unsigned long)p & malloc_pagemask) == PTR_GAP)
1145
1146/*
1147 * Allocate a piece of memory
1148 */
1149static void *
1150imalloc(size_t size)
1151{
1152 void *result;
1153 int ptralloc = 0;
1154
1155 if (!malloc_started)
1156 malloc_init();
1157
1158 if (suicide)
1159 abort();
1160
1161 /* does not matter if malloc_bytes fails */
1162 if (px == NULL)
1163 px = malloc_bytes(sizeof *px);
1164
1165 if (malloc_ptrguard && size == PTR_SIZE) {
1166 ptralloc = 1;
1167 size = malloc_pagesize;
1168 }
1169 if ((size + malloc_pagesize) < size) { /* Check for overflow */
1170 result = NULL;
1171 errno = ENOMEM;
1172 } else if (size <= malloc_maxsize)
1173 result = malloc_bytes(size);
1174 else
1175 result = malloc_pages(size);
1176
1177 if (malloc_abort == 1 && result == NULL)
1178 wrterror("allocation failed");
1179
1180 if (malloc_zero && result != NULL)
1181 memset(result, 0, size);
1182
1183 if (result && ptralloc)
1184 return ((char *) result + PTR_GAP);
1185 return (result);
1186}
1187
1188/*
1189 * Change the size of an allocation.
1190 */
1191static void *
1192irealloc(void *ptr, size_t size)
1193{
1194 void *p;
1195 size_t osize;
1196 u_long index, i;
1197 struct pginfo **mp;
1198 struct pginfo **pd;
1199 struct pdinfo *pi;
1200#ifdef MALLOC_EXTRA_SANITY
1201 u_long pidx;
1202#endif /* MALLOC_EXTRA_SANITY */
1203
1204 if (suicide)
1205 abort();
1206
1207 if (!malloc_started) {
1208 wrtwarning("malloc() has never been called");
1209 return (NULL);
1210 }
1211 if (malloc_ptrguard && PTR_ALIGNED(ptr)) {
1212 if (size <= PTR_SIZE)
1213 return (ptr);
1214
1215 p = imalloc(size);
1216 if (p)
1217 memcpy(p, ptr, PTR_SIZE);
1218 ifree(ptr);
1219 return (p);
1220 }
1221 index = ptr2index(ptr);
1222
1223 if (index < malloc_pageshift) {
1224 wrtwarning("junk pointer, too low to make sense");
1225 return (NULL);
1226 }
1227 if (index > last_index) {
1228 wrtwarning("junk pointer, too high to make sense");
1229 return (NULL);
1230 }
1231 pdir_lookup(index, &pi);
1232#ifdef MALLOC_EXTRA_SANITY
1233 pidx = PI_IDX(index);
1234 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1235 wrterror("(ES): mapped pages not found in directory");
1236 errno = EFAULT;
1237 return (NULL);
1238 }
1239#endif /* MALLOC_EXTRA_SANITY */
1240 if (pi != last_dir) {
1241 prev_dir = last_dir;
1242 last_dir = pi;
1243 }
1244 pd = pi->base;
1245 mp = &pd[PI_OFF(index)];
1246
1247 if (*mp == MALLOC_FIRST) { /* Page allocation */
1248
1249 /* Check the pointer */
1250 if ((u_long) ptr & malloc_pagemask) {
1251 wrtwarning("modified (page-) pointer");
1252 return (NULL);
1253 }
1254 /* Find the size in bytes */
1255 i = index;
1256 if (!PI_OFF(++i)) {
1257 pi = pi->next;
1258 if (pi != NULL && PD_IDX(pi->dirnum) != PI_IDX(i))
1259 pi = NULL;
1260 if (pi != NULL)
1261 pd = pi->base;
1262 }
1263 for (osize = malloc_pagesize;
1264 pi != NULL && pd[PI_OFF(i)] == MALLOC_FOLLOW;) {
1265 osize += malloc_pagesize;
1266 if (!PI_OFF(++i)) {
1267 pi = pi->next;
1268 if (pi != NULL && PD_IDX(pi->dirnum) != PI_IDX(i))
1269 pi = NULL;
1270 if (pi != NULL)
1271 pd = pi->base;
1272 }
1273 }
1274
1275 if (!malloc_realloc && size <= osize &&
1276 size > osize - malloc_pagesize) {
1277 if (malloc_junk)
1278 memset((char *)ptr + size, SOME_JUNK, osize - size);
1279 return (ptr); /* ..don't do anything else. */
1280 }
1281 } else if (*mp >= MALLOC_MAGIC) { /* Chunk allocation */
1282
1283 /* Check the pointer for sane values */
1284 if ((u_long) ptr & ((1UL << ((*mp)->shift)) - 1)) {
1285 wrtwarning("modified (chunk-) pointer");
1286 return (NULL);
1287 }
1288 /* Find the chunk index in the page */
1289 i = ((u_long) ptr & malloc_pagemask) >> (*mp)->shift;
1290
1291 /* Verify that it isn't a free chunk already */
1292 if ((*mp)->bits[i / MALLOC_BITS] & (1UL << (i % MALLOC_BITS))) {
1293 wrtwarning("chunk is already free");
1294 return (NULL);
1295 }
1296 osize = (*mp)->size;
1297
1298 if (!malloc_realloc && size <= osize &&
1299 (size > osize / 2 || osize == malloc_minsize)) {
1300 if (malloc_junk)
1301 memset((char *) ptr + size, SOME_JUNK, osize - size);
1302 return (ptr); /* ..don't do anything else. */
1303 }
1304 } else {
1305 wrtwarning("irealloc: pointer to wrong page");
1306 return (NULL);
1307 }
1308
1309 p = imalloc(size);
1310
1311 if (p != NULL) {
1312 /* copy the lesser of the two sizes, and free the old one */
1313 /* Don't move from/to 0 sized region !!! */
1314 if (osize != 0 && size != 0) {
1315 if (osize < size)
1316 memcpy(p, ptr, osize);
1317 else
1318 memcpy(p, ptr, size);
1319 }
1320 ifree(ptr);
1321 }
1322 return (p);
1323}
1324
1325/*
1326 * Free a sequence of pages
1327 */
1328static __inline__ void
1329free_pages(void *ptr, u_long index, struct pginfo * info)
1330{
1331 u_long i, pidx, lidx;
1332 size_t l, cachesize = 0;
1333 struct pginfo **pd;
1334 struct pdinfo *pi, *spi;
1335 struct pgfree *pf, *pt = NULL;
1336 caddr_t tail;
1337
1338 if (info == MALLOC_FREE) {
1339 wrtwarning("page is already free");
1340 return;
1341 }
1342 if (info != MALLOC_FIRST) {
1343 wrtwarning("free_pages: pointer to wrong page");
1344 return;
1345 }
1346 if ((u_long) ptr & malloc_pagemask) {
1347 wrtwarning("modified (page-) pointer");
1348 return;
1349 }
1350 /* Count how many pages and mark them free at the same time */
1351 pidx = PI_IDX(index);
1352 pdir_lookup(index, &pi);
1353#ifdef MALLOC_EXTRA_SANITY
1354 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1355 wrterror("(ES): mapped pages not found in directory");
1356 errno = EFAULT;
1357 return;
1358 }
1359#endif /* MALLOC_EXTRA_SANITY */
1360
1361 spi = pi; /* Save page index for start of region. */
1362
1363 pd = pi->base;
1364 pd[PI_OFF(index)] = MALLOC_FREE;
1365 i = 1;
1366 if (!PI_OFF(index + i)) {
1367 pi = pi->next;
1368 if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(index + i))
1369 pi = NULL;
1370 else
1371 pd = pi->base;
1372 }
1373 while (pi != NULL && pd[PI_OFF(index + i)] == MALLOC_FOLLOW) {
1374 pd[PI_OFF(index + i)] = MALLOC_FREE;
1375 i++;
1376 if (!PI_OFF(index + i)) {
1377 if ((pi = pi->next) == NULL ||
1378 PD_IDX(pi->dirnum) != PI_IDX(index + i))
1379 pi = NULL;
1380 else
1381 pd = pi->base;
1382 }
1383 }
1384
1385 l = i << malloc_pageshift;
1386
1387 if (malloc_junk)
1388 memset(ptr, SOME_JUNK, l);
1389
1390 malloc_used -= l;
1391 malloc_guarded -= malloc_guard;
1392 if (malloc_guard) {
1393#ifdef MALLOC_EXTRA_SANITY
1394 if (pi == NULL || PD_IDX(pi->dirnum) != PI_IDX(index + i)) {
1395 wrterror("(ES): hole in mapped pages directory");
1396 errno = EFAULT;
1397 return;
1398 }
1399#endif /* MALLOC_EXTRA_SANITY */
1400 pd[PI_OFF(index + i)] = MALLOC_FREE;
1401 l += malloc_guard;
1402 }
1403 tail = (caddr_t)ptr + l;
1404
1405 if (malloc_hint)
1406 madvise(ptr, l, MADV_FREE);
1407
1408 if (malloc_freeprot)
1409 mprotect(ptr, l, PROT_NONE);
1410
1411 /* Add to free-list. */
1412 if (px == NULL && (px = malloc_bytes(sizeof *px)) == NULL)
1413 goto not_return;
1414 px->page = ptr;
1415 px->pdir = spi;
1416 px->size = l;
1417
1418 if (free_list.next == NULL) {
1419 /* Nothing on free list, put this at head. */
1420 px->next = NULL;
1421 px->prev = &free_list;
1422 free_list.next = px;
1423 pf = px;
1424 px = NULL;
1425 } else {
1426 /*
1427 * Find the right spot, leave pf pointing to the modified
1428 * entry.
1429 */
1430
1431 /* Race ahead here, while calculating cache size. */
1432 for (pf = free_list.next;
1433 (caddr_t)ptr > ((caddr_t)pf->page + pf->size)
1434 && pf->next != NULL;
1435 pf = pf->next)
1436 cachesize += pf->size;
1437
1438 /* Finish cache size calculation. */
1439 pt = pf;
1440 while (pt) {
1441 cachesize += pt->size;
1442 pt = pt->next;
1443 }
1444
1445 if ((caddr_t)pf->page > tail) {
1446 /* Insert before entry */
1447 px->next = pf;
1448 px->prev = pf->prev;
1449 pf->prev = px;
1450 px->prev->next = px;
1451 pf = px;
1452 px = NULL;
1453 } else if (((caddr_t)pf->page + pf->size) == ptr) {
1454 /* Append to the previous entry. */
1455 cachesize -= pf->size;
1456 pf->size += l;
1457 if (pf->next != NULL &&
1458 pf->next->page == ((caddr_t)pf->page + pf->size)) {
1459 /* And collapse the next too. */
1460 pt = pf->next;
1461 pf->size += pt->size;
1462 pf->next = pt->next;
1463 if (pf->next != NULL)
1464 pf->next->prev = pf;
1465 }
1466 } else if (pf->page == tail) {
1467 /* Prepend to entry. */
1468 cachesize -= pf->size;
1469 pf->size += l;
1470 pf->page = ptr;
1471 pf->pdir = spi;
1472 } else if (pf->next == NULL) {
1473 /* Append at tail of chain. */
1474 px->next = NULL;
1475 px->prev = pf;
1476 pf->next = px;
1477 pf = px;
1478 px = NULL;
1479 } else {
1480 wrterror("freelist is destroyed");
1481 errno = EFAULT;
1482 return;
1483 }
1484 }
1485
1486 if (pf->pdir != last_dir) {
1487 prev_dir = last_dir;
1488 last_dir = pf->pdir;
1489 }
1490
1491 /* Return something to OS ? */
1492 if (pf->size > (malloc_cache - cachesize)) {
1493
1494 /*
1495 * Keep the cache intact. Notice that the '>' above guarantees that
1496 * the pf will always have at least one page afterwards.
1497 */
1498 if (munmap((char *) pf->page + (malloc_cache - cachesize),
1499 pf->size - (malloc_cache - cachesize)) != 0)
1500 goto not_return;
1501 tail = (caddr_t)pf->page + pf->size;
1502 lidx = ptr2index(tail) - 1;
1503 pf->size = malloc_cache - cachesize;
1504
1505 index = ptr2index((caddr_t)pf->page + pf->size);
1506
1507 pidx = PI_IDX(index);
1508 if (prev_dir != NULL && PD_IDX(prev_dir->dirnum) >= pidx)
1509 prev_dir = NULL; /* Will be wiped out below ! */
1510
1511 for (pi = pf->pdir; pi != NULL && PD_IDX(pi->dirnum) < pidx;
1512 pi = pi->next)
1513 ;
1514
1515 spi = pi;
1516 if (pi != NULL && PD_IDX(pi->dirnum) == pidx) {
1517 pd = pi->base;
1518
1519 for (i = index; i <= lidx;) {
1520 if (pd[PI_OFF(i)] != MALLOC_NOT_MINE) {
1521 pd[PI_OFF(i)] = MALLOC_NOT_MINE;
1522#ifdef MALLOC_EXTRA_SANITY
1523 if (!PD_OFF(pi->dirnum)) {
1524 wrterror("(ES): pages directory underflow");
1525 errno = EFAULT;
1526 return;
1527 }
1528#endif /* MALLOC_EXTRA_SANITY */
1529 pi->dirnum--;
1530 }
1531#ifdef MALLOC_EXTRA_SANITY
1532 else
1533 wrtwarning("(ES): page already unmapped");
1534#endif /* MALLOC_EXTRA_SANITY */
1535 i++;
1536 if (!PI_OFF(i)) {
1537 /*
1538 * If no page in that dir, free
1539 * directory page.
1540 */
1541 if (!PD_OFF(pi->dirnum)) {
1542 /* Remove from list. */
1543 if (spi == pi)
1544 spi = pi->prev;
1545 if (pi->prev != NULL)
1546 pi->prev->next = pi->next;
1547 if (pi->next != NULL)
1548 pi->next->prev = pi->prev;
1549 pi = pi->next;
1550 munmap(pd, malloc_pagesize);
1551 } else
1552 pi = pi->next;
1553 if (pi == NULL ||
1554 PD_IDX(pi->dirnum) != PI_IDX(i))
1555 break;
1556 pd = pi->base;
1557 }
1558 }
1559 if (pi && !PD_OFF(pi->dirnum)) {
1560 /* Resulting page dir is now empty. */
1561 /* Remove from list. */
1562 if (spi == pi) /* Update spi only if first. */
1563 spi = pi->prev;
1564 if (pi->prev != NULL)
1565 pi->prev->next = pi->next;
1566 if (pi->next != NULL)
1567 pi->next->prev = pi->prev;
1568 pi = pi->next;
1569 munmap(pd, malloc_pagesize);
1570 }
1571 }
1572 if (pi == NULL && malloc_brk == tail) {
1573 /* Resize down the malloc upper boundary. */
1574 last_index = index - 1;
1575 malloc_brk = index2ptr(index);
1576 }
1577
1578 /* XXX: We could realloc/shrink the pagedir here I guess. */
1579 if (pf->size == 0) { /* Remove from free-list as well. */
1580 if (px)
1581 ifree(px);
1582 if ((px = pf->prev) != &free_list) {
1583 if (pi == NULL && last_index == (index - 1)) {
1584 if (spi == NULL) {
1585 malloc_brk = NULL;
1586 i = 11;
1587 } else {
1588 pd = spi->base;
1589 if (PD_IDX(spi->dirnum) < pidx)
1590 index =
1591 ((PD_IDX(spi->dirnum) + 1) *
1592 pdi_mod) - 1;
1593 for (pi = spi, i = index;
1594 pd[PI_OFF(i)] == MALLOC_NOT_MINE;
1595 i--)
1596#ifdef MALLOC_EXTRA_SANITY
1597 if (!PI_OFF(i)) {
1598 pi = pi->prev;
1599 if (pi == NULL || i == 0)
1600 break;
1601 pd = pi->base;
1602 i = (PD_IDX(pi->dirnum) + 1) * pdi_mod;
1603 }
1604#else /* !MALLOC_EXTRA_SANITY */
1605 {
1606 }
1607#endif /* MALLOC_EXTRA_SANITY */
1608 malloc_brk = index2ptr(i + 1);
1609 }
1610 last_index = i;
1611 }
1612 if ((px->next = pf->next) != NULL)
1613 px->next->prev = px;
1614 } else {
1615 if ((free_list.next = pf->next) != NULL)
1616 free_list.next->prev = &free_list;
1617 }
1618 px = pf;
1619 last_dir = prev_dir;
1620 prev_dir = NULL;
1621 }
1622 }
1623not_return:
1624 if (pt != NULL)
1625 ifree(pt);
1626}
1627
1628/*
1629 * Free a chunk, and possibly the page it's on, if the page becomes empty.
1630 */
1631
1632/* ARGSUSED */
1633static __inline__ void
1634free_bytes(void *ptr, u_long index, struct pginfo * info)
1635{
1636 struct pginfo **mp, **pd;
1637 struct pdinfo *pi;
1638#ifdef MALLOC_EXTRA_SANITY
1639 u_long pidx;
1640#endif /* MALLOC_EXTRA_SANITY */
1641 void *vp;
1642 long i;
1643
1644 /* Find the chunk number on the page */
1645 i = ((u_long) ptr & malloc_pagemask) >> info->shift;
1646
1647 if ((u_long) ptr & ((1UL << (info->shift)) - 1)) {
1648 wrtwarning("modified (chunk-) pointer");
1649 return;
1650 }
1651 if (info->bits[i / MALLOC_BITS] & (1UL << (i % MALLOC_BITS))) {
1652 wrtwarning("chunk is already free");
1653 return;
1654 }
1655 if (malloc_junk && info->size != 0)
1656 memset(ptr, SOME_JUNK, (size_t)info->size);
1657
1658 info->bits[i / MALLOC_BITS] |= 1UL << (i % MALLOC_BITS);
1659 info->free++;
1660
1661 if (info->size != 0)
1662 mp = page_dir + info->shift;
1663 else
1664 mp = page_dir;
1665
1666 if (info->free == 1) {
1667 /* Page became non-full */
1668
1669 /* Insert in address order */
1670 while (*mp != NULL && (*mp)->next != NULL &&
1671 (*mp)->next->page < info->page)
1672 mp = &(*mp)->next;
1673 info->next = *mp;
1674 *mp = info;
1675 return;
1676 }
1677 if (info->free != info->total)
1678 return;
1679
1680 /* Find & remove this page in the queue */
1681 while (*mp != info) {
1682 mp = &((*mp)->next);
1683#ifdef MALLOC_EXTRA_SANITY
1684 if (!*mp) {
1685 wrterror("(ES): Not on queue");
1686 errno = EFAULT;
1687 return;
1688 }
1689#endif /* MALLOC_EXTRA_SANITY */
1690 }
1691 *mp = info->next;
1692
1693 /* Free the page & the info structure if need be */
1694 pdir_lookup(ptr2index(info->page), &pi);
1695#ifdef MALLOC_EXTRA_SANITY
1696 pidx = PI_IDX(ptr2index(info->page));
1697 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1698 wrterror("(ES): mapped pages not found in directory");
1699 errno = EFAULT;
1700 return;
1701 }
1702#endif /* MALLOC_EXTRA_SANITY */
1703 if (pi != last_dir) {
1704 prev_dir = last_dir;
1705 last_dir = pi;
1706 }
1707 pd = pi->base;
1708 pd[PI_OFF(ptr2index(info->page))] = MALLOC_FIRST;
1709
1710 /* If the page was mprotected, unprotect it before releasing it */
1711 if (info->size == 0)
1712 mprotect(info->page, malloc_pagesize, PROT_READ | PROT_WRITE);
1713
1714 vp = info->page; /* Order is important ! */
1715 if (vp != (void *) info)
1716 ifree(info);
1717 ifree(vp);
1718}
1719
1720static void
1721ifree(void *ptr)
1722{
1723 struct pginfo *info, **pd;
1724 u_long index;
1725#ifdef MALLOC_EXTRA_SANITY
1726 u_long pidx;
1727#endif /* MALLOC_EXTRA_SANITY */
1728 struct pdinfo *pi;
1729
1730 if (!malloc_started) {
1731 wrtwarning("malloc() has never been called");
1732 return;
1733 }
1734 /* If we're already sinking, don't make matters any worse. */
1735 if (suicide)
1736 return;
1737
1738 if (malloc_ptrguard && PTR_ALIGNED(ptr))
1739 ptr = (char *) ptr - PTR_GAP;
1740
1741 index = ptr2index(ptr);
1742
1743 if (index < malloc_pageshift) {
1744 warnx("(%p)", ptr);
1745 wrtwarning("ifree: junk pointer, too low to make sense");
1746 return;
1747 }
1748 if (index > last_index) {
1749 warnx("(%p)", ptr);
1750 wrtwarning("ifree: junk pointer, too high to make sense");
1751 return;
1752 }
1753 pdir_lookup(index, &pi);
1754#ifdef MALLOC_EXTRA_SANITY
1755 pidx = PI_IDX(index);
1756 if (pi == NULL || PD_IDX(pi->dirnum) != pidx) {
1757 wrterror("(ES): mapped pages not found in directory");
1758 errno = EFAULT;
1759 return;
1760 }
1761#endif /* MALLOC_EXTRA_SANITY */
1762 if (pi != last_dir) {
1763 prev_dir = last_dir;
1764 last_dir = pi;
1765 }
1766 pd = pi->base;
1767 info = pd[PI_OFF(index)];
1768
1769 if (info < MALLOC_MAGIC)
1770 free_pages(ptr, index, info);
1771 else
1772 free_bytes(ptr, index, info);
1773
1774 /* does not matter if malloc_bytes fails */
1775 if (px == NULL)
1776 px = malloc_bytes(sizeof *px);
1777
1778 return;
1779}
1780
1781/*
1782 * Common function for handling recursion. Only
1783 * print the error message once, to avoid making the problem
1784 * potentially worse.
1785 */
1786static void
1787malloc_recurse(void)
1788{
1789 static int noprint;
1790
1791 if (noprint == 0) {
1792 noprint = 1;
1793 wrtwarning("recursive call");
1794 }
1795 malloc_active--;
1796 _MALLOC_UNLOCK();
1797 errno = EDEADLK;
1798}
1799
1800/*
1801 * These are the public exported interface routines.
1802 */
1803void *
1804malloc(size_t size)
1805{
1806 void *r;
1807
1808 _MALLOC_LOCK();
1809 malloc_func = " in malloc():";
1810 if (malloc_active++) {
1811 malloc_recurse();
1812 return (NULL);
1813 }
1814 r = imalloc(size);
1815 UTRACE(0, size, r);
1816 malloc_active--;
1817 _MALLOC_UNLOCK();
1818 if (malloc_xmalloc && r == NULL) {
1819 wrterror("out of memory");
1820 errno = ENOMEM;
1821 }
1822 return (r);
1823}
1824
1825void
1826free(void *ptr)
1827{
1828 /* This is legal. XXX quick path */
1829 if (ptr == NULL)
1830 return;
1831
1832 _MALLOC_LOCK();
1833 malloc_func = " in free():";
1834 if (malloc_active++) {
1835 malloc_recurse();
1836 return;
1837 }
1838 ifree(ptr);
1839 UTRACE(ptr, 0, 0);
1840 malloc_active--;
1841 _MALLOC_UNLOCK();
1842 return;
1843}
1844
1845void *
1846realloc(void *ptr, size_t size)
1847{
1848 void *r;
1849
1850 _MALLOC_LOCK();
1851 malloc_func = " in realloc():";
1852 if (malloc_active++) {
1853 malloc_recurse();
1854 return (NULL);
1855 }
1856
1857 if (ptr == NULL)
1858 r = imalloc(size);
1859 else
1860 r = irealloc(ptr, size);
1861
1862 UTRACE(ptr, size, r);
1863 malloc_active--;
1864 _MALLOC_UNLOCK();
1865 if (malloc_xmalloc && r == NULL) {
1866 wrterror("out of memory");
1867 errno = ENOMEM;
1868 }
1869 return (r);
1870}
diff --git a/src/lib/libc/stdlib/merge.c b/src/lib/libc/stdlib/merge.c
new file mode 100644
index 0000000000..623f652134
--- /dev/null
+++ b/src/lib/libc/stdlib/merge.c
@@ -0,0 +1,333 @@
1/* $OpenBSD: merge.c,v 1.8 2005/08/08 08:05:37 espie Exp $ */
2/*-
3 * Copyright (c) 1992, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * Peter McIlroy.
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
34/*
35 * Hybrid exponential search/linear search merge sort with hybrid
36 * natural/pairwise first pass. Requires about .3% more comparisons
37 * for random data than LSMS with pairwise first pass alone.
38 * It works for objects as small as two bytes.
39 */
40
41#define NATURAL
42#define THRESHOLD 16 /* Best choice for natural merge cut-off. */
43
44/* #define NATURAL to get hybrid natural merge.
45 * (The default is pairwise merging.)
46 */
47
48#include <sys/types.h>
49
50#include <errno.h>
51#include <stdlib.h>
52#include <string.h>
53
54static void setup(u_char *, u_char *, size_t, size_t, int (*)());
55static void insertionsort(u_char *, size_t, size_t, int (*)());
56
57#define ISIZE sizeof(int)
58#define PSIZE sizeof(u_char *)
59#define ICOPY_LIST(src, dst, last) \
60 do \
61 *(int*)dst = *(int*)src, src += ISIZE, dst += ISIZE; \
62 while(src < last)
63#define ICOPY_ELT(src, dst, i) \
64 do \
65 *(int*) dst = *(int*) src, src += ISIZE, dst += ISIZE; \
66 while (i -= ISIZE)
67
68#define CCOPY_LIST(src, dst, last) \
69 do \
70 *dst++ = *src++; \
71 while (src < last)
72#define CCOPY_ELT(src, dst, i) \
73 do \
74 *dst++ = *src++; \
75 while (i -= 1)
76
77/*
78 * Find the next possible pointer head. (Trickery for forcing an array
79 * to do double duty as a linked list when objects do not align with word
80 * boundaries.
81 */
82/* Assumption: PSIZE is a power of 2. */
83#define EVAL(p) (u_char **) \
84 ((u_char *)0 + \
85 (((u_char *)p + PSIZE - 1 - (u_char *) 0) & ~(PSIZE - 1)))
86
87/*
88 * Arguments are as for qsort.
89 */
90int
91mergesort(void *base, size_t nmemb, size_t size,
92 int (*cmp)(const void *, const void *))
93{
94 int i, sense;
95 int big, iflag;
96 u_char *f1, *f2, *t, *b, *tp2, *q, *l1, *l2;
97 u_char *list2, *list1, *p2, *p, *last, **p1;
98
99 if (size < PSIZE / 2) { /* Pointers must fit into 2 * size. */
100 errno = EINVAL;
101 return (-1);
102 }
103
104 /*
105 * XXX
106 * Stupid subtraction for the Cray.
107 */
108 iflag = 0;
109 if (!(size % ISIZE) && !(((char *)base - (char *)0) % ISIZE))
110 iflag = 1;
111
112 if ((list2 = malloc(nmemb * size + PSIZE)) == NULL)
113 return (-1);
114
115 list1 = base;
116 setup(list1, list2, nmemb, size, cmp);
117 last = list2 + nmemb * size;
118 i = big = 0;
119 while (*EVAL(list2) != last) {
120 l2 = list1;
121 p1 = EVAL(list1);
122 for (tp2 = p2 = list2; p2 != last; p1 = EVAL(l2)) {
123 p2 = *EVAL(p2);
124 f1 = l2;
125 f2 = l1 = list1 + (p2 - list2);
126 if (p2 != last)
127 p2 = *EVAL(p2);
128 l2 = list1 + (p2 - list2);
129 while (f1 < l1 && f2 < l2) {
130 if ((*cmp)(f1, f2) <= 0) {
131 q = f2;
132 b = f1, t = l1;
133 sense = -1;
134 } else {
135 q = f1;
136 b = f2, t = l2;
137 sense = 0;
138 }
139 if (!big) { /* here i = 0 */
140 while ((b += size) < t && cmp(q, b) >sense)
141 if (++i == 6) {
142 big = 1;
143 goto EXPONENTIAL;
144 }
145 } else {
146EXPONENTIAL: for (i = size; ; i <<= 1)
147 if ((p = (b + i)) >= t) {
148 if ((p = t - size) > b &&
149 (*cmp)(q, p) <= sense)
150 t = p;
151 else
152 b = p;
153 break;
154 } else if ((*cmp)(q, p) <= sense) {
155 t = p;
156 if (i == size)
157 big = 0;
158 goto FASTCASE;
159 } else
160 b = p;
161 while (t > b+size) {
162 i = (((t - b) / size) >> 1) * size;
163 if ((*cmp)(q, p = b + i) <= sense)
164 t = p;
165 else
166 b = p;
167 }
168 goto COPY;
169FASTCASE: while (i > size)
170 if ((*cmp)(q,
171 p = b + (i >>= 1)) <= sense)
172 t = p;
173 else
174 b = p;
175COPY: b = t;
176 }
177 i = size;
178 if (q == f1) {
179 if (iflag) {
180 ICOPY_LIST(f2, tp2, b);
181 ICOPY_ELT(f1, tp2, i);
182 } else {
183 CCOPY_LIST(f2, tp2, b);
184 CCOPY_ELT(f1, tp2, i);
185 }
186 } else {
187 if (iflag) {
188 ICOPY_LIST(f1, tp2, b);
189 ICOPY_ELT(f2, tp2, i);
190 } else {
191 CCOPY_LIST(f1, tp2, b);
192 CCOPY_ELT(f2, tp2, i);
193 }
194 }
195 }
196 if (f2 < l2) {
197 if (iflag)
198 ICOPY_LIST(f2, tp2, l2);
199 else
200 CCOPY_LIST(f2, tp2, l2);
201 } else if (f1 < l1) {
202 if (iflag)
203 ICOPY_LIST(f1, tp2, l1);
204 else
205 CCOPY_LIST(f1, tp2, l1);
206 }
207 *p1 = l2;
208 }
209 tp2 = list1; /* swap list1, list2 */
210 list1 = list2;
211 list2 = tp2;
212 last = list2 + nmemb*size;
213 }
214 if (base == list2) {
215 memmove(list2, list1, nmemb*size);
216 list2 = list1;
217 }
218 free(list2);
219 return (0);
220}
221
222#define swap(a, b) { \
223 s = b; \
224 i = size; \
225 do { \
226 tmp = *a; *a++ = *s; *s++ = tmp; \
227 } while (--i); \
228 a -= size; \
229 }
230#define reverse(bot, top) { \
231 s = top; \
232 do { \
233 i = size; \
234 do { \
235 tmp = *bot; *bot++ = *s; *s++ = tmp; \
236 } while (--i); \
237 s -= size2; \
238 } while(bot < s); \
239}
240
241/*
242 * Optional hybrid natural/pairwise first pass. Eats up list1 in runs of
243 * increasing order, list2 in a corresponding linked list. Checks for runs
244 * when THRESHOLD/2 pairs compare with same sense. (Only used when NATURAL
245 * is defined. Otherwise simple pairwise merging is used.)
246 */
247void
248setup(u_char *list1, u_char *list2, size_t n, size_t size,
249 int (*cmp)(const void *, const void *))
250{
251 int i, length, size2, tmp, sense;
252 u_char *f1, *f2, *s, *l2, *last, *p2;
253
254 size2 = size*2;
255 if (n <= 5) {
256 insertionsort(list1, n, size, cmp);
257 *EVAL(list2) = (u_char*) list2 + n*size;
258 return;
259 }
260 /*
261 * Avoid running pointers out of bounds; limit n to evens
262 * for simplicity.
263 */
264 i = 4 + (n & 1);
265 insertionsort(list1 + (n - i) * size, i, size, cmp);
266 last = list1 + size * (n - i);
267 *EVAL(list2 + (last - list1)) = list2 + n * size;
268
269#ifdef NATURAL
270 p2 = list2;
271 f1 = list1;
272 sense = (cmp(f1, f1 + size) > 0);
273 for (; f1 < last; sense = !sense) {
274 length = 2;
275 /* Find pairs with same sense. */
276 for (f2 = f1 + size2; f2 < last; f2 += size2) {
277 if ((cmp(f2, f2+ size) > 0) != sense)
278 break;
279 length += 2;
280 }
281 if (length < THRESHOLD) { /* Pairwise merge */
282 do {
283 p2 = *EVAL(p2) = f1 + size2 - list1 + list2;
284 if (sense > 0)
285 swap (f1, f1 + size);
286 } while ((f1 += size2) < f2);
287 } else { /* Natural merge */
288 l2 = f2;
289 for (f2 = f1 + size2; f2 < l2; f2 += size2) {
290 if ((cmp(f2-size, f2) > 0) != sense) {
291 p2 = *EVAL(p2) = f2 - list1 + list2;
292 if (sense > 0)
293 reverse(f1, f2-size);
294 f1 = f2;
295 }
296 }
297 if (sense > 0)
298 reverse (f1, f2-size);
299 f1 = f2;
300 if (f2 < last || cmp(f2 - size, f2) > 0)
301 p2 = *EVAL(p2) = f2 - list1 + list2;
302 else
303 p2 = *EVAL(p2) = list2 + n*size;
304 }
305 }
306#else /* pairwise merge only. */
307 for (f1 = list1, p2 = list2; f1 < last; f1 += size2) {
308 p2 = *EVAL(p2) = p2 + size2;
309 if (cmp (f1, f1 + size) > 0)
310 swap(f1, f1 + size);
311 }
312#endif /* NATURAL */
313}
314
315/*
316 * This is to avoid out-of-bounds addresses in sorting the
317 * last 4 elements.
318 */
319static void
320insertionsort(u_char *a, size_t n, size_t size,
321 int (*cmp)(const void *, const void *))
322{
323 u_char *ai, *s, *t, *u, tmp;
324 int i;
325
326 for (ai = a+size; --n >= 1; ai += size)
327 for (t = ai; t > a; t -= size) {
328 u = t - size;
329 if (cmp(u, t) <= 0)
330 break;
331 swap(u, t);
332 }
333}
diff --git a/src/lib/libc/stdlib/mrand48.c b/src/lib/libc/stdlib/mrand48.c
new file mode 100644
index 0000000000..977264aba5
--- /dev/null
+++ b/src/lib/libc/stdlib/mrand48.c
@@ -0,0 +1,24 @@
1/* $OpenBSD: mrand48.c,v 1.3 2005/08/08 08:05:37 espie Exp $ */
2/*
3 * Copyright (c) 1993 Martin Birgmeier
4 * All rights reserved.
5 *
6 * You may redistribute unmodified or modified versions of this source
7 * code provided that the above copyright notice and this and the
8 * following conditions are retained.
9 *
10 * This software is provided ``as is'', and comes with no warranties
11 * of any kind. I shall in no event be liable for anything that happens
12 * to anyone/anything when using this software.
13 */
14
15#include "rand48.h"
16
17extern unsigned short __rand48_seed[3];
18
19long
20mrand48(void)
21{
22 __dorand48(__rand48_seed);
23 return ((long) __rand48_seed[2] << 16) + (long) __rand48_seed[1];
24}
diff --git a/src/lib/libc/stdlib/nrand48.c b/src/lib/libc/stdlib/nrand48.c
new file mode 100644
index 0000000000..f1f548c3af
--- /dev/null
+++ b/src/lib/libc/stdlib/nrand48.c
@@ -0,0 +1,22 @@
1/* $OpenBSD: nrand48.c,v 1.3 2005/08/08 08:05:37 espie Exp $ */
2/*
3 * Copyright (c) 1993 Martin Birgmeier
4 * All rights reserved.
5 *
6 * You may redistribute unmodified or modified versions of this source
7 * code provided that the above copyright notice and this and the
8 * following conditions are retained.
9 *
10 * This software is provided ``as is'', and comes with no warranties
11 * of any kind. I shall in no event be liable for anything that happens
12 * to anyone/anything when using this software.
13 */
14
15#include "rand48.h"
16
17long
18nrand48(unsigned short xseed[3])
19{
20 __dorand48(xseed);
21 return ((long) xseed[2] << 15) + ((long) xseed[1] >> 1);
22}
diff --git a/src/lib/libc/stdlib/putenv.c b/src/lib/libc/stdlib/putenv.c
new file mode 100644
index 0000000000..54482f6a14
--- /dev/null
+++ b/src/lib/libc/stdlib/putenv.c
@@ -0,0 +1,50 @@
1/* $OpenBSD: putenv.c,v 1.5 2005/08/08 08:05:37 espie Exp $ */
2/*-
3 * Copyright (c) 1988, 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
31#include <stdlib.h>
32#include <string.h>
33
34int
35putenv(const char *str)
36{
37 char *p, *equal;
38 int rval;
39
40 if ((p = strdup(str)) == NULL)
41 return (-1);
42 if ((equal = strchr(p, '=')) == NULL) {
43 (void)free(p);
44 return (-1);
45 }
46 *equal = '\0';
47 rval = setenv(p, equal + 1, 1);
48 (void)free(p);
49 return (rval);
50}
diff --git a/src/lib/libc/stdlib/qabs.3 b/src/lib/libc/stdlib/qabs.3
new file mode 100644
index 0000000000..863758e1c7
--- /dev/null
+++ b/src/lib/libc/stdlib/qabs.3
@@ -0,0 +1,57 @@
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.10 2006/01/15 17:31:06 jmc 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 imaxabs 3 ,
54.Xr labs 3 ,
55.Xr math 3
56.Sh BUGS
57The 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..656b93c822
--- /dev/null
+++ b/src/lib/libc/stdlib/qabs.c
@@ -0,0 +1,37 @@
1/* $OpenBSD: qabs.c,v 1.5 2005/08/08 08:05:37 espie Exp $ */
2/*-
3 * Copyright (c) 1990 The Regents of the University of California.
4 * 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
31#include <stdlib.h>
32
33quad_t
34qabs(quad_t j)
35{
36 return(j < 0 ? -j : j);
37}
diff --git a/src/lib/libc/stdlib/qdiv.3 b/src/lib/libc/stdlib/qdiv.3
new file mode 100644
index 0000000000..643672ea5b
--- /dev/null
+++ b/src/lib/libc/stdlib/qdiv.3
@@ -0,0 +1,62 @@
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.7 2006/01/13 17:58:09 millert Exp $
33.\"
34.Dd June 29, 1991
35.Dt QDIV 3
36.Os
37.Sh NAME
38.Nm qdiv
39.Nd return quotient and remainder from division
40.Sh SYNOPSIS
41.Fd #include <stdlib.h>
42.Ft qdiv_t
43.Fn qdiv "quad_t num" "quad_t denom"
44.Sh DESCRIPTION
45The
46.Fn qdiv
47function computes the value
48.Fa num Ns / 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 imaxdiv 3 ,
60.Xr ldiv 3 ,
61.Xr lldiv 3 ,
62.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..f3db0915ed
--- /dev/null
+++ b/src/lib/libc/stdlib/qdiv.c
@@ -0,0 +1,50 @@
1/* $OpenBSD: qdiv.c,v 1.5 2005/08/08 08:05:37 espie Exp $ */
2/*
3 * Copyright (c) 1990 Regents of the University of California.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * Chris Torek.
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
34#include <stdlib.h> /* qdiv_t */
35
36qdiv_t
37qdiv(quad_t num, quad_t denom)
38{
39 qdiv_t r;
40
41 /* see div.c for comments */
42
43 r.quot = num / denom;
44 r.rem = num % denom;
45 if (num >= 0 && r.rem < 0) {
46 r.quot++;
47 r.rem -= denom;
48 }
49 return (r);
50}
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..bb4a9a11f2
--- /dev/null
+++ b/src/lib/libc/stdlib/qsort.c
@@ -0,0 +1,161 @@
1/* $OpenBSD: qsort.c,v 1.10 2005/08/08 08:05:37 espie Exp $ */
2/*-
3 * Copyright (c) 1992, 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
31#include <sys/types.h>
32#include <stdlib.h>
33
34static __inline char *med3(char *, char *, char *, int (*)(const void *, const void *));
35static __inline void swapfunc(char *, char *, int, int);
36
37#define min(a, b) (a) < (b) ? a : b
38
39/*
40 * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
41 */
42#define swapcode(TYPE, parmi, parmj, n) { \
43 long i = (n) / sizeof (TYPE); \
44 TYPE *pi = (TYPE *) (parmi); \
45 TYPE *pj = (TYPE *) (parmj); \
46 do { \
47 TYPE t = *pi; \
48 *pi++ = *pj; \
49 *pj++ = t; \
50 } while (--i > 0); \
51}
52
53#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
54 es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
55
56static __inline void
57swapfunc(char *a, char *b, int n, int swaptype)
58{
59 if (swaptype <= 1)
60 swapcode(long, a, b, n)
61 else
62 swapcode(char, a, b, n)
63}
64
65#define swap(a, b) \
66 if (swaptype == 0) { \
67 long t = *(long *)(a); \
68 *(long *)(a) = *(long *)(b); \
69 *(long *)(b) = t; \
70 } else \
71 swapfunc(a, b, es, swaptype)
72
73#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
74
75static __inline char *
76med3(char *a, char *b, char *c, int (*cmp)(const void *, const void *))
77{
78 return cmp(a, b) < 0 ?
79 (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))
80 :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ));
81}
82
83void
84qsort(void *aa, size_t n, size_t es, int (*cmp)(const void *, const void *))
85{
86 char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
87 int d, r, swaptype, swap_cnt;
88 char *a = aa;
89
90loop: SWAPINIT(a, es);
91 swap_cnt = 0;
92 if (n < 7) {
93 for (pm = (char *)a + es; pm < (char *) a + n * es; pm += es)
94 for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
95 pl -= es)
96 swap(pl, pl - es);
97 return;
98 }
99 pm = (char *)a + (n / 2) * es;
100 if (n > 7) {
101 pl = (char *)a;
102 pn = (char *)a + (n - 1) * es;
103 if (n > 40) {
104 d = (n / 8) * es;
105 pl = med3(pl, pl + d, pl + 2 * d, cmp);
106 pm = med3(pm - d, pm, pm + d, cmp);
107 pn = med3(pn - 2 * d, pn - d, pn, cmp);
108 }
109 pm = med3(pl, pm, pn, cmp);
110 }
111 swap(a, pm);
112 pa = pb = (char *)a + es;
113
114 pc = pd = (char *)a + (n - 1) * es;
115 for (;;) {
116 while (pb <= pc && (r = cmp(pb, a)) <= 0) {
117 if (r == 0) {
118 swap_cnt = 1;
119 swap(pa, pb);
120 pa += es;
121 }
122 pb += es;
123 }
124 while (pb <= pc && (r = cmp(pc, a)) >= 0) {
125 if (r == 0) {
126 swap_cnt = 1;
127 swap(pc, pd);
128 pd -= es;
129 }
130 pc -= es;
131 }
132 if (pb > pc)
133 break;
134 swap(pb, pc);
135 swap_cnt = 1;
136 pb += es;
137 pc -= es;
138 }
139 if (swap_cnt == 0) { /* Switch to insertion sort */
140 for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
141 for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
142 pl -= es)
143 swap(pl, pl - es);
144 return;
145 }
146
147 pn = (char *)a + n * es;
148 r = min(pa - (char *)a, pb - pa);
149 vecswap(a, pb - r, r);
150 r = min(pd - pc, pn - pd - es);
151 vecswap(pb, pn - r, r);
152 if ((r = pb - pa) > es)
153 qsort(a, r / es, es, cmp);
154 if ((r = pd - pc) > es) {
155 /* Iterate rather than recurse to save stack space */
156 a = pn - r;
157 n = r / es;
158 goto loop;
159 }
160/* qsort(pn - r, r / es, es, cmp);*/
161}
diff --git a/src/lib/libc/stdlib/radixsort.3 b/src/lib/libc/stdlib/radixsort.3
new file mode 100644
index 0000000000..8a4f71641f
--- /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.10 2005/07/26 04:20:23 jaredy 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..0b2ff27044
--- /dev/null
+++ b/src/lib/libc/stdlib/radixsort.c
@@ -0,0 +1,294 @@
1/* $OpenBSD: radixsort.c,v 1.8 2005/08/08 08:05:37 espie Exp $ */
2/*-
3 * Copyright (c) 1990, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * Peter McIlroy and by Dan Bernstein at New York University,
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
34/*
35 * Radixsort routines.
36 *
37 * Program r_sort_a() is unstable but uses O(logN) extra memory for a stack.
38 * Use radixsort(a, n, trace, endchar) for this case.
39 *
40 * For stable sorting (using N extra pointers) use sradixsort(), which calls
41 * r_sort_b().
42 *
43 * For a description of this code, see D. McIlroy, P. McIlroy, K. Bostic,
44 * "Engineering Radix Sort".
45 */
46
47#include <sys/types.h>
48#include <stdlib.h>
49#include <errno.h>
50
51typedef struct {
52 const u_char **sa;
53 int sn, si;
54} stack;
55
56static __inline void simplesort
57(const u_char **, int, int, const u_char *, u_int);
58static void r_sort_a(const u_char **, int, int, const u_char *, u_int);
59static void r_sort_b(const u_char **,
60 const u_char **, int, int, const u_char *, u_int);
61
62#define THRESHOLD 20 /* Divert to simplesort(). */
63#define SIZE 512 /* Default stack size. */
64
65#define SETUP { \
66 if (tab == NULL) { \
67 tr = tr0; \
68 for (c = 0; c < endch; c++) \
69 tr0[c] = c + 1; \
70 tr0[c] = 0; \
71 for (c++; c < 256; c++) \
72 tr0[c] = c; \
73 endch = 0; \
74 } else { \
75 endch = tab[endch]; \
76 tr = tab; \
77 if (endch != 0 && endch != 255) { \
78 errno = EINVAL; \
79 return (-1); \
80 } \
81 } \
82}
83
84int
85radixsort(const u_char **a, int n, const u_char *tab, u_int endch)
86{
87 const u_char *tr;
88 int c;
89 u_char tr0[256];
90
91 SETUP;
92 r_sort_a(a, n, 0, tr, endch);
93 return (0);
94}
95
96int
97sradixsort(const u_char **a, int n, const u_char *tab, u_int endch)
98{
99 const u_char *tr, **ta;
100 int c;
101 u_char tr0[256];
102
103 SETUP;
104 if (n < THRESHOLD)
105 simplesort(a, n, 0, tr, endch);
106 else {
107 if ((ta = malloc(n * sizeof(a))) == NULL)
108 return (-1);
109 r_sort_b(a, ta, n, 0, tr, endch);
110 free(ta);
111 }
112 return (0);
113}
114
115#define empty(s) (s >= sp)
116#define pop(a, n, i) a = (--sp)->sa, n = sp->sn, i = sp->si
117#define push(a, n, i) sp->sa = a, sp->sn = n, (sp++)->si = i
118#define swap(a, b, t) t = a, a = b, b = t
119
120/* Unstable, in-place sort. */
121void
122r_sort_a(const u_char **a, int n, int i, const u_char *tr, u_int endch)
123{
124 static int count[256], nc, bmin;
125 int c;
126 const u_char **ak, *r;
127 stack s[SIZE], *sp, *sp0, *sp1, temp;
128 int *cp, bigc;
129 const u_char **an, *t, **aj, **top[256];
130
131 /* Set up stack. */
132 sp = s;
133 push(a, n, i);
134 while (!empty(s)) {
135 pop(a, n, i);
136 if (n < THRESHOLD) {
137 simplesort(a, n, i, tr, endch);
138 continue;
139 }
140 an = a + n;
141
142 /* Make character histogram. */
143 if (nc == 0) {
144 bmin = 255; /* First occupied bin, excluding eos. */
145 for (ak = a; ak < an;) {
146 c = tr[(*ak++)[i]];
147 if (++count[c] == 1 && c != endch) {
148 if (c < bmin)
149 bmin = c;
150 nc++;
151 }
152 }
153 if (sp + nc > s + SIZE) { /* Get more stack. */
154 r_sort_a(a, n, i, tr, endch);
155 continue;
156 }
157 }
158
159 /*
160 * Set top[]; push incompletely sorted bins onto stack.
161 * top[] = pointers to last out-of-place element in bins.
162 * count[] = counts of elements in bins.
163 * Before permuting: top[c-1] + count[c] = top[c];
164 * during deal: top[c] counts down to top[c-1].
165 */
166 sp0 = sp1 = sp; /* Stack position of biggest bin. */
167 bigc = 2; /* Size of biggest bin. */
168 if (endch == 0) /* Special case: set top[eos]. */
169 top[0] = ak = a + count[0];
170 else {
171 ak = a;
172 top[255] = an;
173 }
174 for (cp = count + bmin; nc > 0; cp++) {
175 while (*cp == 0) /* Find next non-empty pile. */
176 cp++;
177 if (*cp > 1) {
178 if (*cp > bigc) {
179 bigc = *cp;
180 sp1 = sp;
181 }
182 push(ak, *cp, i+1);
183 }
184 top[cp-count] = ak += *cp;
185 nc--;
186 }
187 swap(*sp0, *sp1, temp); /* Play it safe -- biggest bin last. */
188
189 /*
190 * Permute misplacements home. Already home: everything
191 * before aj, and in bin[c], items from top[c] on.
192 * Inner loop:
193 * r = next element to put in place;
194 * ak = top[r[i]] = location to put the next element.
195 * aj = bottom of 1st disordered bin.
196 * Outer loop:
197 * Once the 1st disordered bin is done, ie. aj >= ak,
198 * aj<-aj + count[c] connects the bins in a linked list;
199 * reset count[c].
200 */
201 for (aj = a; aj < an; *aj = r, aj += count[c], count[c] = 0)
202 for (r = *aj; aj < (ak = --top[c = tr[r[i]]]);)
203 swap(*ak, r, t);
204 }
205}
206
207/* Stable sort, requiring additional memory. */
208void
209r_sort_b(const u_char **a, const u_char **ta, int n, int i, const u_char *tr,
210 u_int endch)
211{
212 static int count[256], nc, bmin;
213 int c;
214 const u_char **ak, **ai;
215 stack s[512], *sp, *sp0, *sp1, temp;
216 const u_char **top[256];
217 int *cp, bigc;
218
219 sp = s;
220 push(a, n, i);
221 while (!empty(s)) {
222 pop(a, n, i);
223 if (n < THRESHOLD) {
224 simplesort(a, n, i, tr, endch);
225 continue;
226 }
227
228 if (nc == 0) {
229 bmin = 255;
230 for (ak = a + n; --ak >= a;) {
231 c = tr[(*ak)[i]];
232 if (++count[c] == 1 && c != endch) {
233 if (c < bmin)
234 bmin = c;
235 nc++;
236 }
237 }
238 if (sp + nc > s + SIZE) {
239 r_sort_b(a, ta, n, i, tr, endch);
240 continue;
241 }
242 }
243
244 sp0 = sp1 = sp;
245 bigc = 2;
246 if (endch == 0) {
247 top[0] = ak = a + count[0];
248 count[0] = 0;
249 } else {
250 ak = a;
251 top[255] = a + n;
252 count[255] = 0;
253 }
254 for (cp = count + bmin; nc > 0; cp++) {
255 while (*cp == 0)
256 cp++;
257 if ((c = *cp) > 1) {
258 if (c > bigc) {
259 bigc = c;
260 sp1 = sp;
261 }
262 push(ak, c, i+1);
263 }
264 top[cp-count] = ak += c;
265 *cp = 0; /* Reset count[]. */
266 nc--;
267 }
268 swap(*sp0, *sp1, temp);
269
270 for (ak = ta + n, ai = a+n; ak > ta;) /* Copy to temp. */
271 *--ak = *--ai;
272 for (ak = ta+n; --ak >= ta;) /* Deal to piles. */
273 *--top[tr[(*ak)[i]]] = *ak;
274 }
275}
276
277static __inline void
278simplesort(const u_char **a, int n, int b, const u_char *tr, u_int endch)
279 /* insertion sort */
280{
281 u_char ch;
282 const u_char **ak, **ai, *s, *t;
283
284 for (ak = a+1; --n >= 1; ak++)
285 for (ai = ak; ai > a; ai--) {
286 for (s = ai[0] + b, t = ai[-1] + b;
287 (ch = tr[*s]) != endch; s++, t++)
288 if (ch != tr[*t])
289 break;
290 if (ch >= tr[*t])
291 break;
292 swap(ai[0], ai[-1], s);
293 }
294}
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..0f9c100807
--- /dev/null
+++ b/src/lib/libc/stdlib/rand.c
@@ -0,0 +1,52 @@
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#include <sys/types.h>
31#include <stdlib.h>
32
33static u_int next = 1;
34
35int
36rand_r(u_int *seed)
37{
38 *seed = *seed * 1103515245 + 12345;
39 return (*seed % ((u_int)RAND_MAX + 1));
40}
41
42int
43rand(void)
44{
45 return (rand_r(&next));
46}
47
48void
49srand(u_int seed)
50{
51 next = seed;
52}
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..626b040b50
--- /dev/null
+++ b/src/lib/libc/stdlib/random.3
@@ -0,0 +1,185 @@
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.18 2005/11/30 07:51:02 otto 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
93random numbers obtained from the kernel,
94suitable for cryptographic use.
95Note that this particular seeding procedure can generate
96states which are impossible to reproduce by calling
97.Fn srandom
98with any value, since the succeeding terms in the
99state buffer are no longer derived from the LC algorithm applied to
100a fixed seed.
101.Pp
102The
103.Fn initstate
104routine allows a state array, passed in as an argument, to be initialized
105for future use.
106The size of the state array (in bytes) is used by
107.Fn initstate
108to decide how sophisticated a random number generator it should use \(em the
109more state, the better the random numbers will be.
110(Current "optimal" values for the amount of state information are
1118, 32, 64, 128, and 256 bytes; other amounts will be rounded down to
112the nearest known amount.
113Using less than 8 bytes will cause an error.)
114The seed for the initialization (which specifies a starting point for
115the random number sequence, and provides for restarting at the same
116point) is also an argument.
117The
118.Fn initstate
119function returns a pointer to the previous state information array.
120.Pp
121Once a state has been initialized, the
122.Fn setstate
123routine provides for rapid switching between states.
124The
125.Fn setstate
126function returns a pointer to the previous state array; its
127argument state array is used for further random number generation
128until the next call to
129.Fn initstate
130or
131.Fn setstate .
132.Pp
133Once a state array has been initialized, it may be restarted at a
134different point either by calling
135.Fn initstate
136(with the desired seed, the state array, and its size) or by calling
137both
138.Fn setstate
139(with the state array) and
140.Fn srandom
141(with the desired seed).
142The advantage of calling both
143.Fn setstate
144and
145.Fn srandom
146is that the size of the state array does not have to be remembered after
147it is initialized.
148.Pp
149With 256 bytes of state information, the period of the random number
150generator is greater than 2**69
151which should be sufficient for most purposes.
152.Sh DIAGNOSTICS
153If
154.Fn initstate
155is called with less than 8 bytes of state information, or if
156.Fn setstate
157detects that the state information has been garbled, error
158messages are printed on the standard error output.
159.Sh SEE ALSO
160.Xr arc4random 3 ,
161.Xr drand48 3 ,
162.Xr rand 3 ,
163.Xr random 4
164.Sh STANDARDS
165The
166.Fn random ,
167.Fn srandom ,
168.Fn initstate ,
169and
170.Fn setstate
171functions conform to
172.St -xpg4.2 .
173.Pp
174The
175.Fn srandomdev
176function is an extension.
177.Sh HISTORY
178These
179functions appeared in
180.Bx 4.2 .
181.Sh AUTHORS
182.An Earl T. Cohen
183.Sh BUGS
184About 2/3 the speed of
185.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..48e892042b
--- /dev/null
+++ b/src/lib/libc/stdlib/random.c
@@ -0,0 +1,395 @@
1/* $OpenBSD: random.c,v 1.15 2005/11/30 07:51:02 otto Exp $ */
2/*
3 * Copyright (c) 1983 Regents of the University of California.
4 * 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
31#include <sys/param.h>
32#include <sys/sysctl.h>
33#include <sys/time.h>
34#include <fcntl.h>
35#include <stdio.h>
36#include <stdlib.h>
37#include <unistd.h>
38
39/*
40 * random.c:
41 *
42 * An improved random number generation package. In addition to the standard
43 * rand()/srand() like interface, this package also has a special state info
44 * interface. The initstate() routine is called with a seed, an array of
45 * bytes, and a count of how many bytes are being passed in; this array is
46 * then initialized to contain information for random number generation with
47 * that much state information. Good sizes for the amount of state
48 * information are 32, 64, 128, and 256 bytes. The state can be switched by
49 * calling the setstate() routine with the same array as was initiallized
50 * with initstate(). By default, the package runs with 128 bytes of state
51 * information and generates far better random numbers than a linear
52 * congruential generator. If the amount of state information is less than
53 * 32 bytes, a simple linear congruential R.N.G. is used.
54 *
55 * Internally, the state information is treated as an array of int32_t; the
56 * zeroeth element of the array is the type of R.N.G. being used (small
57 * integer); the remainder of the array is the state information for the
58 * R.N.G. Thus, 32 bytes of state information will give 7 int32_ts worth of
59 * state information, which will allow a degree seven polynomial. (Note:
60 * the zeroeth word of state information also has some other information
61 * stored in it -- see setstate() for details).
62 *
63 * The random number generation technique is a linear feedback shift register
64 * approach, employing trinomials (since there are fewer terms to sum up that
65 * way). In this approach, the least significant bit of all the numbers in
66 * the state table will act as a linear feedback shift register, and will
67 * have period 2^deg - 1 (where deg is the degree of the polynomial being
68 * used, assuming that the polynomial is irreducible and primitive). The
69 * higher order bits will have longer periods, since their values are also
70 * influenced by pseudo-random carries out of the lower bits. The total
71 * period of the generator is approximately deg*(2**deg - 1); thus doubling
72 * the amount of state information has a vast influence on the period of the
73 * generator. Note: the deg*(2**deg - 1) is an approximation only good for
74 * large deg, when the period of the shift register is the dominant factor.
75 * With deg equal to seven, the period is actually much longer than the
76 * 7*(2**7 - 1) predicted by this formula.
77 */
78
79/*
80 * For each of the currently supported random number generators, we have a
81 * break value on the amount of state information (you need at least this
82 * many bytes of state info to support this random number generator), a degree
83 * for the polynomial (actually a trinomial) that the R.N.G. is based on, and
84 * the separation between the two lower order coefficients of the trinomial.
85 */
86#define TYPE_0 0 /* linear congruential */
87#define BREAK_0 8
88#define DEG_0 0
89#define SEP_0 0
90
91#define TYPE_1 1 /* x**7 + x**3 + 1 */
92#define BREAK_1 32
93#define DEG_1 7
94#define SEP_1 3
95
96#define TYPE_2 2 /* x**15 + x + 1 */
97#define BREAK_2 64
98#define DEG_2 15
99#define SEP_2 1
100
101#define TYPE_3 3 /* x**31 + x**3 + 1 */
102#define BREAK_3 128
103#define DEG_3 31
104#define SEP_3 3
105
106#define TYPE_4 4 /* x**63 + x + 1 */
107#define BREAK_4 256
108#define DEG_4 63
109#define SEP_4 1
110
111/*
112 * Array versions of the above information to make code run faster --
113 * relies on fact that TYPE_i == i.
114 */
115#define MAX_TYPES 5 /* max number of types above */
116
117static int degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 };
118static int seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
119
120/*
121 * Initially, everything is set up as if from:
122 *
123 * initstate(1, &randtbl, 128);
124 *
125 * Note that this initialization takes advantage of the fact that srandom()
126 * advances the front and rear pointers 10*rand_deg times, and hence the
127 * rear pointer which starts at 0 will also end up at zero; thus the zeroeth
128 * element of the state information, which contains info about the current
129 * position of the rear pointer is just
130 *
131 * MAX_TYPES * (rptr - state) + TYPE_3 == TYPE_3.
132 */
133
134static int32_t randtbl[DEG_3 + 1] = {
135 TYPE_3,
136 0x991539b1, 0x16a5bce3, 0x6774a4cd, 0x3e01511e, 0x4e508aaa, 0x61048c05,
137 0xf5500617, 0x846b7115, 0x6a19892c, 0x896a97af, 0xdb48f936, 0x14898454,
138 0x37ffd106, 0xb58bff9c, 0x59e17104, 0xcf918a49, 0x09378c83, 0x52c7a471,
139 0x8d293ea9, 0x1f4fc301, 0xc3db71be, 0x39b44e1c, 0xf8a44ef9, 0x4c8b80b1,
140 0x19edc328, 0x87bf4bdd, 0xc9b240e5, 0xe9ee4b1b, 0x4382aee7, 0x535b6b41,
141 0xf3bec5da,
142};
143
144/*
145 * fptr and rptr are two pointers into the state info, a front and a rear
146 * pointer. These two pointers are always rand_sep places aparts, as they
147 * cycle cyclically through the state information. (Yes, this does mean we
148 * could get away with just one pointer, but the code for random() is more
149 * efficient this way). The pointers are left positioned as they would be
150 * from the call
151 *
152 * initstate(1, randtbl, 128);
153 *
154 * (The position of the rear pointer, rptr, is really 0 (as explained above
155 * in the initialization of randtbl) because the state table pointer is set
156 * to point to randtbl[1] (as explained below).
157 */
158static int32_t *fptr = &randtbl[SEP_3 + 1];
159static int32_t *rptr = &randtbl[1];
160
161/*
162 * The following things are the pointer to the state information table, the
163 * type of the current generator, the degree of the current polynomial being
164 * used, and the separation between the two pointers. Note that for efficiency
165 * of random(), we remember the first location of the state information, not
166 * the zeroeth. Hence it is valid to access state[-1], which is used to
167 * store the type of the R.N.G. Also, we remember the last location, since
168 * this is more efficient than indexing every time to find the address of
169 * the last element to see if the front and rear pointers have wrapped.
170 */
171static int32_t *state = &randtbl[1];
172static int32_t *end_ptr = &randtbl[DEG_3 + 1];
173static int rand_type = TYPE_3;
174static int rand_deg = DEG_3;
175static int rand_sep = SEP_3;
176
177/*
178 * srandom:
179 *
180 * Initialize the random number generator based on the given seed. If the
181 * type is the trivial no-state-information type, just remember the seed.
182 * Otherwise, initializes state[] based on the given "seed" via a linear
183 * congruential generator. Then, the pointers are set to known locations
184 * that are exactly rand_sep places apart. Lastly, it cycles the state
185 * information a given number of times to get rid of any initial dependencies
186 * introduced by the L.C.R.N.G. Note that the initialization of randtbl[]
187 * for default usage relies on values produced by this routine.
188 */
189void
190srandom(unsigned int x)
191{
192 int i;
193 int32_t test;
194 div_t val;
195
196 if (rand_type == TYPE_0)
197 state[0] = x;
198 else {
199 state[0] = x;
200 for (i = 1; i < rand_deg; i++) {
201 /*
202 * Implement the following, without overflowing 31 bits:
203 *
204 * state[i] = (16807 * state[i - 1]) % 2147483647;
205 *
206 * 2^31-1 (prime) = 2147483647 = 127773*16807+2836
207 */
208 val = div(state[i-1], 127773);
209 test = 16807 * val.rem - 2836 * val.quot;
210 state[i] = test + (test < 0 ? 2147483647 : 0);
211 }
212 fptr = &state[rand_sep];
213 rptr = &state[0];
214 for (i = 0; i < 10 * rand_deg; i++)
215 (void)random();
216 }
217}
218
219/*
220 * srandomdev:
221 *
222 * Many programs choose the seed value in a totally predictable manner.
223 * This often causes problems. We seed the generator using random
224 * data from the kernel.
225 * Note that this particular seeding procedure can generate states
226 * which are impossible to reproduce by calling srandom() with any
227 * value, since the succeeding terms in the state buffer are no longer
228 * derived from the LC algorithm applied to a fixed seed.
229 */
230void
231srandomdev(void)
232{
233 int mib[2];
234 size_t len;
235
236 if (rand_type == TYPE_0)
237 len = sizeof(state[0]);
238 else
239 len = rand_deg * sizeof(state[0]);
240
241 mib[0] = CTL_KERN;
242 mib[1] = KERN_ARND;
243 sysctl(mib, 2, state, &len, NULL, 0);
244
245 if (rand_type != TYPE_0) {
246 fptr = &state[rand_sep];
247 rptr = &state[0];
248 }
249}
250
251/*
252 * initstate:
253 *
254 * Initialize the state information in the given array of n bytes for future
255 * random number generation. Based on the number of bytes we are given, and
256 * the break values for the different R.N.G.'s, we choose the best (largest)
257 * one we can and set things up for it. srandom() is then called to
258 * initialize the state information.
259 *
260 * Note that on return from srandom(), we set state[-1] to be the type
261 * multiplexed with the current value of the rear pointer; this is so
262 * successive calls to initstate() won't lose this information and will be
263 * able to restart with setstate().
264 *
265 * Note: the first thing we do is save the current state, if any, just like
266 * setstate() so that it doesn't matter when initstate is called.
267 *
268 * Returns a pointer to the old state.
269 */
270char *
271initstate(u_int seed, char *arg_state, size_t n)
272{
273 char *ostate = (char *)(&state[-1]);
274
275 if (rand_type == TYPE_0)
276 state[-1] = rand_type;
277 else
278 state[-1] = MAX_TYPES * (rptr - state) + rand_type;
279 if (n < BREAK_0)
280 return(NULL);
281 if (n < BREAK_1) {
282 rand_type = TYPE_0;
283 rand_deg = DEG_0;
284 rand_sep = SEP_0;
285 } else if (n < BREAK_2) {
286 rand_type = TYPE_1;
287 rand_deg = DEG_1;
288 rand_sep = SEP_1;
289 } else if (n < BREAK_3) {
290 rand_type = TYPE_2;
291 rand_deg = DEG_2;
292 rand_sep = SEP_2;
293 } else if (n < BREAK_4) {
294 rand_type = TYPE_3;
295 rand_deg = DEG_3;
296 rand_sep = SEP_3;
297 } else {
298 rand_type = TYPE_4;
299 rand_deg = DEG_4;
300 rand_sep = SEP_4;
301 }
302 state = &(((int32_t *)arg_state)[1]); /* first location */
303 end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */
304 srandom(seed);
305 if (rand_type == TYPE_0)
306 state[-1] = rand_type;
307 else
308 state[-1] = MAX_TYPES*(rptr - state) + rand_type;
309 return(ostate);
310}
311
312/*
313 * setstate:
314 *
315 * Restore the state from the given state array.
316 *
317 * Note: it is important that we also remember the locations of the pointers
318 * in the current state information, and restore the locations of the pointers
319 * from the old state information. This is done by multiplexing the pointer
320 * location into the zeroeth word of the state information.
321 *
322 * Note that due to the order in which things are done, it is OK to call
323 * setstate() with the same state as the current state.
324 *
325 * Returns a pointer to the old state information.
326 */
327char *
328setstate(const char *arg_state)
329{
330 int32_t *new_state = (int32_t *)arg_state;
331 int32_t type = new_state[0] % MAX_TYPES;
332 int32_t rear = new_state[0] / MAX_TYPES;
333 char *ostate = (char *)(&state[-1]);
334
335 if (rand_type == TYPE_0)
336 state[-1] = rand_type;
337 else
338 state[-1] = MAX_TYPES * (rptr - state) + rand_type;
339 switch(type) {
340 case TYPE_0:
341 case TYPE_1:
342 case TYPE_2:
343 case TYPE_3:
344 case TYPE_4:
345 rand_type = type;
346 rand_deg = degrees[type];
347 rand_sep = seps[type];
348 break;
349 default:
350 return(NULL);
351 }
352 state = &new_state[1];
353 if (rand_type != TYPE_0) {
354 rptr = &state[rear];
355 fptr = &state[(rear + rand_sep) % rand_deg];
356 }
357 end_ptr = &state[rand_deg]; /* set end_ptr too */
358 return(ostate);
359}
360
361/*
362 * random:
363 *
364 * If we are using the trivial TYPE_0 R.N.G., just do the old linear
365 * congruential bit. Otherwise, we do our fancy trinomial stuff, which is
366 * the same in all the other cases due to all the global variables that have
367 * been set up. The basic operation is to add the number at the rear pointer
368 * into the one at the front pointer. Then both pointers are advanced to
369 * the next location cyclically in the table. The value returned is the sum
370 * generated, reduced to 31 bits by throwing away the "least random" low bit.
371 *
372 * Note: the code takes advantage of the fact that both the front and
373 * rear pointers can't wrap on the same call by not testing the rear
374 * pointer if the front one has wrapped.
375 *
376 * Returns a 31-bit random number.
377 */
378long
379random(void)
380{
381 int32_t i;
382
383 if (rand_type == TYPE_0)
384 i = state[0] = (state[0] * 1103515245 + 12345) & 0x7fffffff;
385 else {
386 *fptr += *rptr;
387 i = (*fptr >> 1) & 0x7fffffff; /* chucking least random bit */
388 if (++fptr >= end_ptr) {
389 fptr = state;
390 ++rptr;
391 } else if (++rptr >= end_ptr)
392 rptr = state;
393 }
394 return((long)i);
395}
diff --git a/src/lib/libc/stdlib/realpath.3 b/src/lib/libc/stdlib/realpath.3
new file mode 100644
index 0000000000..e1e0b10605
--- /dev/null
+++ b/src/lib/libc/stdlib/realpath.3
@@ -0,0 +1,117 @@
1.\" Copyright (c) 1994
2.\" The Regents of the University of California. All rights reserved.
3.\"
4.\" This code is derived from software contributed to Berkeley by
5.\" Jan-Simon Pendry.
6.\"
7.\" Redistribution and use in source and binary forms, with or without
8.\" modification, are permitted provided that the following conditions
9.\" are met:
10.\" 1. Redistributions of source code must retain the above copyright
11.\" notice, this list of conditions and the following disclaimer.
12.\" 2. Redistributions in binary form must reproduce the above copyright
13.\" notice, this list of conditions and the following disclaimer in the
14.\" documentation and/or other materials provided with the distribution.
15.\" 3. Neither the name of the University nor the names of its contributors
16.\" may be used to endorse or promote products derived from this software
17.\" without specific prior written permission.
18.\"
19.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29.\" SUCH DAMAGE.
30.\"
31.\" $OpenBSD: realpath.3,v 1.13 2005/04/03 18:59:15 otto Exp $
32.\"
33.Dd February 16, 1994
34.Dt REALPATH 3
35.Os
36.Sh NAME
37.Nm realpath
38.Nd returns the canonicalized absolute pathname
39.Sh SYNOPSIS
40.Fd #include <sys/param.h>
41.Fd #include <stdlib.h>
42.Ft "char *"
43.Fn realpath "const char *pathname" "char resolved[PATH_MAX]"
44.Sh DESCRIPTION
45The
46.Fn realpath
47function resolves all symbolic links, extra
48.Dq /
49characters and references to
50.Pa /./
51and
52.Pa /../
53in
54.Fa pathname ,
55and copies the resulting absolute pathname into the memory referenced by
56.Fa resolved .
57The
58.Fa resolved
59argument
60.Em must
61refer to a buffer capable of storing at least
62.Dv PATH_MAX
63characters.
64.Pp
65The
66.Fn realpath
67function will resolve both absolute and relative paths
68and return the absolute pathname corresponding to
69.Fa pathname .
70All but the last component of
71.Fa pathname
72must exist when
73.Fn realpath
74is called.
75.Sh RETURN VALUES
76The
77.Fn realpath
78function returns
79.Fa resolved
80on success.
81If an error occurs,
82.Fn realpath
83returns
84.Dv NULL
85and the contents of
86.Fa resolved
87are undefined.
88.Sh ERRORS
89The function
90.Fn realpath
91may fail and set the external variable
92.Va errno
93for any of the errors specified for the library functions
94.Xr lstat 2 ,
95.Xr readlink 2 ,
96and
97.Xr getcwd 3 .
98.Sh SEE ALSO
99.Xr readlink 1 ,
100.Xr getcwd 3
101.Sh HISTORY
102The
103.Fn realpath
104function call first appeared in
105.Bx 4.4 .
106.Sh CAVEATS
107This implementation of
108.Fn realpath
109differs slightly from the Solaris implementation.
110The
111.Bx 4.4
112version always returns absolute pathnames,
113whereas the Solaris implementation will,
114under certain circumstances, return a relative
115.Fa resolved
116when given a relative
117.Fa pathname .
diff --git a/src/lib/libc/stdlib/realpath.c b/src/lib/libc/stdlib/realpath.c
new file mode 100644
index 0000000000..4cb847b313
--- /dev/null
+++ b/src/lib/libc/stdlib/realpath.c
@@ -0,0 +1,190 @@
1/* $OpenBSD: realpath.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */
2/*
3 * Copyright (c) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru>
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 names of the authors may not be used to endorse or promote
14 * products derived from this software without specific prior written
15 * permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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#include <sys/param.h>
31#include <sys/stat.h>
32
33#include <errno.h>
34#include <stdlib.h>
35#include <string.h>
36#include <unistd.h>
37
38/*
39 * char *realpath(const char *path, char resolved[PATH_MAX]);
40 *
41 * Find the real name of path, by removing all ".", ".." and symlink
42 * components. Returns (resolved) on success, or (NULL) on failure,
43 * in which case the path which caused trouble is left in (resolved).
44 */
45char *
46realpath(const char *path, char resolved[PATH_MAX])
47{
48 struct stat sb;
49 char *p, *q, *s;
50 size_t left_len, resolved_len;
51 unsigned symlinks;
52 int serrno, slen;
53 char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
54
55 serrno = errno;
56 symlinks = 0;
57 if (path[0] == '/') {
58 resolved[0] = '/';
59 resolved[1] = '\0';
60 if (path[1] == '\0')
61 return (resolved);
62 resolved_len = 1;
63 left_len = strlcpy(left, path + 1, sizeof(left));
64 } else {
65 if (getcwd(resolved, PATH_MAX) == NULL) {
66 strlcpy(resolved, ".", PATH_MAX);
67 return (NULL);
68 }
69 resolved_len = strlen(resolved);
70 left_len = strlcpy(left, path, sizeof(left));
71 }
72 if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
73 errno = ENAMETOOLONG;
74 return (NULL);
75 }
76
77 /*
78 * Iterate over path components in `left'.
79 */
80 while (left_len != 0) {
81 /*
82 * Extract the next path component and adjust `left'
83 * and its length.
84 */
85 p = strchr(left, '/');
86 s = p ? p : left + left_len;
87 if (s - left >= sizeof(next_token)) {
88 errno = ENAMETOOLONG;
89 return (NULL);
90 }
91 memcpy(next_token, left, s - left);
92 next_token[s - left] = '\0';
93 left_len -= s - left;
94 if (p != NULL)
95 memmove(left, s + 1, left_len + 1);
96 if (resolved[resolved_len - 1] != '/') {
97 if (resolved_len + 1 >= PATH_MAX) {
98 errno = ENAMETOOLONG;
99 return (NULL);
100 }
101 resolved[resolved_len++] = '/';
102 resolved[resolved_len] = '\0';
103 }
104 if (next_token[0] == '\0')
105 continue;
106 else if (strcmp(next_token, ".") == 0)
107 continue;
108 else if (strcmp(next_token, "..") == 0) {
109 /*
110 * Strip the last path component except when we have
111 * single "/"
112 */
113 if (resolved_len > 1) {
114 resolved[resolved_len - 1] = '\0';
115 q = strrchr(resolved, '/') + 1;
116 *q = '\0';
117 resolved_len = q - resolved;
118 }
119 continue;
120 }
121
122 /*
123 * Append the next path component and lstat() it. If
124 * lstat() fails we still can return successfully if
125 * there are no more path components left.
126 */
127 resolved_len = strlcat(resolved, next_token, PATH_MAX);
128 if (resolved_len >= PATH_MAX) {
129 errno = ENAMETOOLONG;
130 return (NULL);
131 }
132 if (lstat(resolved, &sb) != 0) {
133 if (errno == ENOENT && p == NULL) {
134 errno = serrno;
135 return (resolved);
136 }
137 return (NULL);
138 }
139 if (S_ISLNK(sb.st_mode)) {
140 if (symlinks++ > MAXSYMLINKS) {
141 errno = ELOOP;
142 return (NULL);
143 }
144 slen = readlink(resolved, symlink, sizeof(symlink) - 1);
145 if (slen < 0)
146 return (NULL);
147 symlink[slen] = '\0';
148 if (symlink[0] == '/') {
149 resolved[1] = 0;
150 resolved_len = 1;
151 } else if (resolved_len > 1) {
152 /* Strip the last path component. */
153 resolved[resolved_len - 1] = '\0';
154 q = strrchr(resolved, '/') + 1;
155 *q = '\0';
156 resolved_len = q - resolved;
157 }
158
159 /*
160 * If there are any path components left, then
161 * append them to symlink. The result is placed
162 * in `left'.
163 */
164 if (p != NULL) {
165 if (symlink[slen - 1] != '/') {
166 if (slen + 1 >= sizeof(symlink)) {
167 errno = ENAMETOOLONG;
168 return (NULL);
169 }
170 symlink[slen] = '/';
171 symlink[slen + 1] = 0;
172 }
173 left_len = strlcat(symlink, left, sizeof(left));
174 if (left_len >= sizeof(left)) {
175 errno = ENAMETOOLONG;
176 return (NULL);
177 }
178 }
179 left_len = strlcpy(left, symlink, sizeof(left));
180 }
181 }
182
183 /*
184 * Remove trailing slash except when the resolved pathname
185 * is a single "/".
186 */
187 if (resolved_len > 1 && resolved[resolved_len - 1] == '/')
188 resolved[resolved_len - 1] = '\0';
189 return (resolved);
190}
diff --git a/src/lib/libc/stdlib/remque.c b/src/lib/libc/stdlib/remque.c
new file mode 100644
index 0000000000..ae249ae053
--- /dev/null
+++ b/src/lib/libc/stdlib/remque.c
@@ -0,0 +1,44 @@
1/* $OpenBSD: remque.c,v 1.2 2005/08/08 08:05:37 espie 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#include <search.h>
32
33struct qelem {
34 struct qelem *q_forw;
35 struct qelem *q_back;
36};
37
38void
39remque(void *element)
40{
41 struct qelem *e = (struct qelem *) element;
42 e->q_forw->q_back = e->q_back;
43 e->q_back->q_forw = e->q_forw;
44}
diff --git a/src/lib/libc/stdlib/seed48.c b/src/lib/libc/stdlib/seed48.c
new file mode 100644
index 0000000000..583262f2d5
--- /dev/null
+++ b/src/lib/libc/stdlib/seed48.c
@@ -0,0 +1,37 @@
1/* $OpenBSD: seed48.c,v 1.3 2005/08/08 08:05:37 espie Exp $ */
2/*
3 * Copyright (c) 1993 Martin Birgmeier
4 * All rights reserved.
5 *
6 * You may redistribute unmodified or modified versions of this source
7 * code provided that the above copyright notice and this and the
8 * following conditions are retained.
9 *
10 * This software is provided ``as is'', and comes with no warranties
11 * of any kind. I shall in no event be liable for anything that happens
12 * to anyone/anything when using this software.
13 */
14
15#include "rand48.h"
16
17extern unsigned short __rand48_seed[3];
18extern unsigned short __rand48_mult[3];
19extern unsigned short __rand48_add;
20
21unsigned short *
22seed48(unsigned short xseed[3])
23{
24 static unsigned short sseed[3];
25
26 sseed[0] = __rand48_seed[0];
27 sseed[1] = __rand48_seed[1];
28 sseed[2] = __rand48_seed[2];
29 __rand48_seed[0] = xseed[0];
30 __rand48_seed[1] = xseed[1];
31 __rand48_seed[2] = xseed[2];
32 __rand48_mult[0] = RAND48_MULT_0;
33 __rand48_mult[1] = RAND48_MULT_1;
34 __rand48_mult[2] = RAND48_MULT_2;
35 __rand48_add = RAND48_ADD;
36 return sseed;
37}
diff --git a/src/lib/libc/stdlib/setenv.c b/src/lib/libc/stdlib/setenv.c
new file mode 100644
index 0000000000..36540ebb0c
--- /dev/null
+++ b/src/lib/libc/stdlib/setenv.c
@@ -0,0 +1,103 @@
1/* $OpenBSD: setenv.c,v 1.9 2005/08/08 08:05:37 espie Exp $ */
2/*
3 * Copyright (c) 1987 Regents of the University of California.
4 * 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
31#include <stdlib.h>
32#include <string.h>
33
34char *__findenv(const char *name, int *offset);
35
36extern char **environ;
37
38/*
39 * setenv --
40 * Set the value of the environmental variable "name" to be
41 * "value". If rewrite is set, replace any current value.
42 */
43int
44setenv(const char *name, const char *value, int rewrite)
45{
46 static char **lastenv; /* last value of environ */
47 char *C;
48 int l_value, offset;
49
50 if (*value == '=') /* no `=' in value */
51 ++value;
52 l_value = strlen(value);
53 if ((C = __findenv(name, &offset))) { /* find if already exists */
54 if (!rewrite)
55 return (0);
56 if (strlen(C) >= l_value) { /* old larger; copy over */
57 while ((*C++ = *value++))
58 ;
59 return (0);
60 }
61 } else { /* create new slot */
62 size_t cnt;
63 char **P;
64
65 for (P = environ; *P != NULL; P++)
66 ;
67 cnt = P - environ;
68 P = (char **)realloc(lastenv, sizeof(char *) * (cnt + 2));
69 if (!P)
70 return (-1);
71 if (lastenv != environ)
72 memcpy(P, environ, cnt * sizeof(char *));
73 lastenv = environ = P;
74 offset = cnt;
75 environ[cnt + 1] = NULL;
76 }
77 for (C = (char *)name; *C && *C != '='; ++C)
78 ; /* no `=' in name */
79 if (!(environ[offset] = /* name + `=' + value */
80 malloc((size_t)((int)(C - name) + l_value + 2))))
81 return (-1);
82 for (C = environ[offset]; (*C = *name++) && *C != '='; ++C)
83 ;
84 for (*C++ = '='; (*C++ = *value++); )
85 ;
86 return (0);
87}
88
89/*
90 * unsetenv(name) --
91 * Delete environmental variable "name".
92 */
93void
94unsetenv(const char *name)
95{
96 char **P;
97 int offset;
98
99 while (__findenv(name, &offset)) /* if set multiple times */
100 for (P = &environ[offset];; ++P)
101 if (!(*P = *(P + 1)))
102 break;
103}
diff --git a/src/lib/libc/stdlib/srand48.c b/src/lib/libc/stdlib/srand48.c
new file mode 100644
index 0000000000..f76b6cca86
--- /dev/null
+++ b/src/lib/libc/stdlib/srand48.c
@@ -0,0 +1,31 @@
1/* $OpenBSD: srand48.c,v 1.3 2005/08/08 08:05:37 espie Exp $ */
2/*
3 * Copyright (c) 1993 Martin Birgmeier
4 * All rights reserved.
5 *
6 * You may redistribute unmodified or modified versions of this source
7 * code provided that the above copyright notice and this and the
8 * following conditions are retained.
9 *
10 * This software is provided ``as is'', and comes with no warranties
11 * of any kind. I shall in no event be liable for anything that happens
12 * to anyone/anything when using this software.
13 */
14
15#include "rand48.h"
16
17extern unsigned short __rand48_seed[3];
18extern unsigned short __rand48_mult[3];
19extern unsigned short __rand48_add;
20
21void
22srand48(long seed)
23{
24 __rand48_seed[0] = RAND48_SEED_0;
25 __rand48_seed[1] = (unsigned short) seed;
26 __rand48_seed[2] = (unsigned short) (seed >> 16);
27 __rand48_mult[0] = RAND48_MULT_0;
28 __rand48_mult[1] = RAND48_MULT_1;
29 __rand48_mult[2] = RAND48_MULT_2;
30 __rand48_add = RAND48_ADD;
31}
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..d01158e10c
--- /dev/null
+++ b/src/lib/libc/stdlib/strtod.c
@@ -0,0 +1,2408 @@
1/* $OpenBSD: strtod.c,v 1.22 2006/05/19 14:15:27 thib Exp $ */
2/****************************************************************
3 *
4 * The author of this software is David M. Gay.
5 *
6 * Copyright (c) 1991 by AT&T.
7 *
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose without fee is hereby granted, provided that this entire notice
10 * is included in all copies of any software which is or includes a copy
11 * or modification of this software and in all copies of the supporting
12 * documentation for such software.
13 *
14 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
15 * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY
16 * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
17 * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
18 *
19 ***************************************************************/
20
21/* Please send bug reports to
22 David M. Gay
23 AT&T Bell Laboratories, Room 2C-463
24 600 Mountain Avenue
25 Murray Hill, NJ 07974-2070
26 U.S.A.
27 dmg@research.att.com or research!dmg
28 */
29
30/* strtod for IEEE-, VAX-, and IBM-arithmetic machines.
31 *
32 * This strtod returns a nearest machine number to the input decimal
33 * string (or sets errno to ERANGE). With IEEE arithmetic, ties are
34 * broken by the IEEE round-even rule. Otherwise ties are broken by
35 * biased rounding (add half and chop).
36 *
37 * Inspired loosely by William D. Clinger's paper "How to Read Floating
38 * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101].
39 *
40 * Modifications:
41 *
42 * 1. We only require IEEE, IBM, or VAX double-precision
43 * arithmetic (not IEEE double-extended).
44 * 2. We get by with floating-point arithmetic in a case that
45 * Clinger missed -- when we're computing d * 10^n
46 * for a small integer d and the integer n is not too
47 * much larger than 22 (the maximum integer k for which
48 * we can represent 10^k exactly), we may be able to
49 * compute (d*10^k) * 10^(e-k) with just one roundoff.
50 * 3. Rather than a bit-at-a-time adjustment of the binary
51 * result in the hard case, we use floating-point
52 * arithmetic to determine the adjustment to within
53 * one bit; only in really hard cases do we need to
54 * compute a second residual.
55 * 4. Because of 3., we don't need a large table of powers of 10
56 * for ten-to-e (just some small tables, e.g. of 10^k
57 * for 0 <= k <= 22).
58 */
59
60/*
61 * #define IEEE_LITTLE_ENDIAN for IEEE-arithmetic machines where the least
62 * significant byte has the lowest address.
63 * #define IEEE_BIG_ENDIAN for IEEE-arithmetic machines where the most
64 * significant byte has the lowest address.
65 * #define Long int on machines with 32-bit ints and 64-bit longs.
66 * #define Sudden_Underflow for IEEE-format machines without gradual
67 * underflow (i.e., that flush to zero on underflow).
68 * #define IBM for IBM mainframe-style floating-point arithmetic.
69 * #define VAX for VAX-style floating-point arithmetic.
70 * #define Unsigned_Shifts if >> does treats its left operand as unsigned.
71 * #define No_leftright to omit left-right logic in fast floating-point
72 * computation of dtoa.
73 * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3.
74 * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines
75 * that use extended-precision instructions to compute rounded
76 * products and quotients) with IBM.
77 * #define ROUND_BIASED for IEEE-format with biased rounding.
78 * #define Inaccurate_Divide for IEEE-format with correctly rounded
79 * products but inaccurate quotients, e.g., for Intel i860.
80 * #define Just_16 to store 16 bits per 32-bit Long when doing high-precision
81 * integer arithmetic. Whether this speeds things up or slows things
82 * down depends on the machine and the number being converted.
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(__m68k__) || defined(__sparc__) || defined(__i386__) || \
93 defined(__mips__) || defined(__ns32k__) || defined(__alpha__) || \
94 defined(__powerpc__) || defined(__m88k__) || defined(__hppa__) || \
95 defined(__x86_64__) || (defined(__arm__) && defined(__VFP_FP__))
96#include <sys/types.h>
97#if BYTE_ORDER == BIG_ENDIAN
98#define IEEE_BIG_ENDIAN
99#else
100#define IEEE_LITTLE_ENDIAN
101#endif
102#endif
103
104#if defined(__arm__) && !defined(__VFP_FP__)
105/*
106 * Although the CPU is little endian the FP has different
107 * byte and word endianness. The byte order is still little endian
108 * but the word order is big endian.
109 */
110#define IEEE_BIG_ENDIAN
111#endif
112
113#ifdef __vax__
114#define VAX
115#endif
116
117#define Long int32_t
118#define ULong u_int32_t
119
120#ifdef DEBUG
121#include "stdio.h"
122#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);}
123#endif
124
125#ifdef __cplusplus
126#include "malloc.h"
127#include "memory.h"
128#else
129#include "stdlib.h"
130#include "string.h"
131#include "locale.h"
132#endif
133
134#ifdef MALLOC
135extern void *MALLOC(size_t);
136#else
137#define MALLOC malloc
138#endif
139
140#include "ctype.h"
141#include "errno.h"
142
143#ifdef Bad_float_h
144#ifdef IEEE_BIG_ENDIAN
145#define IEEE_ARITHMETIC
146#endif
147#ifdef IEEE_LITTLE_ENDIAN
148#define IEEE_ARITHMETIC
149#endif
150
151#ifdef IEEE_ARITHMETIC
152#define DBL_DIG 15
153#define DBL_MAX_10_EXP 308
154#define DBL_MAX_EXP 1024
155#define FLT_RADIX 2
156#define FLT_ROUNDS 1
157#define DBL_MAX 1.7976931348623157e+308
158#endif
159
160#ifdef IBM
161#define DBL_DIG 16
162#define DBL_MAX_10_EXP 75
163#define DBL_MAX_EXP 63
164#define FLT_RADIX 16
165#define FLT_ROUNDS 0
166#define DBL_MAX 7.2370055773322621e+75
167#endif
168
169#ifdef VAX
170#define DBL_DIG 16
171#define DBL_MAX_10_EXP 38
172#define DBL_MAX_EXP 127
173#define FLT_RADIX 2
174#define FLT_ROUNDS 1
175#define DBL_MAX 1.7014118346046923e+38
176#endif
177
178#ifndef LONG_MAX
179#define LONG_MAX 2147483647
180#endif
181#else
182#include "float.h"
183#endif
184#ifndef __MATH_H__
185#include "math.h"
186#endif
187
188#ifdef __cplusplus
189extern "C" {
190#endif
191
192#ifndef CONST
193#define CONST const
194#endif
195
196#ifdef Unsigned_Shifts
197#define Sign_Extend(a,b) if (b < 0) a |= 0xffff0000;
198#else
199#define Sign_Extend(a,b) /*no-op*/
200#endif
201
202#if defined(IEEE_LITTLE_ENDIAN) + defined(IEEE_BIG_ENDIAN) + defined(VAX) + \
203 defined(IBM) != 1
204Exactly one of IEEE_LITTLE_ENDIAN IEEE_BIG_ENDIAN, VAX, or
205IBM should be defined.
206#endif
207
208typedef union {
209 double d;
210 ULong ul[2];
211} _double;
212#define value(x) ((x).d)
213#ifdef IEEE_LITTLE_ENDIAN
214#define word0(x) ((x).ul[1])
215#define word1(x) ((x).ul[0])
216#else
217#define word0(x) ((x).ul[0])
218#define word1(x) ((x).ul[1])
219#endif
220
221/* The following definition of Storeinc is appropriate for MIPS processors.
222 * An alternative that might be better on some machines is
223 * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff)
224 */
225#if defined(IEEE_LITTLE_ENDIAN) + defined(VAX) + defined(__arm__)
226#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \
227((unsigned short *)a)[0] = (unsigned short)c, a++)
228#else
229#define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \
230((unsigned short *)a)[1] = (unsigned short)c, a++)
231#endif
232
233/* #define P DBL_MANT_DIG */
234/* Ten_pmax = floor(P*log(2)/log(5)) */
235/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */
236/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */
237/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */
238
239#if defined(IEEE_LITTLE_ENDIAN) + defined(IEEE_BIG_ENDIAN)
240#define Exp_shift 20
241#define Exp_shift1 20
242#define Exp_msk1 0x100000
243#define Exp_msk11 0x100000
244#define Exp_mask 0x7ff00000
245#define P 53
246#define Bias 1023
247#define IEEE_Arith
248#define Emin (-1022)
249#define Exp_1 0x3ff00000
250#define Exp_11 0x3ff00000
251#define Ebits 11
252#define Frac_mask 0xfffff
253#define Frac_mask1 0xfffff
254#define Ten_pmax 22
255#define Bletch 0x10
256#define Bndry_mask 0xfffff
257#define Bndry_mask1 0xfffff
258#define LSB 1
259#define Sign_bit 0x80000000
260#define Log2P 1
261#define Tiny0 0
262#define Tiny1 1
263#define Quick_max 14
264#define Int_max 14
265#define Infinite(x) (word0(x) == 0x7ff00000) /* sufficient test for here */
266#else
267#undef Sudden_Underflow
268#define Sudden_Underflow
269#ifdef IBM
270#define Exp_shift 24
271#define Exp_shift1 24
272#define Exp_msk1 0x1000000
273#define Exp_msk11 0x1000000
274#define Exp_mask 0x7f000000
275#define P 14
276#define Bias 65
277#define Exp_1 0x41000000
278#define Exp_11 0x41000000
279#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */
280#define Frac_mask 0xffffff
281#define Frac_mask1 0xffffff
282#define Bletch 4
283#define Ten_pmax 22
284#define Bndry_mask 0xefffff
285#define Bndry_mask1 0xffffff
286#define LSB 1
287#define Sign_bit 0x80000000
288#define Log2P 4
289#define Tiny0 0x100000
290#define Tiny1 0
291#define Quick_max 14
292#define Int_max 15
293#else /* VAX */
294#define Exp_shift 23
295#define Exp_shift1 7
296#define Exp_msk1 0x80
297#define Exp_msk11 0x800000
298#define Exp_mask 0x7f80
299#define P 56
300#define Bias 129
301#define Exp_1 0x40800000
302#define Exp_11 0x4080
303#define Ebits 8
304#define Frac_mask 0x7fffff
305#define Frac_mask1 0xffff007f
306#define Ten_pmax 24
307#define Bletch 2
308#define Bndry_mask 0xffff007f
309#define Bndry_mask1 0xffff007f
310#define LSB 0x10000
311#define Sign_bit 0x8000
312#define Log2P 1
313#define Tiny0 0x80
314#define Tiny1 0
315#define Quick_max 15
316#define Int_max 15
317#endif
318#endif
319
320#ifndef IEEE_Arith
321#define ROUND_BIASED
322#endif
323
324#ifdef RND_PRODQUOT
325#define rounded_product(a,b) a = rnd_prod(a, b)
326#define rounded_quotient(a,b) a = rnd_quot(a, b)
327extern double rnd_prod(double, double), rnd_quot(double, double);
328#else
329#define rounded_product(a,b) a *= b
330#define rounded_quotient(a,b) a /= b
331#endif
332
333#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1))
334#define Big1 0xffffffff
335
336#ifndef Just_16
337/* When Pack_32 is not defined, we store 16 bits per 32-bit Long.
338 * This makes some inner loops simpler and sometimes saves work
339 * during multiplications, but it often seems to make things slightly
340 * slower. Hence the default is now to store 32 bits per Long.
341 */
342#ifndef Pack_32
343#define Pack_32
344#endif
345#endif
346
347#define Kmax 15
348
349#ifdef __cplusplus
350extern "C" double strtod(const char *s00, char **se);
351extern "C" char *__dtoa(double d, int mode, int ndigits,
352 int *decpt, int *sign, char **rve);
353#endif
354
355 struct
356Bigint {
357 struct Bigint *next;
358 int k, maxwds, sign, wds;
359 ULong x[1];
360 };
361
362 typedef struct Bigint Bigint;
363
364 static Bigint *freelist[Kmax+1];
365
366 static Bigint *
367Balloc(int k)
368{
369 int x;
370 Bigint *rv;
371
372 if ((rv = freelist[k])) {
373 freelist[k] = rv->next;
374 }
375 else {
376 x = 1 << k;
377 rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(Long));
378 rv->k = k;
379 rv->maxwds = x;
380 }
381 rv->sign = rv->wds = 0;
382 return rv;
383 }
384
385 static void
386Bfree(Bigint *v)
387{
388 if (v) {
389 v->next = freelist[v->k];
390 freelist[v->k] = v;
391 }
392 }
393
394#define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \
395y->wds*sizeof(Long) + 2*sizeof(int))
396
397 static Bigint *
398multadd(Bigint *b, int m, int a) /* multiply by m and add a */
399{
400 int i, wds;
401 ULong *x, y;
402#ifdef Pack_32
403 ULong xi, z;
404#endif
405 Bigint *b1;
406
407 wds = b->wds;
408 x = b->x;
409 i = 0;
410 do {
411#ifdef Pack_32
412 xi = *x;
413 y = (xi & 0xffff) * m + a;
414 z = (xi >> 16) * m + (y >> 16);
415 a = (int)(z >> 16);
416 *x++ = (z << 16) + (y & 0xffff);
417#else
418 y = *x * m + a;
419 a = (int)(y >> 16);
420 *x++ = y & 0xffff;
421#endif
422 }
423 while(++i < wds);
424 if (a) {
425 if (wds >= b->maxwds) {
426 b1 = Balloc(b->k+1);
427 Bcopy(b1, b);
428 Bfree(b);
429 b = b1;
430 }
431 b->x[wds++] = a;
432 b->wds = wds;
433 }
434 return b;
435 }
436
437 static Bigint *
438s2b(CONST char *s, int nd0, int nd, ULong y9)
439{
440 Bigint *b;
441 int i, k;
442 Long x, y;
443
444 x = (nd + 8) / 9;
445 for(k = 0, y = 1; x > y; y <<= 1, k++) ;
446#ifdef Pack_32
447 b = Balloc(k);
448 b->x[0] = y9;
449 b->wds = 1;
450#else
451 b = Balloc(k+1);
452 b->x[0] = y9 & 0xffff;
453 b->wds = (b->x[1] = y9 >> 16) ? 2 : 1;
454#endif
455
456 i = 9;
457 if (9 < nd0) {
458 s += 9;
459 do b = multadd(b, 10, *s++ - '0');
460 while(++i < nd0);
461 s++;
462 }
463 else
464 s += 10;
465 for(; i < nd; i++)
466 b = multadd(b, 10, *s++ - '0');
467 return b;
468 }
469
470 static int
471hi0bits(ULong x)
472{
473 int k = 0;
474
475 if (!(x & 0xffff0000)) {
476 k = 16;
477 x <<= 16;
478 }
479 if (!(x & 0xff000000)) {
480 k += 8;
481 x <<= 8;
482 }
483 if (!(x & 0xf0000000)) {
484 k += 4;
485 x <<= 4;
486 }
487 if (!(x & 0xc0000000)) {
488 k += 2;
489 x <<= 2;
490 }
491 if (!(x & 0x80000000)) {
492 k++;
493 if (!(x & 0x40000000))
494 return 32;
495 }
496 return k;
497 }
498
499 static int
500lo0bits(ULong *y)
501{
502 int k;
503 ULong x = *y;
504
505 if (x & 7) {
506 if (x & 1)
507 return 0;
508 if (x & 2) {
509 *y = x >> 1;
510 return 1;
511 }
512 *y = x >> 2;
513 return 2;
514 }
515 k = 0;
516 if (!(x & 0xffff)) {
517 k = 16;
518 x >>= 16;
519 }
520 if (!(x & 0xff)) {
521 k += 8;
522 x >>= 8;
523 }
524 if (!(x & 0xf)) {
525 k += 4;
526 x >>= 4;
527 }
528 if (!(x & 0x3)) {
529 k += 2;
530 x >>= 2;
531 }
532 if (!(x & 1)) {
533 k++;
534 x >>= 1;
535 if (!(x & 1))
536 return 32;
537 }
538 *y = x;
539 return k;
540 }
541
542 static Bigint *
543i2b(int i)
544{
545 Bigint *b;
546
547 b = Balloc(1);
548 b->x[0] = i;
549 b->wds = 1;
550 return b;
551 }
552
553 static Bigint *
554mult(Bigint *a, Bigint *b)
555{
556 Bigint *c;
557 int k, wa, wb, wc;
558 ULong carry, y, z;
559 ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
560#ifdef Pack_32
561 ULong z2;
562#endif
563
564 if (a->wds < b->wds) {
565 c = a;
566 a = b;
567 b = c;
568 }
569 k = a->k;
570 wa = a->wds;
571 wb = b->wds;
572 wc = wa + wb;
573 if (wc > a->maxwds)
574 k++;
575 c = Balloc(k);
576 for(x = c->x, xa = x + wc; x < xa; x++)
577 *x = 0;
578 xa = a->x;
579 xae = xa + wa;
580 xb = b->x;
581 xbe = xb + wb;
582 xc0 = c->x;
583#ifdef Pack_32
584 for(; xb < xbe; xb++, xc0++) {
585 if ((y = *xb & 0xffff)) {
586 x = xa;
587 xc = xc0;
588 carry = 0;
589 do {
590 z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
591 carry = z >> 16;
592 z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
593 carry = z2 >> 16;
594 Storeinc(xc, z2, z);
595 }
596 while(x < xae);
597 *xc = carry;
598 }
599 if ((y = *xb >> 16)) {
600 x = xa;
601 xc = xc0;
602 carry = 0;
603 z2 = *xc;
604 do {
605 z = (*x & 0xffff) * y + (*xc >> 16) + carry;
606 carry = z >> 16;
607 Storeinc(xc, z, z2);
608 z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
609 carry = z2 >> 16;
610 }
611 while(x < xae);
612 *xc = z2;
613 }
614 }
615#else
616 for(; xb < xbe; xc0++) {
617 if (y = *xb++) {
618 x = xa;
619 xc = xc0;
620 carry = 0;
621 do {
622 z = *x++ * y + *xc + carry;
623 carry = z >> 16;
624 *xc++ = z & 0xffff;
625 }
626 while(x < xae);
627 *xc = carry;
628 }
629 }
630#endif
631 for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
632 c->wds = wc;
633 return c;
634 }
635
636 static Bigint *p5s;
637
638 static Bigint *
639pow5mult(Bigint *b, int k)
640{
641 Bigint *b1, *p5, *p51;
642 int i;
643 static int p05[3] = { 5, 25, 125 };
644
645 if ((i = k & 3))
646 b = multadd(b, p05[i-1], 0);
647
648 if (!(k >>= 2))
649 return b;
650 if (!(p5 = p5s)) {
651 /* first time */
652 p5 = p5s = i2b(625);
653 p5->next = 0;
654 }
655 for(;;) {
656 if (k & 1) {
657 b1 = mult(b, p5);
658 Bfree(b);
659 b = b1;
660 }
661 if (!(k >>= 1))
662 break;
663 if (!(p51 = p5->next)) {
664 p51 = p5->next = mult(p5,p5);
665 p51->next = 0;
666 }
667 p5 = p51;
668 }
669 return b;
670 }
671
672 static Bigint *
673lshift(Bigint *b, int k)
674{
675 int i, k1, n, n1;
676 Bigint *b1;
677 ULong *x, *x1, *xe, z;
678
679#ifdef Pack_32
680 n = k >> 5;
681#else
682 n = k >> 4;
683#endif
684 k1 = b->k;
685 n1 = n + b->wds + 1;
686 for(i = b->maxwds; n1 > i; i <<= 1)
687 k1++;
688 b1 = Balloc(k1);
689 x1 = b1->x;
690 for(i = 0; i < n; i++)
691 *x1++ = 0;
692 x = b->x;
693 xe = x + b->wds;
694#ifdef Pack_32
695 if (k &= 0x1f) {
696 k1 = 32 - k;
697 z = 0;
698 do {
699 *x1++ = *x << k | z;
700 z = *x++ >> k1;
701 }
702 while(x < xe);
703 if ((*x1 = z))
704 ++n1;
705 }
706#else
707 if (k &= 0xf) {
708 k1 = 16 - k;
709 z = 0;
710 do {
711 *x1++ = *x << k & 0xffff | z;
712 z = *x++ >> k1;
713 }
714 while(x < xe);
715 if (*x1 = z)
716 ++n1;
717 }
718#endif
719 else do
720 *x1++ = *x++;
721 while(x < xe);
722 b1->wds = n1 - 1;
723 Bfree(b);
724 return b1;
725 }
726
727 static int
728cmp(Bigint *a, Bigint *b)
729{
730 ULong *xa, *xa0, *xb, *xb0;
731 int i, j;
732
733 i = a->wds;
734 j = b->wds;
735#ifdef DEBUG
736 if (i > 1 && !a->x[i-1])
737 Bug("cmp called with a->x[a->wds-1] == 0");
738 if (j > 1 && !b->x[j-1])
739 Bug("cmp called with b->x[b->wds-1] == 0");
740#endif
741 if (i -= j)
742 return i;
743 xa0 = a->x;
744 xa = xa0 + j;
745 xb0 = b->x;
746 xb = xb0 + j;
747 for(;;) {
748 if (*--xa != *--xb)
749 return *xa < *xb ? -1 : 1;
750 if (xa <= xa0)
751 break;
752 }
753 return 0;
754 }
755
756 static Bigint *
757diff(Bigint *a, Bigint *b)
758{
759 Bigint *c;
760 int i, wa, wb;
761 Long borrow, y; /* We need signed shifts here. */
762 ULong *xa, *xae, *xb, *xbe, *xc;
763#ifdef Pack_32
764 Long z;
765#endif
766
767 i = cmp(a,b);
768 if (!i) {
769 c = Balloc(0);
770 c->wds = 1;
771 c->x[0] = 0;
772 return c;
773 }
774 if (i < 0) {
775 c = a;
776 a = b;
777 b = c;
778 i = 1;
779 }
780 else
781 i = 0;
782 c = Balloc(a->k);
783 c->sign = i;
784 wa = a->wds;
785 xa = a->x;
786 xae = xa + wa;
787 wb = b->wds;
788 xb = b->x;
789 xbe = xb + wb;
790 xc = c->x;
791 borrow = 0;
792#ifdef Pack_32
793 do {
794 y = (*xa & 0xffff) - (*xb & 0xffff) + borrow;
795 borrow = y >> 16;
796 Sign_Extend(borrow, y);
797 z = (*xa++ >> 16) - (*xb++ >> 16) + borrow;
798 borrow = z >> 16;
799 Sign_Extend(borrow, z);
800 Storeinc(xc, z, y);
801 }
802 while(xb < xbe);
803 while(xa < xae) {
804 y = (*xa & 0xffff) + borrow;
805 borrow = y >> 16;
806 Sign_Extend(borrow, y);
807 z = (*xa++ >> 16) + borrow;
808 borrow = z >> 16;
809 Sign_Extend(borrow, z);
810 Storeinc(xc, z, y);
811 }
812#else
813 do {
814 y = *xa++ - *xb++ + borrow;
815 borrow = y >> 16;
816 Sign_Extend(borrow, y);
817 *xc++ = y & 0xffff;
818 }
819 while(xb < xbe);
820 while(xa < xae) {
821 y = *xa++ + borrow;
822 borrow = y >> 16;
823 Sign_Extend(borrow, y);
824 *xc++ = y & 0xffff;
825 }
826#endif
827 while(!*--xc)
828 wa--;
829 c->wds = wa;
830 return c;
831 }
832
833 static double
834ulp(double _x)
835{
836 _double x;
837 Long L;
838 _double a;
839
840 value(x) = _x;
841 L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1;
842#ifndef Sudden_Underflow
843 if (L > 0) {
844#endif
845#ifdef IBM
846 L |= Exp_msk1 >> 4;
847#endif
848 word0(a) = L;
849 word1(a) = 0;
850#ifndef Sudden_Underflow
851 }
852 else {
853 L = -L >> Exp_shift;
854 if (L < Exp_shift) {
855 word0(a) = 0x80000 >> L;
856 word1(a) = 0;
857 }
858 else {
859 word0(a) = 0;
860 L -= Exp_shift;
861 word1(a) = L >= 31 ? 1 : 1 << 31 - L;
862 }
863 }
864#endif
865 return value(a);
866 }
867
868 static double
869b2d(Bigint *a, int *e)
870{
871 ULong *xa, *xa0, w, y, z;
872 int k;
873 _double d;
874#ifdef VAX
875 ULong d0, d1;
876#else
877#define d0 word0(d)
878#define d1 word1(d)
879#endif
880
881 xa0 = a->x;
882 xa = xa0 + a->wds;
883 y = *--xa;
884#ifdef DEBUG
885 if (!y) Bug("zero y in b2d");
886#endif
887 k = hi0bits(y);
888 *e = 32 - k;
889#ifdef Pack_32
890 if (k < Ebits) {
891 d0 = Exp_1 | y >> Ebits - k;
892 w = xa > xa0 ? *--xa : 0;
893 d1 = y << (32-Ebits) + k | w >> Ebits - k;
894 goto ret_d;
895 }
896 z = xa > xa0 ? *--xa : 0;
897 if (k -= Ebits) {
898 d0 = Exp_1 | y << k | z >> 32 - k;
899 y = xa > xa0 ? *--xa : 0;
900 d1 = z << k | y >> 32 - k;
901 }
902 else {
903 d0 = Exp_1 | y;
904 d1 = z;
905 }
906#else
907 if (k < Ebits + 16) {
908 z = xa > xa0 ? *--xa : 0;
909 d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
910 w = xa > xa0 ? *--xa : 0;
911 y = xa > xa0 ? *--xa : 0;
912 d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
913 goto ret_d;
914 }
915 z = xa > xa0 ? *--xa : 0;
916 w = xa > xa0 ? *--xa : 0;
917 k -= Ebits + 16;
918 d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
919 y = xa > xa0 ? *--xa : 0;
920 d1 = w << k + 16 | y << k;
921#endif
922 ret_d:
923#ifdef VAX
924 word0(d) = d0 >> 16 | d0 << 16;
925 word1(d) = d1 >> 16 | d1 << 16;
926#else
927#undef d0
928#undef d1
929#endif
930 return value(d);
931 }
932
933 static Bigint *
934d2b(double _d, int *e, int *bits)
935{
936 Bigint *b;
937 int de, i, k;
938 ULong *x, y, z;
939 _double d;
940#ifdef VAX
941 ULong d0, d1;
942#endif
943
944 value(d) = _d;
945#ifdef VAX
946 d0 = word0(d) >> 16 | word0(d) << 16;
947 d1 = word1(d) >> 16 | word1(d) << 16;
948#else
949#define d0 word0(d)
950#define d1 word1(d)
951#endif
952
953#ifdef Pack_32
954 b = Balloc(1);
955#else
956 b = Balloc(2);
957#endif
958 x = b->x;
959
960 z = d0 & Frac_mask;
961 d0 &= 0x7fffffff; /* clear sign bit, which we ignore */
962#ifdef Sudden_Underflow
963 de = (int)(d0 >> Exp_shift);
964#ifndef IBM
965 z |= Exp_msk11;
966#endif
967#else
968 if (de = (int)(d0 >> Exp_shift))
969 z |= Exp_msk1;
970#endif
971#ifdef Pack_32
972 if (y = d1) {
973 if (k = lo0bits(&y)) {
974 x[0] = y | z << 32 - k;
975 z >>= k;
976 }
977 else
978 x[0] = y;
979 i = b->wds = (x[1] = z) ? 2 : 1;
980 }
981 else {
982#ifdef DEBUG
983 if (!z)
984 Bug("Zero passed to d2b");
985#endif
986 k = lo0bits(&z);
987 x[0] = z;
988 i = b->wds = 1;
989 k += 32;
990 }
991#else
992 if (y = d1) {
993 if (k = lo0bits(&y))
994 if (k >= 16) {
995 x[0] = y | z << 32 - k & 0xffff;
996 x[1] = z >> k - 16 & 0xffff;
997 x[2] = z >> k;
998 i = 2;
999 }
1000 else {
1001 x[0] = y & 0xffff;
1002 x[1] = y >> 16 | z << 16 - k & 0xffff;
1003 x[2] = z >> k & 0xffff;
1004 x[3] = z >> k+16;
1005 i = 3;
1006 }
1007 else {
1008 x[0] = y & 0xffff;
1009 x[1] = y >> 16;
1010 x[2] = z & 0xffff;
1011 x[3] = z >> 16;
1012 i = 3;
1013 }
1014 }
1015 else {
1016#ifdef DEBUG
1017 if (!z)
1018 Bug("Zero passed to d2b");
1019#endif
1020 k = lo0bits(&z);
1021 if (k >= 16) {
1022 x[0] = z;
1023 i = 0;
1024 }
1025 else {
1026 x[0] = z & 0xffff;
1027 x[1] = z >> 16;
1028 i = 1;
1029 }
1030 k += 32;
1031 }
1032 while(!x[i])
1033 --i;
1034 b->wds = i + 1;
1035#endif
1036#ifndef Sudden_Underflow
1037 if (de) {
1038#endif
1039#ifdef IBM
1040 *e = (de - Bias - (P-1) << 2) + k;
1041 *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask);
1042#else
1043 *e = de - Bias - (P-1) + k;
1044 *bits = P - k;
1045#endif
1046#ifndef Sudden_Underflow
1047 }
1048 else {
1049 *e = de - Bias - (P-1) + 1 + k;
1050#ifdef Pack_32
1051 *bits = 32*i - hi0bits(x[i-1]);
1052#else
1053 *bits = (i+2)*16 - hi0bits(x[i]);
1054#endif
1055 }
1056#endif
1057 return b;
1058 }
1059#undef d0
1060#undef d1
1061
1062 static double
1063ratio(Bigint *a, Bigint *b)
1064{
1065 _double da, db;
1066 int k, ka, kb;
1067
1068 value(da) = b2d(a, &ka);
1069 value(db) = b2d(b, &kb);
1070#ifdef Pack_32
1071 k = ka - kb + 32*(a->wds - b->wds);
1072#else
1073 k = ka - kb + 16*(a->wds - b->wds);
1074#endif
1075#ifdef IBM
1076 if (k > 0) {
1077 word0(da) += (k >> 2)*Exp_msk1;
1078 if (k &= 3)
1079 da *= 1 << k;
1080 }
1081 else {
1082 k = -k;
1083 word0(db) += (k >> 2)*Exp_msk1;
1084 if (k &= 3)
1085 db *= 1 << k;
1086 }
1087#else
1088 if (k > 0)
1089 word0(da) += k*Exp_msk1;
1090 else {
1091 k = -k;
1092 word0(db) += k*Exp_msk1;
1093 }
1094#endif
1095 return value(da) / value(db);
1096 }
1097
1098static CONST double
1099tens[] = {
1100 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
1101 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
1102 1e20, 1e21, 1e22
1103#ifdef VAX
1104 , 1e23, 1e24
1105#endif
1106 };
1107
1108#ifdef IEEE_Arith
1109static CONST double bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
1110static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
1111#define n_bigtens 5
1112#else
1113#ifdef IBM
1114static CONST double bigtens[] = { 1e16, 1e32, 1e64 };
1115static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64 };
1116#define n_bigtens 3
1117#else
1118static CONST double bigtens[] = { 1e16, 1e32 };
1119static CONST double tinytens[] = { 1e-16, 1e-32 };
1120#define n_bigtens 2
1121#endif
1122#endif
1123
1124 double
1125strtod(CONST char *s00, char **se)
1126{
1127 int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
1128 e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
1129 CONST char *s, *s0, *s1;
1130 double aadj, aadj1, adj;
1131 _double rv, rv0;
1132 Long L;
1133 ULong y, z;
1134 Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
1135
1136 CONST char decimal_point = localeconv()->decimal_point[0];
1137
1138 sign = nz0 = nz = 0;
1139 value(rv) = 0.;
1140
1141
1142 for(s = s00; isspace((unsigned char) *s); s++)
1143 ;
1144
1145 if (*s == '-') {
1146 sign = 1;
1147 s++;
1148 } else if (*s == '+') {
1149 s++;
1150 }
1151
1152 if (*s == '\0') {
1153 s = s00;
1154 goto ret;
1155 }
1156
1157 if (*s == '0') {
1158 nz0 = 1;
1159 while(*++s == '0') ;
1160 if (!*s)
1161 goto ret;
1162 }
1163 s0 = s;
1164 y = z = 0;
1165 for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
1166 if (nd < 9)
1167 y = 10*y + c - '0';
1168 else if (nd < 16)
1169 z = 10*z + c - '0';
1170 nd0 = nd;
1171 if (c == decimal_point) {
1172 c = *++s;
1173 if (!nd) {
1174 for(; c == '0'; c = *++s)
1175 nz++;
1176 if (c > '0' && c <= '9') {
1177 s0 = s;
1178 nf += nz;
1179 nz = 0;
1180 goto have_dig;
1181 }
1182 goto dig_done;
1183 }
1184 for(; c >= '0' && c <= '9'; c = *++s) {
1185 have_dig:
1186 nz++;
1187 if (c -= '0') {
1188 nf += nz;
1189 for(i = 1; i < nz; i++)
1190 if (nd++ < 9)
1191 y *= 10;
1192 else if (nd <= DBL_DIG + 1)
1193 z *= 10;
1194 if (nd++ < 9)
1195 y = 10*y + c;
1196 else if (nd <= DBL_DIG + 1)
1197 z = 10*z + c;
1198 nz = 0;
1199 }
1200 }
1201 }
1202 dig_done:
1203 e = 0;
1204 if (c == 'e' || c == 'E') {
1205 if (!nd && !nz && !nz0) {
1206 s = s00;
1207 goto ret;
1208 }
1209 s00 = s;
1210 esign = 0;
1211 switch(c = *++s) {
1212 case '-':
1213 esign = 1;
1214 case '+':
1215 c = *++s;
1216 }
1217 if (c >= '0' && c <= '9') {
1218 while(c == '0')
1219 c = *++s;
1220 if (c > '0' && c <= '9') {
1221 L = c - '0';
1222 s1 = s;
1223 while((c = *++s) >= '0' && c <= '9')
1224 L = 10*L + c - '0';
1225 if (s - s1 > 8 || L > 19999)
1226 /* Avoid confusion from exponents
1227 * so large that e might overflow.
1228 */
1229 e = 19999; /* safe for 16 bit ints */
1230 else
1231 e = (int)L;
1232 if (esign)
1233 e = -e;
1234 }
1235 else
1236 e = 0;
1237 }
1238 else
1239 s = s00;
1240 }
1241 if (!nd) {
1242 if (!nz && !nz0)
1243 s = s00;
1244 goto ret;
1245 }
1246 e1 = e -= nf;
1247
1248 /* Now we have nd0 digits, starting at s0, followed by a
1249 * decimal point, followed by nd-nd0 digits. The number we're
1250 * after is the integer represented by those digits times
1251 * 10**e */
1252
1253 if (!nd0)
1254 nd0 = nd;
1255 k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
1256 value(rv) = y;
1257 if (k > 9)
1258 value(rv) = tens[k - 9] * value(rv) + z;
1259 bd0 = 0;
1260 if (nd <= DBL_DIG
1261#ifndef RND_PRODQUOT
1262 && FLT_ROUNDS == 1
1263#endif
1264 ) {
1265 if (!e)
1266 goto ret;
1267 if (e > 0) {
1268 if (e <= Ten_pmax) {
1269#ifdef VAX
1270 goto vax_ovfl_check;
1271#else
1272 /* value(rv) = */ rounded_product(value(rv),
1273 tens[e]);
1274 goto ret;
1275#endif
1276 }
1277 i = DBL_DIG - nd;
1278 if (e <= Ten_pmax + i) {
1279 /* A fancier test would sometimes let us do
1280 * this for larger i values.
1281 */
1282 e -= i;
1283 value(rv) *= tens[i];
1284#ifdef VAX
1285 /* VAX exponent range is so narrow we must
1286 * worry about overflow here...
1287 */
1288 vax_ovfl_check:
1289 word0(rv) -= P*Exp_msk1;
1290 /* value(rv) = */ rounded_product(value(rv),
1291 tens[e]);
1292 if ((word0(rv) & Exp_mask)
1293 > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
1294 goto ovfl;
1295 word0(rv) += P*Exp_msk1;
1296#else
1297 /* value(rv) = */ rounded_product(value(rv),
1298 tens[e]);
1299#endif
1300 goto ret;
1301 }
1302 }
1303#ifndef Inaccurate_Divide
1304 else if (e >= -Ten_pmax) {
1305 /* value(rv) = */ rounded_quotient(value(rv),
1306 tens[-e]);
1307 goto ret;
1308 }
1309#endif
1310 }
1311 e1 += nd - k;
1312
1313 /* Get starting approximation = rv * 10**e1 */
1314
1315 if (e1 > 0) {
1316 if (i = e1 & 15)
1317 value(rv) *= tens[i];
1318 if (e1 &= ~15) {
1319 if (e1 > DBL_MAX_10_EXP) {
1320 ovfl:
1321 errno = ERANGE;
1322#ifndef Bad_float_h
1323 value(rv) = HUGE_VAL;
1324#else
1325 /* Can't trust HUGE_VAL */
1326#ifdef IEEE_Arith
1327 word0(rv) = Exp_mask;
1328 word1(rv) = 0;
1329#else
1330 word0(rv) = Big0;
1331 word1(rv) = Big1;
1332#endif
1333#endif
1334 if (bd0)
1335 goto retfree;
1336 goto ret;
1337 }
1338 if (e1 >>= 4) {
1339 for(j = 0; e1 > 1; j++, e1 >>= 1)
1340 if (e1 & 1)
1341 value(rv) *= bigtens[j];
1342 /* The last multiplication could overflow. */
1343 word0(rv) -= P*Exp_msk1;
1344 value(rv) *= bigtens[j];
1345 if ((z = word0(rv) & Exp_mask)
1346 > Exp_msk1*(DBL_MAX_EXP+Bias-P))
1347 goto ovfl;
1348 if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {
1349 /* set to largest number */
1350 /* (Can't trust DBL_MAX) */
1351 word0(rv) = Big0;
1352 word1(rv) = Big1;
1353 }
1354 else
1355 word0(rv) += P*Exp_msk1;
1356 }
1357
1358 }
1359 }
1360 else if (e1 < 0) {
1361 e1 = -e1;
1362 if (i = e1 & 15)
1363 value(rv) /= tens[i];
1364 if (e1 &= ~15) {
1365 e1 >>= 4;
1366 if (e1 >= 1 << n_bigtens)
1367 goto undfl;
1368 for(j = 0; e1 > 1; j++, e1 >>= 1)
1369 if (e1 & 1)
1370 value(rv) *= tinytens[j];
1371 /* The last multiplication could underflow. */
1372 value(rv0) = value(rv);
1373 value(rv) *= tinytens[j];
1374 if (!value(rv)) {
1375 value(rv) = 2.*value(rv0);
1376 value(rv) *= tinytens[j];
1377 if (!value(rv)) {
1378 undfl:
1379 value(rv) = 0.;
1380 errno = ERANGE;
1381 if (bd0)
1382 goto retfree;
1383 goto ret;
1384 }
1385 word0(rv) = Tiny0;
1386 word1(rv) = Tiny1;
1387 /* The refinement below will clean
1388 * this approximation up.
1389 */
1390 }
1391 }
1392 }
1393
1394 /* Now the hard part -- adjusting rv to the correct value.*/
1395
1396 /* Put digits into bd: true value = bd * 10^e */
1397
1398 bd0 = s2b(s0, nd0, nd, y);
1399
1400 for(;;) {
1401 bd = Balloc(bd0->k);
1402 Bcopy(bd, bd0);
1403 bb = d2b(value(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */
1404 bs = i2b(1);
1405
1406 if (e >= 0) {
1407 bb2 = bb5 = 0;
1408 bd2 = bd5 = e;
1409 }
1410 else {
1411 bb2 = bb5 = -e;
1412 bd2 = bd5 = 0;
1413 }
1414 if (bbe >= 0)
1415 bb2 += bbe;
1416 else
1417 bd2 -= bbe;
1418 bs2 = bb2;
1419#ifdef Sudden_Underflow
1420#ifdef IBM
1421 j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3);
1422#else
1423 j = P + 1 - bbbits;
1424#endif
1425#else
1426 i = bbe + bbbits - 1; /* logb(rv) */
1427 if (i < Emin) /* denormal */
1428 j = bbe + (P-Emin);
1429 else
1430 j = P + 1 - bbbits;
1431#endif
1432 bb2 += j;
1433 bd2 += j;
1434 i = bb2 < bd2 ? bb2 : bd2;
1435 if (i > bs2)
1436 i = bs2;
1437 if (i > 0) {
1438 bb2 -= i;
1439 bd2 -= i;
1440 bs2 -= i;
1441 }
1442 if (bb5 > 0) {
1443 bs = pow5mult(bs, bb5);
1444 bb1 = mult(bs, bb);
1445 Bfree(bb);
1446 bb = bb1;
1447 }
1448 if (bb2 > 0)
1449 bb = lshift(bb, bb2);
1450 if (bd5 > 0)
1451 bd = pow5mult(bd, bd5);
1452 if (bd2 > 0)
1453 bd = lshift(bd, bd2);
1454 if (bs2 > 0)
1455 bs = lshift(bs, bs2);
1456 delta = diff(bb, bd);
1457 dsign = delta->sign;
1458 delta->sign = 0;
1459 i = cmp(delta, bs);
1460 if (i < 0) {
1461 /* Error is less than half an ulp -- check for
1462 * special case of mantissa a power of two.
1463 */
1464 if (dsign || word1(rv) || word0(rv) & Bndry_mask)
1465 break;
1466 delta = lshift(delta,Log2P);
1467 if (cmp(delta, bs) > 0)
1468 goto drop_down;
1469 break;
1470 }
1471 if (i == 0) {
1472 /* exactly half-way between */
1473 if (dsign) {
1474 if ((word0(rv) & Bndry_mask1) == Bndry_mask1
1475 && word1(rv) == 0xffffffff) {
1476 /*boundary case -- increment exponent*/
1477 word0(rv) = (word0(rv) & Exp_mask)
1478 + Exp_msk1
1479#ifdef IBM
1480 | Exp_msk1 >> 4
1481#endif
1482 ;
1483 word1(rv) = 0;
1484 break;
1485 }
1486 }
1487 else if (!(word0(rv) & Bndry_mask) && !word1(rv)) {
1488 drop_down:
1489 /* boundary case -- decrement exponent */
1490#ifdef Sudden_Underflow
1491 L = word0(rv) & Exp_mask;
1492#ifdef IBM
1493 if (L < Exp_msk1)
1494#else
1495 if (L <= Exp_msk1)
1496#endif
1497 goto undfl;
1498 L -= Exp_msk1;
1499#else
1500 L = (word0(rv) & Exp_mask) - Exp_msk1;
1501#endif
1502 word0(rv) = L | Bndry_mask1;
1503 word1(rv) = 0xffffffff;
1504#ifdef IBM
1505 goto cont;
1506#else
1507 break;
1508#endif
1509 }
1510#ifndef ROUND_BIASED
1511 if (!(word1(rv) & LSB))
1512 break;
1513#endif
1514 if (dsign)
1515 value(rv) += ulp(value(rv));
1516#ifndef ROUND_BIASED
1517 else {
1518 value(rv) -= ulp(value(rv));
1519#ifndef Sudden_Underflow
1520 if (!value(rv))
1521 goto undfl;
1522#endif
1523 }
1524#endif
1525 break;
1526 }
1527 if ((aadj = ratio(delta, bs)) <= 2.) {
1528 if (dsign)
1529 aadj = aadj1 = 1.;
1530 else if (word1(rv) || word0(rv) & Bndry_mask) {
1531#ifndef Sudden_Underflow
1532 if (word1(rv) == Tiny1 && !word0(rv))
1533 goto undfl;
1534#endif
1535 aadj = 1.;
1536 aadj1 = -1.;
1537 }
1538 else {
1539 /* special case -- power of FLT_RADIX to be */
1540 /* rounded down... */
1541
1542 if (aadj < 2./FLT_RADIX)
1543 aadj = 1./FLT_RADIX;
1544 else
1545 aadj *= 0.5;
1546 aadj1 = -aadj;
1547 }
1548 }
1549 else {
1550 aadj *= 0.5;
1551 aadj1 = dsign ? aadj : -aadj;
1552#ifdef Check_FLT_ROUNDS
1553 switch(FLT_ROUNDS) {
1554 case 2: /* towards +infinity */
1555 aadj1 -= 0.5;
1556 break;
1557 case 0: /* towards 0 */
1558 case 3: /* towards -infinity */
1559 aadj1 += 0.5;
1560 }
1561#else
1562 if (FLT_ROUNDS == 0)
1563 aadj1 += 0.5;
1564#endif
1565 }
1566 y = word0(rv) & Exp_mask;
1567
1568 /* Check for overflow */
1569
1570 if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
1571 value(rv0) = value(rv);
1572 word0(rv) -= P*Exp_msk1;
1573 adj = aadj1 * ulp(value(rv));
1574 value(rv) += adj;
1575 if ((word0(rv) & Exp_mask) >=
1576 Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
1577 if (word0(rv0) == Big0 && word1(rv0) == Big1)
1578 goto ovfl;
1579 word0(rv) = Big0;
1580 word1(rv) = Big1;
1581 goto cont;
1582 }
1583 else
1584 word0(rv) += P*Exp_msk1;
1585 }
1586 else {
1587#ifdef Sudden_Underflow
1588 if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
1589 value(rv0) = value(rv);
1590 word0(rv) += P*Exp_msk1;
1591 adj = aadj1 * ulp(value(rv));
1592 value(rv) += adj;
1593#ifdef IBM
1594 if ((word0(rv) & Exp_mask) < P*Exp_msk1)
1595#else
1596 if ((word0(rv) & Exp_mask) <= P*Exp_msk1)
1597#endif
1598 {
1599 if (word0(rv0) == Tiny0
1600 && word1(rv0) == Tiny1)
1601 goto undfl;
1602 word0(rv) = Tiny0;
1603 word1(rv) = Tiny1;
1604 goto cont;
1605 }
1606 else
1607 word0(rv) -= P*Exp_msk1;
1608 }
1609 else {
1610 adj = aadj1 * ulp(value(rv));
1611 value(rv) += adj;
1612 }
1613#else
1614 /* Compute adj so that the IEEE rounding rules will
1615 * correctly round rv + adj in some half-way cases.
1616 * If rv * ulp(rv) is denormalized (i.e.,
1617 * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid
1618 * trouble from bits lost to denormalization;
1619 * example: 1.2e-307 .
1620 */
1621 if (y <= (P-1)*Exp_msk1 && aadj >= 1.) {
1622 aadj1 = (double)(int)(aadj + 0.5);
1623 if (!dsign)
1624 aadj1 = -aadj1;
1625 }
1626 adj = aadj1 * ulp(value(rv));
1627 value(rv) += adj;
1628#endif
1629 }
1630 z = word0(rv) & Exp_mask;
1631 if (y == z) {
1632 /* Can we stop now? */
1633 L = aadj;
1634 aadj -= L;
1635 /* The tolerances below are conservative. */
1636 if (dsign || word1(rv) || word0(rv) & Bndry_mask) {
1637 if (aadj < .4999999 || aadj > .5000001)
1638 break;
1639 }
1640 else if (aadj < .4999999/FLT_RADIX)
1641 break;
1642 }
1643 cont:
1644 Bfree(bb);
1645 Bfree(bd);
1646 Bfree(bs);
1647 Bfree(delta);
1648 }
1649 retfree:
1650 Bfree(bb);
1651 Bfree(bd);
1652 Bfree(bs);
1653 Bfree(bd0);
1654 Bfree(delta);
1655 ret:
1656 if (se)
1657 *se = (char *)s;
1658 return sign ? -value(rv) : value(rv);
1659 }
1660
1661 static int
1662quorem(Bigint *b, Bigint *S)
1663{
1664 int n;
1665 Long borrow, y;
1666 ULong carry, q, ys;
1667 ULong *bx, *bxe, *sx, *sxe;
1668#ifdef Pack_32
1669 Long z;
1670 ULong si, zs;
1671#endif
1672
1673 n = S->wds;
1674#ifdef DEBUG
1675 /*debug*/ if (b->wds > n)
1676 /*debug*/ Bug("oversize b in quorem");
1677#endif
1678 if (b->wds < n)
1679 return 0;
1680 sx = S->x;
1681 sxe = sx + --n;
1682 bx = b->x;
1683 bxe = bx + n;
1684 q = *bxe / (*sxe + 1); /* ensure q <= true quotient */
1685#ifdef DEBUG
1686 /*debug*/ if (q > 9)
1687 /*debug*/ Bug("oversized quotient in quorem");
1688#endif
1689 if (q) {
1690 borrow = 0;
1691 carry = 0;
1692 do {
1693#ifdef Pack_32
1694 si = *sx++;
1695 ys = (si & 0xffff) * q + carry;
1696 zs = (si >> 16) * q + (ys >> 16);
1697 carry = zs >> 16;
1698 y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
1699 borrow = y >> 16;
1700 Sign_Extend(borrow, y);
1701 z = (*bx >> 16) - (zs & 0xffff) + borrow;
1702 borrow = z >> 16;
1703 Sign_Extend(borrow, z);
1704 Storeinc(bx, z, y);
1705#else
1706 ys = *sx++ * q + carry;
1707 carry = ys >> 16;
1708 y = *bx - (ys & 0xffff) + borrow;
1709 borrow = y >> 16;
1710 Sign_Extend(borrow, y);
1711 *bx++ = y & 0xffff;
1712#endif
1713 }
1714 while(sx <= sxe);
1715 if (!*bxe) {
1716 bx = b->x;
1717 while(--bxe > bx && !*bxe)
1718 --n;
1719 b->wds = n;
1720 }
1721 }
1722 if (cmp(b, S) >= 0) {
1723 q++;
1724 borrow = 0;
1725 carry = 0;
1726 bx = b->x;
1727 sx = S->x;
1728 do {
1729#ifdef Pack_32
1730 si = *sx++;
1731 ys = (si & 0xffff) + carry;
1732 zs = (si >> 16) + (ys >> 16);
1733 carry = zs >> 16;
1734 y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
1735 borrow = y >> 16;
1736 Sign_Extend(borrow, y);
1737 z = (*bx >> 16) - (zs & 0xffff) + borrow;
1738 borrow = z >> 16;
1739 Sign_Extend(borrow, z);
1740 Storeinc(bx, z, y);
1741#else
1742 ys = *sx++ + carry;
1743 carry = ys >> 16;
1744 y = *bx - (ys & 0xffff) + borrow;
1745 borrow = y >> 16;
1746 Sign_Extend(borrow, y);
1747 *bx++ = y & 0xffff;
1748#endif
1749 }
1750 while(sx <= sxe);
1751 bx = b->x;
1752 bxe = bx + n;
1753 if (!*bxe) {
1754 while(--bxe > bx && !*bxe)
1755 --n;
1756 b->wds = n;
1757 }
1758 }
1759 return q;
1760 }
1761
1762/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
1763 *
1764 * Inspired by "How to Print Floating-Point Numbers Accurately" by
1765 * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101].
1766 *
1767 * Modifications:
1768 * 1. Rather than iterating, we use a simple numeric overestimate
1769 * to determine k = floor(log10(d)). We scale relevant
1770 * quantities using O(log2(k)) rather than O(k) multiplications.
1771 * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
1772 * try to generate digits strictly left to right. Instead, we
1773 * compute with fewer bits and propagate the carry if necessary
1774 * when rounding the final digit up. This is often faster.
1775 * 3. Under the assumption that input will be rounded nearest,
1776 * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
1777 * That is, we allow equality in stopping tests when the
1778 * round-nearest rule will give the same floating-point value
1779 * as would satisfaction of the stopping test with strict
1780 * inequality.
1781 * 4. We remove common factors of powers of 2 from relevant
1782 * quantities.
1783 * 5. When converting floating-point integers less than 1e16,
1784 * we use floating-point arithmetic rather than resorting
1785 * to multiple-precision integers.
1786 * 6. When asked to produce fewer than 15 digits, we first try
1787 * to get by with floating-point arithmetic; we resort to
1788 * multiple-precision integer arithmetic only if we cannot
1789 * guarantee that the floating-point calculation has given
1790 * the correctly rounded result. For k requested digits and
1791 * "uniformly" distributed input, the probability is
1792 * something like 10^(k-15) that we must resort to the Long
1793 * calculation.
1794 */
1795
1796 char *
1797__dtoa(double _d, int mode, int ndigits, int *decpt, int *sign, char **rve)
1798{
1799 /* Arguments ndigits, decpt, sign are similar to those
1800 of ecvt and fcvt; trailing zeros are suppressed from
1801 the returned string. If not null, *rve is set to point
1802 to the end of the return value. If d is +-Infinity or NaN,
1803 then *decpt is set to 9999.
1804
1805 mode:
1806 0 ==> shortest string that yields d when read in
1807 and rounded to nearest.
1808 1 ==> like 0, but with Steele & White stopping rule;
1809 e.g. with IEEE P754 arithmetic , mode 0 gives
1810 1e23 whereas mode 1 gives 9.999999999999999e22.
1811 2 ==> max(1,ndigits) significant digits. This gives a
1812 return value similar to that of ecvt, except
1813 that trailing zeros are suppressed.
1814 3 ==> through ndigits past the decimal point. This
1815 gives a return value similar to that from fcvt,
1816 except that trailing zeros are suppressed, and
1817 ndigits can be negative.
1818 4-9 should give the same return values as 2-3, i.e.,
1819 4 <= mode <= 9 ==> same return as mode
1820 2 + (mode & 1). These modes are mainly for
1821 debugging; often they run slower but sometimes
1822 faster than modes 2-3.
1823 4,5,8,9 ==> left-to-right digit generation.
1824 6-9 ==> don't try fast floating-point estimate
1825 (if applicable).
1826
1827 Values of mode other than 0-9 are treated as mode 0.
1828
1829 Sufficient space is allocated to the return value
1830 to hold the suppressed trailing zeros.
1831 */
1832
1833 int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1,
1834 j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
1835 spec_case, try_quick;
1836 Long L;
1837#ifndef Sudden_Underflow
1838 int denorm;
1839 ULong x;
1840#endif
1841 Bigint *b, *b1, *delta, *mlo, *mhi, *S;
1842 double ds;
1843 char *s, *s0;
1844 static Bigint *result;
1845 static int result_k;
1846 _double d, d2, eps;
1847
1848 value(d) = _d;
1849 if (result) {
1850 result->k = result_k;
1851 result->maxwds = 1 << result_k;
1852 Bfree(result);
1853 result = 0;
1854 }
1855
1856 if (word0(d) & Sign_bit) {
1857 /* set sign for everything, including 0's and NaNs */
1858 *sign = 1;
1859 word0(d) &= ~Sign_bit; /* clear sign bit */
1860 }
1861 else
1862 *sign = 0;
1863
1864#if defined(IEEE_Arith) + defined(VAX)
1865#ifdef IEEE_Arith
1866 if ((word0(d) & Exp_mask) == Exp_mask)
1867#else
1868 if (word0(d) == 0x8000)
1869#endif
1870 {
1871 /* Infinity or NaN */
1872 *decpt = 9999;
1873 s =
1874#ifdef IEEE_Arith
1875 !word1(d) && !(word0(d) & 0xfffff) ? ndigits < 8 ? "Inf" : "Infinity" :
1876#endif
1877 "NaN";
1878 if (rve)
1879 *rve =
1880#ifdef IEEE_Arith
1881 s[3] ? s + 8 :
1882#endif
1883 s + 3;
1884 return s;
1885 }
1886#endif
1887#ifdef IBM
1888 value(d) += 0; /* normalize */
1889#endif
1890 if (!value(d)) {
1891 *decpt = 1;
1892 s = "0";
1893 if (rve)
1894 *rve = s + 1;
1895 return s;
1896 }
1897
1898 b = d2b(value(d), &be, &bbits);
1899#ifdef Sudden_Underflow
1900 i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
1901#else
1902 if (i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) {
1903#endif
1904 value(d2) = value(d);
1905 word0(d2) &= Frac_mask1;
1906 word0(d2) |= Exp_11;
1907#ifdef IBM
1908 if (j = 11 - hi0bits(word0(d2) & Frac_mask))
1909 value(d2) /= 1 << j;
1910#endif
1911
1912 /* log(x) ~=~ log(1.5) + (x-1.5)/1.5
1913 * log10(x) = log(x) / log(10)
1914 * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
1915 * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
1916 *
1917 * This suggests computing an approximation k to log10(d) by
1918 *
1919 * k = (i - Bias)*0.301029995663981
1920 * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
1921 *
1922 * We want k to be too large rather than too small.
1923 * The error in the first-order Taylor series approximation
1924 * is in our favor, so we just round up the constant enough
1925 * to compensate for any error in the multiplication of
1926 * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
1927 * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
1928 * adding 1e-13 to the constant term more than suffices.
1929 * Hence we adjust the constant term to 0.1760912590558.
1930 * (We could get a more accurate k by invoking log10,
1931 * but this is probably not worthwhile.)
1932 */
1933
1934 i -= Bias;
1935#ifdef IBM
1936 i <<= 2;
1937 i += j;
1938#endif
1939#ifndef Sudden_Underflow
1940 denorm = 0;
1941 }
1942 else {
1943 /* d is denormalized */
1944
1945 i = bbits + be + (Bias + (P-1) - 1);
1946 x = i > 32 ? word0(d) << 64 - i | word1(d) >> i - 32
1947 : word1(d) << 32 - i;
1948 value(d2) = x;
1949 word0(d2) -= 31*Exp_msk1; /* adjust exponent */
1950 i -= (Bias + (P-1) - 1) + 1;
1951 denorm = 1;
1952 }
1953#endif
1954 ds = (value(d2)-1.5)*0.289529654602168 + 0.1760912590558 +
1955 i*0.301029995663981;
1956 k = (int)ds;
1957 if (ds < 0. && ds != k)
1958 k--; /* want k = floor(ds) */
1959 k_check = 1;
1960 if (k >= 0 && k <= Ten_pmax) {
1961 if (value(d) < tens[k])
1962 k--;
1963 k_check = 0;
1964 }
1965 j = bbits - i - 1;
1966 if (j >= 0) {
1967 b2 = 0;
1968 s2 = j;
1969 }
1970 else {
1971 b2 = -j;
1972 s2 = 0;
1973 }
1974 if (k >= 0) {
1975 b5 = 0;
1976 s5 = k;
1977 s2 += k;
1978 }
1979 else {
1980 b2 -= k;
1981 b5 = -k;
1982 s5 = 0;
1983 }
1984 if (mode < 0 || mode > 9)
1985 mode = 0;
1986 try_quick = 1;
1987 if (mode > 5) {
1988 mode -= 4;
1989 try_quick = 0;
1990 }
1991 leftright = 1;
1992 switch(mode) {
1993 case 0:
1994 case 1:
1995 ilim = ilim1 = -1;
1996 i = 18;
1997 ndigits = 0;
1998 break;
1999 case 2:
2000 leftright = 0;
2001 /* no break */
2002 case 4:
2003 if (ndigits <= 0)
2004 ndigits = 1;
2005 ilim = ilim1 = i = ndigits;
2006 break;
2007 case 3:
2008 leftright = 0;
2009 /* no break */
2010 case 5:
2011 i = ndigits + k + 1;
2012 ilim = i;
2013 ilim1 = i - 1;
2014 if (i <= 0)
2015 i = 1;
2016 }
2017 j = sizeof(ULong);
2018 for(result_k = 0; sizeof(Bigint) - sizeof(ULong) + j <= i;
2019 j <<= 1) result_k++;
2020 result = Balloc(result_k);
2021 s = s0 = (char *)result;
2022
2023 if (ilim >= 0 && ilim <= Quick_max && try_quick) {
2024
2025 /* Try to get by with floating-point arithmetic. */
2026
2027 i = 0;
2028 value(d2) = value(d);
2029 k0 = k;
2030 ilim0 = ilim;
2031 ieps = 2; /* conservative */
2032 if (k > 0) {
2033 ds = tens[k&0xf];
2034 j = k >> 4;
2035 if (j & Bletch) {
2036 /* prevent overflows */
2037 j &= Bletch - 1;
2038 value(d) /= bigtens[n_bigtens-1];
2039 ieps++;
2040 }
2041 for(; j; j >>= 1, i++)
2042 if (j & 1) {
2043 ieps++;
2044 ds *= bigtens[i];
2045 }
2046 value(d) /= ds;
2047 }
2048 else if (j1 = -k) {
2049 value(d) *= tens[j1 & 0xf];
2050 for(j = j1 >> 4; j; j >>= 1, i++)
2051 if (j & 1) {
2052 ieps++;
2053 value(d) *= bigtens[i];
2054 }
2055 }
2056 if (k_check && value(d) < 1. && ilim > 0) {
2057 if (ilim1 <= 0)
2058 goto fast_failed;
2059 ilim = ilim1;
2060 k--;
2061 value(d) *= 10.;
2062 ieps++;
2063 }
2064 value(eps) = ieps*value(d) + 7.;
2065 word0(eps) -= (P-1)*Exp_msk1;
2066 if (ilim == 0) {
2067 S = mhi = 0;
2068 value(d) -= 5.;
2069 if (value(d) > value(eps))
2070 goto one_digit;
2071 if (value(d) < -value(eps))
2072 goto no_digits;
2073 goto fast_failed;
2074 }
2075#ifndef No_leftright
2076 if (leftright) {
2077 /* Use Steele & White method of only
2078 * generating digits needed.
2079 */
2080 value(eps) = 0.5/tens[ilim-1] - value(eps);
2081 for(i = 0;;) {
2082 L = value(d);
2083 value(d) -= L;
2084 *s++ = '0' + (int)L;
2085 if (value(d) < value(eps))
2086 goto ret1;
2087 if (1. - value(d) < value(eps))
2088 goto bump_up;
2089 if (++i >= ilim)
2090 break;
2091 value(eps) *= 10.;
2092 value(d) *= 10.;
2093 }
2094 }
2095 else {
2096#endif
2097 /* Generate ilim digits, then fix them up. */
2098 value(eps) *= tens[ilim-1];
2099 for(i = 1;; i++, value(d) *= 10.) {
2100 L = value(d);
2101 value(d) -= L;
2102 *s++ = '0' + (int)L;
2103 if (i == ilim) {
2104 if (value(d) > 0.5 + value(eps))
2105 goto bump_up;
2106 else if (value(d) < 0.5 - value(eps)) {
2107 while(*--s == '0');
2108 s++;
2109 goto ret1;
2110 }
2111 break;
2112 }
2113 }
2114#ifndef No_leftright
2115 }
2116#endif
2117 fast_failed:
2118 s = s0;
2119 value(d) = value(d2);
2120 k = k0;
2121 ilim = ilim0;
2122 }
2123
2124 /* Do we have a "small" integer? */
2125
2126 if (be >= 0 && k <= Int_max) {
2127 /* Yes. */
2128 ds = tens[k];
2129 if (ndigits < 0 && ilim <= 0) {
2130 S = mhi = 0;
2131 if (ilim < 0 || value(d) <= 5*ds)
2132 goto no_digits;
2133 goto one_digit;
2134 }
2135 for(i = 1;; i++) {
2136 L = value(d) / ds;
2137 value(d) -= L*ds;
2138#ifdef Check_FLT_ROUNDS
2139 /* If FLT_ROUNDS == 2, L will usually be high by 1 */
2140 if (value(d) < 0) {
2141 L--;
2142 value(d) += ds;
2143 }
2144#endif
2145 *s++ = '0' + (int)L;
2146 if (i == ilim) {
2147 value(d) += value(d);
2148 if (value(d) > ds || value(d) == ds && L & 1) {
2149 bump_up:
2150 while(*--s == '9')
2151 if (s == s0) {
2152 k++;
2153 *s = '0';
2154 break;
2155 }
2156 ++*s++;
2157 }
2158 break;
2159 }
2160 if (!(value(d) *= 10.))
2161 break;
2162 }
2163 goto ret1;
2164 }
2165
2166 m2 = b2;
2167 m5 = b5;
2168 mhi = mlo = 0;
2169 if (leftright) {
2170 if (mode < 2) {
2171 i =
2172#ifndef Sudden_Underflow
2173 denorm ? be + (Bias + (P-1) - 1 + 1) :
2174#endif
2175#ifdef IBM
2176 1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3);
2177#else
2178 1 + P - bbits;
2179#endif
2180 }
2181 else {
2182 j = ilim - 1;
2183 if (m5 >= j)
2184 m5 -= j;
2185 else {
2186 s5 += j -= m5;
2187 b5 += j;
2188 m5 = 0;
2189 }
2190 if ((i = ilim) < 0) {
2191 m2 -= i;
2192 i = 0;
2193 }
2194 }
2195 b2 += i;
2196 s2 += i;
2197 mhi = i2b(1);
2198 }
2199 if (m2 > 0 && s2 > 0) {
2200 i = m2 < s2 ? m2 : s2;
2201 b2 -= i;
2202 m2 -= i;
2203 s2 -= i;
2204 }
2205 if (b5 > 0) {
2206 if (leftright) {
2207 if (m5 > 0) {
2208 mhi = pow5mult(mhi, m5);
2209 b1 = mult(mhi, b);
2210 Bfree(b);
2211 b = b1;
2212 }
2213 if (j = b5 - m5)
2214 b = pow5mult(b, j);
2215 }
2216 else
2217 b = pow5mult(b, b5);
2218 }
2219 S = i2b(1);
2220 if (s5 > 0)
2221 S = pow5mult(S, s5);
2222
2223 /* Check for special case that d is a normalized power of 2. */
2224
2225 if (mode < 2) {
2226 if (!word1(d) && !(word0(d) & Bndry_mask)
2227#ifndef Sudden_Underflow
2228 && word0(d) & Exp_mask
2229#endif
2230 ) {
2231 /* The special case */
2232 b2 += Log2P;
2233 s2 += Log2P;
2234 spec_case = 1;
2235 }
2236 else
2237 spec_case = 0;
2238 }
2239
2240 /* Arrange for convenient computation of quotients:
2241 * shift left if necessary so divisor has 4 leading 0 bits.
2242 *
2243 * Perhaps we should just compute leading 28 bits of S once
2244 * and for all and pass them and a shift to quorem, so it
2245 * can do shifts and ors to compute the numerator for q.
2246 */
2247#ifdef Pack_32
2248 if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f)
2249 i = 32 - i;
2250#else
2251 if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf)
2252 i = 16 - i;
2253#endif
2254 if (i > 4) {
2255 i -= 4;
2256 b2 += i;
2257 m2 += i;
2258 s2 += i;
2259 }
2260 else if (i < 4) {
2261 i += 28;
2262 b2 += i;
2263 m2 += i;
2264 s2 += i;
2265 }
2266 if (b2 > 0)
2267 b = lshift(b, b2);
2268 if (s2 > 0)
2269 S = lshift(S, s2);
2270 if (k_check) {
2271 if (cmp(b,S) < 0) {
2272 k--;
2273 b = multadd(b, 10, 0); /* we botched the k estimate */
2274 if (leftright)
2275 mhi = multadd(mhi, 10, 0);
2276 ilim = ilim1;
2277 }
2278 }
2279 if (ilim <= 0 && mode > 2) {
2280 if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) {
2281 /* no digits, fcvt style */
2282 no_digits:
2283 k = -1 - ndigits;
2284 goto ret;
2285 }
2286 one_digit:
2287 *s++ = '1';
2288 k++;
2289 goto ret;
2290 }
2291 if (leftright) {
2292 if (m2 > 0)
2293 mhi = lshift(mhi, m2);
2294
2295 /* Compute mlo -- check for special case
2296 * that d is a normalized power of 2.
2297 */
2298
2299 mlo = mhi;
2300 if (spec_case) {
2301 mhi = Balloc(mhi->k);
2302 Bcopy(mhi, mlo);
2303 mhi = lshift(mhi, Log2P);
2304 }
2305
2306 for(i = 1;;i++) {
2307 dig = quorem(b,S) + '0';
2308 /* Do we yet have the shortest decimal string
2309 * that will round to d?
2310 */
2311 j = cmp(b, mlo);
2312 delta = diff(S, mhi);
2313 j1 = delta->sign ? 1 : cmp(b, delta);
2314 Bfree(delta);
2315#ifndef ROUND_BIASED
2316 if (j1 == 0 && !mode && !(word1(d) & 1)) {
2317 if (dig == '9')
2318 goto round_9_up;
2319 if (j > 0)
2320 dig++;
2321 *s++ = dig;
2322 goto ret;
2323 }
2324#endif
2325 if (j < 0 || j == 0 && !mode
2326#ifndef ROUND_BIASED
2327 && !(word1(d) & 1)
2328#endif
2329 ) {
2330 if (j1 > 0) {
2331 b = lshift(b, 1);
2332 j1 = cmp(b, S);
2333 if ((j1 > 0 || j1 == 0 && dig & 1)
2334 && dig++ == '9')
2335 goto round_9_up;
2336 }
2337 *s++ = dig;
2338 goto ret;
2339 }
2340 if (j1 > 0) {
2341 if (dig == '9') { /* possible if i == 1 */
2342 round_9_up:
2343 *s++ = '9';
2344 goto roundoff;
2345 }
2346 *s++ = dig + 1;
2347 goto ret;
2348 }
2349 *s++ = dig;
2350 if (i == ilim)
2351 break;
2352 b = multadd(b, 10, 0);
2353 if (mlo == mhi)
2354 mlo = mhi = multadd(mhi, 10, 0);
2355 else {
2356 mlo = multadd(mlo, 10, 0);
2357 mhi = multadd(mhi, 10, 0);
2358 }
2359 }
2360 }
2361 else
2362 for(i = 1;; i++) {
2363 *s++ = dig = quorem(b,S) + '0';
2364 if (i >= ilim)
2365 break;
2366 b = multadd(b, 10, 0);
2367 }
2368
2369 /* Round off last digit */
2370
2371 b = lshift(b, 1);
2372 j = cmp(b, S);
2373 if (j > 0 || j == 0 && dig & 1) {
2374 roundoff:
2375 while(*--s == '9')
2376 if (s == s0) {
2377 k++;
2378 *s++ = '1';
2379 goto ret;
2380 }
2381 ++*s++;
2382 }
2383 else {
2384 while(*--s == '0');
2385 s++;
2386 }
2387 ret:
2388 Bfree(S);
2389 if (mhi) {
2390 if (mlo && mlo != mhi)
2391 Bfree(mlo);
2392 Bfree(mhi);
2393 }
2394 ret1:
2395 Bfree(b);
2396 if (s == s0) { /* don't return empty string */
2397 *s++ = '0';
2398 k = 0;
2399 }
2400 *s = 0;
2401 *decpt = k + 1;
2402 if (rve)
2403 *rve = s;
2404 return s0;
2405 }
2406#ifdef __cplusplus
2407}
2408#endif
diff --git a/src/lib/libc/stdlib/strtoimax.c b/src/lib/libc/stdlib/strtoimax.c
new file mode 100644
index 0000000000..2c77f41650
--- /dev/null
+++ b/src/lib/libc/stdlib/strtoimax.c
@@ -0,0 +1,140 @@
1/* $OpenBSD: strtoimax.c,v 1.1 2006/01/13 17:58:09 millert Exp $ */
2
3/*-
4 * Copyright (c) 1992 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. 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#include <ctype.h>
33#include <errno.h>
34#include <inttypes.h>
35
36/*
37 * Convert a string to an intmax_t
38 *
39 * Ignores `locale' stuff. Assumes that the upper and lower case
40 * alphabets and digits are each contiguous.
41 */
42intmax_t
43strtoimax(const char *nptr, char **endptr, int base)
44{
45 const char *s;
46 intmax_t acc, cutoff;
47 int c;
48 int neg, any, cutlim;
49
50 /*
51 * Skip white space and pick up leading +/- sign if any.
52 * If base is 0, allow 0x for hex and 0 for octal, else
53 * assume decimal; if base is already 16, allow 0x.
54 */
55 s = nptr;
56 do {
57 c = (unsigned char) *s++;
58 } while (isspace(c));
59 if (c == '-') {
60 neg = 1;
61 c = *s++;
62 } else {
63 neg = 0;
64 if (c == '+')
65 c = *s++;
66 }
67 if ((base == 0 || base == 16) &&
68 c == '0' && (*s == 'x' || *s == 'X')) {
69 c = s[1];
70 s += 2;
71 base = 16;
72 }
73 if (base == 0)
74 base = c == '0' ? 8 : 10;
75
76 /*
77 * Compute the cutoff value between legal numbers and illegal
78 * numbers. That is the largest legal value, divided by the
79 * base. An input number that is greater than this value, if
80 * followed by a legal input character, is too big. One that
81 * is equal to this value may be valid or not; the limit
82 * between valid and invalid numbers is then based on the last
83 * digit. For instance, if the range for intmax_t is
84 * [-9223372036854775808..9223372036854775807] and the input base
85 * is 10, cutoff will be set to 922337203685477580 and cutlim to
86 * either 7 (neg==0) or 8 (neg==1), meaning that if we have
87 * accumulated a value > 922337203685477580, or equal but the
88 * next digit is > 7 (or 8), the number is too big, and we will
89 * return a range error.
90 *
91 * Set any if any `digits' consumed; make it negative to indicate
92 * overflow.
93 */
94 cutoff = neg ? INTMAX_MIN : INTMAX_MAX;
95 cutlim = cutoff % base;
96 cutoff /= base;
97 if (neg) {
98 if (cutlim > 0) {
99 cutlim -= base;
100 cutoff += 1;
101 }
102 cutlim = -cutlim;
103 }
104 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
105 if (isdigit(c))
106 c -= '0';
107 else if (isalpha(c))
108 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
109 else
110 break;
111 if (c >= base)
112 break;
113 if (any < 0)
114 continue;
115 if (neg) {
116 if (acc < cutoff || (acc == cutoff && c > cutlim)) {
117 any = -1;
118 acc = INTMAX_MIN;
119 errno = ERANGE;
120 } else {
121 any = 1;
122 acc *= base;
123 acc -= c;
124 }
125 } else {
126 if (acc > cutoff || (acc == cutoff && c > cutlim)) {
127 any = -1;
128 acc = INTMAX_MAX;
129 errno = ERANGE;
130 } else {
131 any = 1;
132 acc *= base;
133 acc += c;
134 }
135 }
136 }
137 if (endptr != 0)
138 *endptr = (char *) (any ? s - 1 : nptr);
139 return (acc);
140}
diff --git a/src/lib/libc/stdlib/strtol.3 b/src/lib/libc/stdlib/strtol.3
new file mode 100644
index 0000000000..e45941e07b
--- /dev/null
+++ b/src/lib/libc/stdlib/strtol.3
@@ -0,0 +1,258 @@
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.15 2006/03/29 20:10:52 grunk Exp $
33.\"
34.Dd January 3, 2006
35.Dt STRTOL 3
36.Os
37.Sh NAME
38.Nm strtol ,
39.Nm strtoll ,
40.Nm strtoimax ,
41.Nm strtoq ,
42.Nd "convert string value to a long, long long or intmax_t integer"
43.Sh SYNOPSIS
44.Fd #include <stdlib.h>
45.Fd #include <limits.h>
46.Ft long
47.Fn strtol "const char *nptr" "char **endptr" "int base"
48.Pp
49.Ft long long
50.Fn strtoll "const char *nptr" "char **endptr" "int base"
51.Pp
52.Fd #include <inttypes.h>
53.Ft intmax_t
54.Fn strtoimax "const char *nptr" "char **endptr" "int base"
55.Pp
56.Fd #include <sys/types.h>
57.Fd #include <stdlib.h>
58.Fd #include <limits.h>
59.Ft quad_t
60.Fn strtoq "const char *nptr" "char **endptr" "int base"
61.Sh DESCRIPTION
62The
63.Fn strtol
64function converts the string in
65.Fa nptr
66to a
67.Li long
68value.
69The
70.Fn strtoll
71function converts the string in
72.Fa nptr
73to a
74.Li long long
75value.
76The
77.Fn strtoimax
78function converts the string in
79.Fa nptr
80to an
81.Li intmax_t
82value.
83The
84.Fn strtoq
85function is a deprecated equivalent of
86.Fn strtoll
87and is provided for backwards compatibility with legacy programs.
88The conversion is done according to the given
89.Fa base ,
90which must be a number between 2 and 36 inclusive or the special value 0.
91.Pp
92The string may begin with an arbitrary amount of whitespace
93(as determined by
94.Xr isspace 3 )
95followed by a single optional
96.Ql +
97or
98.Ql -
99sign.
100If
101.Fa base
102is zero or 16, the string may then include a
103.Ql 0x
104prefix, and the number will be read in base 16; otherwise, a zero
105.Fa base
106is taken as 10 (decimal) unless the next character is
107.Ql 0 ,
108in which case it is taken as 8 (octal).
109.Pp
110The remainder of the string is converted to a
111.Li long ,
112.Li long long ,
113or
114.Li intmax_t ,
115value in the obvious manner,
116stopping at the first character which is not a valid digit
117in the given base.
118(In bases above 10, the letter
119.Ql A
120in either upper or lower case represents 10,
121.Ql B
122represents 11, and so forth, with
123.Ql Z
124representing 35.)
125.Pp
126If
127.Fa endptr
128is non-null,
129.Fn strtol
130stores the address of the first invalid character in
131.Fa *endptr .
132If there were no digits at all, however,
133.Fn strtol
134stores the original value of
135.Fa nptr
136in
137.Fa *endptr .
138(Thus, if
139.Fa *nptr
140is not
141.Ql \e0
142but
143.Fa **endptr
144is
145.Ql \e0
146on return, the entire string was valid.)
147.Sh RETURN VALUES
148The
149.Fn strtol ,
150.Fn strtoll ,
151.Fn strtoimax ,
152and
153.Fn strtoq
154functions returns the result of the conversion,
155unless the value would underflow or overflow.
156If overflow or underflow occurs,
157.Va errno
158is set to
159.Er ERANGE
160and the function return value is as follows:
161.Bl -column -offset indent "strtoimax" "overflow" "underflow"
162.It Sy Function Ta Sy overflow Ta Sy underflow
163.It Fn strtol Ta Dv LONG_MIN Ta Dv LONG_MAX
164.It Fn strtoll Ta Dv LLONG_MIN Ta Dv LLONG_MAX
165.It Fn strtoimax Ta Dv INTMAX_MIN Ta Dv INTMAX_MAX
166.It Fn strtoq Ta Dv LLONG_MIN Ta Dv LLONG_MAX
167.El
168.Sh EXAMPLES
169Ensuring that a string is a valid number (i.e., in range and containing no
170trailing characters) requires clearing
171.Va errno
172beforehand explicitly since
173.Va errno
174is not changed on a successful call to
175.Fn strtol ,
176and the return value of
177.Fn strtol
178cannot be used unambiguously to signal an error:
179.Bd -literal -offset indent
180char *ep;
181long lval;
182
183\&...
184
185errno = 0;
186lval = strtol(buf, &ep, 10);
187if (buf[0] == '\e0' || *ep != '\e0')
188 goto not_a_number;
189if (errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN))
190 goto out_of_range;
191.Ed
192.Pp
193This example will accept
194.Dq 12
195but not
196.Dq 12foo
197or
198.Dq 12\en .
199If trailing whitespace is acceptable, further checks must be done on
200.Va *ep ;
201alternately, use
202.Xr sscanf 3 .
203.Pp
204If
205.Fn strtol
206is being used instead of
207.Xr atoi 3 ,
208error checking is further complicated because the desired return value is an
209.Li int
210rather than a
211.Li long ;
212however, on some architectures integers and long integers are the same size.
213Thus the following is necessary:
214.Bd -literal -offset indent
215char *ep;
216int ival;
217long lval;
218
219\&...
220
221errno = 0;
222lval = strtol(buf, &ep, 10);
223if (buf[0] == '\e0' || *ep != '\e0')
224 goto not_a_number;
225if ((errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN)) ||
226 (lval > INT_MAX || lval < INT_MIN))
227 goto out_of_range;
228ival = lval;
229.Ed
230.Sh ERRORS
231.Bl -tag -width Er
232.It Bq Er ERANGE
233The given string was out of range; the value converted has been clamped.
234.El
235.Sh SEE ALSO
236.Xr atof 3 ,
237.Xr atoi 3 ,
238.Xr atol 3 ,
239.Xr atoll 3 ,
240.Xr sscanf 3 ,
241.Xr strtod 3 ,
242.Xr strtonum 3 ,
243.Xr strtoul 3
244.Sh STANDARDS
245The
246.Fn strtol ,
247.Fn strtoll ,
248and
249.Fn strtoimax
250functions conform to
251.St -ansiC-99 .
252The
253.Fn strtoq
254function is a
255.Bx
256extension and is provided for backwards compatibility with legacy programs.
257.Sh BUGS
258Ignores 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..5a244766db
--- /dev/null
+++ b/src/lib/libc/stdlib/strtol.c
@@ -0,0 +1,140 @@
1/* $OpenBSD: strtol.c,v 1.7 2005/08/08 08:05:37 espie Exp $ */
2/*-
3 * Copyright (c) 1990 The Regents of the University of California.
4 * 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
31#include <ctype.h>
32#include <errno.h>
33#include <limits.h>
34#include <stdlib.h>
35
36
37/*
38 * Convert a string to a long integer.
39 *
40 * Ignores `locale' stuff. Assumes that the upper and lower case
41 * alphabets and digits are each contiguous.
42 */
43long
44strtol(const char *nptr, char **endptr, int base)
45{
46 const char *s;
47 long acc, cutoff;
48 int c;
49 int neg, any, cutlim;
50
51 /*
52 * Skip white space and pick up leading +/- sign if any.
53 * If base is 0, allow 0x for hex and 0 for octal, else
54 * assume decimal; if base is already 16, allow 0x.
55 */
56 s = nptr;
57 do {
58 c = (unsigned char) *s++;
59 } while (isspace(c));
60 if (c == '-') {
61 neg = 1;
62 c = *s++;
63 } else {
64 neg = 0;
65 if (c == '+')
66 c = *s++;
67 }
68 if ((base == 0 || base == 16) &&
69 c == '0' && (*s == 'x' || *s == 'X')) {
70 c = s[1];
71 s += 2;
72 base = 16;
73 }
74 if (base == 0)
75 base = c == '0' ? 8 : 10;
76
77 /*
78 * Compute the cutoff value between legal numbers and illegal
79 * numbers. That is the largest legal value, divided by the
80 * base. An input number that is greater than this value, if
81 * followed by a legal input character, is too big. One that
82 * is equal to this value may be valid or not; the limit
83 * between valid and invalid numbers is then based on the last
84 * digit. For instance, if the range for longs is
85 * [-2147483648..2147483647] and the input base is 10,
86 * cutoff will be set to 214748364 and cutlim to either
87 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
88 * a value > 214748364, or equal but the next digit is > 7 (or 8),
89 * the number is too big, and we will return a range error.
90 *
91 * Set any if any `digits' consumed; make it negative to indicate
92 * overflow.
93 */
94 cutoff = neg ? LONG_MIN : LONG_MAX;
95 cutlim = cutoff % base;
96 cutoff /= base;
97 if (neg) {
98 if (cutlim > 0) {
99 cutlim -= base;
100 cutoff += 1;
101 }
102 cutlim = -cutlim;
103 }
104 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
105 if (isdigit(c))
106 c -= '0';
107 else if (isalpha(c))
108 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
109 else
110 break;
111 if (c >= base)
112 break;
113 if (any < 0)
114 continue;
115 if (neg) {
116 if (acc < cutoff || acc == cutoff && c > cutlim) {
117 any = -1;
118 acc = LONG_MIN;
119 errno = ERANGE;
120 } else {
121 any = 1;
122 acc *= base;
123 acc -= c;
124 }
125 } else {
126 if (acc > cutoff || acc == cutoff && c > cutlim) {
127 any = -1;
128 acc = LONG_MAX;
129 errno = ERANGE;
130 } else {
131 any = 1;
132 acc *= base;
133 acc += c;
134 }
135 }
136 }
137 if (endptr != 0)
138 *endptr = (char *) (any ? s - 1 : nptr);
139 return (acc);
140}
diff --git a/src/lib/libc/stdlib/strtoll.c b/src/lib/libc/stdlib/strtoll.c
new file mode 100644
index 0000000000..37379252e3
--- /dev/null
+++ b/src/lib/libc/stdlib/strtoll.c
@@ -0,0 +1,153 @@
1/* $OpenBSD: strtoll.c,v 1.6 2005/11/10 10:00:17 espie Exp $ */
2/*-
3 * Copyright (c) 1992 The Regents of the University of California.
4 * 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
31#include <sys/types.h>
32
33#include <ctype.h>
34#include <errno.h>
35#include <limits.h>
36#include <stdlib.h>
37
38/*
39 * Convert a string to a long long.
40 *
41 * Ignores `locale' stuff. Assumes that the upper and lower case
42 * alphabets and digits are each contiguous.
43 */
44long long
45strtoll(const char *nptr, char **endptr, int base)
46{
47 const char *s;
48 long long acc, cutoff;
49 int c;
50 int neg, any, cutlim;
51
52 /*
53 * Skip white space and pick up leading +/- sign if any.
54 * If base is 0, allow 0x for hex and 0 for octal, else
55 * assume decimal; if base is already 16, allow 0x.
56 */
57 s = nptr;
58 do {
59 c = (unsigned char) *s++;
60 } while (isspace(c));
61 if (c == '-') {
62 neg = 1;
63 c = *s++;
64 } else {
65 neg = 0;
66 if (c == '+')
67 c = *s++;
68 }
69 if ((base == 0 || base == 16) &&
70 c == '0' && (*s == 'x' || *s == 'X')) {
71 c = s[1];
72 s += 2;
73 base = 16;
74 }
75 if (base == 0)
76 base = c == '0' ? 8 : 10;
77
78 /*
79 * Compute the cutoff value between legal numbers and illegal
80 * numbers. That is the largest legal value, divided by the
81 * base. An input number that is greater than this value, if
82 * followed by a legal input character, is too big. One that
83 * is equal to this value may be valid or not; the limit
84 * between valid and invalid numbers is then based on the last
85 * digit. For instance, if the range for long longs is
86 * [-9223372036854775808..9223372036854775807] and the input base
87 * is 10, cutoff will be set to 922337203685477580 and cutlim to
88 * either 7 (neg==0) or 8 (neg==1), meaning that if we have
89 * accumulated a value > 922337203685477580, or equal but the
90 * next digit is > 7 (or 8), the number is too big, and we will
91 * return a range error.
92 *
93 * Set any if any `digits' consumed; make it negative to indicate
94 * overflow.
95 */
96 cutoff = neg ? LLONG_MIN : LLONG_MAX;
97 cutlim = cutoff % base;
98 cutoff /= base;
99 if (neg) {
100 if (cutlim > 0) {
101 cutlim -= base;
102 cutoff += 1;
103 }
104 cutlim = -cutlim;
105 }
106 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
107 if (isdigit(c))
108 c -= '0';
109 else if (isalpha(c))
110 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
111 else
112 break;
113 if (c >= base)
114 break;
115 if (any < 0)
116 continue;
117 if (neg) {
118 if (acc < cutoff || (acc == cutoff && c > cutlim)) {
119 any = -1;
120 acc = LLONG_MIN;
121 errno = ERANGE;
122 } else {
123 any = 1;
124 acc *= base;
125 acc -= c;
126 }
127 } else {
128 if (acc > cutoff || (acc == cutoff && c > cutlim)) {
129 any = -1;
130 acc = LLONG_MAX;
131 errno = ERANGE;
132 } else {
133 any = 1;
134 acc *= base;
135 acc += c;
136 }
137 }
138 }
139 if (endptr != 0)
140 *endptr = (char *) (any ? s - 1 : nptr);
141 return (acc);
142}
143
144#ifdef __weak_alias
145__weak_alias(strtoq, strtoll);
146#else
147quad_t
148strtoq(const char *nptr, char **endptr, int base)
149{
150
151 return ((quad_t)strtoll(nptr, endptr, base));
152}
153#endif
diff --git a/src/lib/libc/stdlib/strtonum.3 b/src/lib/libc/stdlib/strtonum.3
new file mode 100644
index 0000000000..6b3c9031d6
--- /dev/null
+++ b/src/lib/libc/stdlib/strtonum.3
@@ -0,0 +1,152 @@
1.\" $OpenBSD: strtonum.3,v 1.13 2006/04/25 05:15:42 tedu Exp $
2.\"
3.\" Copyright (c) 2004 Ted Unangst
4.\"
5.\" Permission to use, copy, modify, and distribute this software for any
6.\" purpose with or without fee is hereby granted, provided that the above
7.\" copyright notice and this permission notice appear in all copies.
8.\"
9.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16.\"
17.Dd April 29, 2004
18.Dt STRTONUM 3
19.Os
20.Sh NAME
21.Nm strtonum
22.Nd "reliably convert string value to an integer"
23.Sh SYNOPSIS
24.Fd #include <stdlib.h>
25.Ft long long
26.Fo strtonum
27.Fa "const char *nptr"
28.Fa "long long minval"
29.Fa "long long maxval"
30.Fa "const char **errstr"
31.Fc
32.Sh DESCRIPTION
33The
34.Fn strtonum
35function converts the string in
36.Fa nptr
37to a
38.Li long long
39value.
40The
41.Fn strtonum
42function was designed to facilitate safe, robust programming
43and overcome the shortcomings of the
44.Xr atoi 3
45and
46.Xr strtol 3
47family of interfaces.
48.Pp
49The string may begin with an arbitrary amount of whitespace
50(as determined by
51.Xr isspace 3 )
52followed by a single optional
53.Ql +
54or
55.Ql -
56sign.
57.Pp
58The remainder of the string is converted to a
59.Li long long
60value according to base 10.
61.Pp
62The value obtained is then checked against the provided
63.Fa minval
64and
65.Fa maxval
66bounds.
67If
68.Fa errstr
69is non-null,
70.Fn strtonum
71stores an error string in
72.Fa *errstr
73indicating the failure.
74.Sh RETURN VALUES
75The
76.Fn strtonum
77function returns the result of the conversion,
78unless the value would exceed the provided bounds or is invalid.
79On error, 0 is returned,
80.Va errno
81is set, and
82.Fa errstr
83will point to an error message.
84.Fa *errstr
85will be set to
86.Dv NULL
87on success;
88this fact can be used to differentiate
89a successful return of 0 from an error.
90.Sh EXAMPLES
91Using
92.Fn strtonum
93correctly is meant to be simpler than the alternative functions.
94.Bd -literal -offset indent
95int iterations;
96const char *errstr;
97
98iterations = strtonum(optarg, 1, 64, &errstr);
99if (errstr)
100 errx(1, "number of iterations is %s: %s", errstr, optarg);
101.Ed
102.Pp
103The above example will guarantee that the value of iterations is between
1041 and 64 (inclusive).
105.Sh ERRORS
106.Bl -tag -width Er
107.It Bq Er ERANGE
108The given string was out of range.
109.It Bq Er EINVAL
110The given string did not consist solely of digit characters.
111.It Bq Er EINVAL
112.Ar minval
113was larger than
114.Ar maxval .
115.El
116.Pp
117If an error occurs,
118.Fa errstr
119will be set to one of the following strings:
120.Pp
121.Bl -tag -width "too largeXX" -compact
122.It too large
123The result was larger than the provided maximum value.
124.It too small
125The result was smaller than the provided minimum value.
126.It invalid
127The string did not consist solely of digit characters.
128.El
129.Sh SEE ALSO
130.Xr atof 3 ,
131.Xr atoi 3 ,
132.Xr atol 3 ,
133.Xr atoll 3 ,
134.Xr sscanf 3 ,
135.Xr strtod 3 ,
136.Xr strtol 3 ,
137.Xr strtoul 3
138.Sh STANDARDS
139.Fn strtonum
140is an
141.Ox
142extension.
143The existing alternatives, such as
144.Xr atoi 3
145and
146.Xr strtol 3 ,
147are either impossible or difficult to use safely.
148.Sh HISTORY
149The
150.Fn strtonum
151function first appeared in
152.Ox 3.6 .
diff --git a/src/lib/libc/stdlib/strtonum.c b/src/lib/libc/stdlib/strtonum.c
new file mode 100644
index 0000000000..e426388ed0
--- /dev/null
+++ b/src/lib/libc/stdlib/strtonum.c
@@ -0,0 +1,65 @@
1/* $OpenBSD: strtonum.c,v 1.6 2004/08/03 19:38:01 millert Exp $ */
2
3/*
4 * Copyright (c) 2004 Ted Unangst and Todd Miller
5 * All rights reserved.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include <errno.h>
21#include <limits.h>
22#include <stdlib.h>
23
24#define INVALID 1
25#define TOOSMALL 2
26#define TOOLARGE 3
27
28long long
29strtonum(const char *numstr, long long minval, long long maxval,
30 const char **errstrp)
31{
32 long long ll = 0;
33 char *ep;
34 int error = 0;
35 struct errval {
36 const char *errstr;
37 int err;
38 } ev[4] = {
39 { NULL, 0 },
40 { "invalid", EINVAL },
41 { "too small", ERANGE },
42 { "too large", ERANGE },
43 };
44
45 ev[0].err = errno;
46 errno = 0;
47 if (minval > maxval)
48 error = INVALID;
49 else {
50 ll = strtoll(numstr, &ep, 10);
51 if (numstr == ep || *ep != '\0')
52 error = INVALID;
53 else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
54 error = TOOSMALL;
55 else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
56 error = TOOLARGE;
57 }
58 if (errstrp != NULL)
59 *errstrp = ev[error].errstr;
60 errno = ev[error].err;
61 if (error)
62 ll = 0;
63
64 return (ll);
65}
diff --git a/src/lib/libc/stdlib/strtoul.3 b/src/lib/libc/stdlib/strtoul.3
new file mode 100644
index 0000000000..2ea5e83297
--- /dev/null
+++ b/src/lib/libc/stdlib/strtoul.3
@@ -0,0 +1,242 @@
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.16 2006/01/13 17:58:09 millert Exp $
33.\"
34.Dd January 3, 2006
35.Dt STRTOUL 3
36.Os
37.Sh NAME
38.Nm strtoul ,
39.Nm strtoull ,
40.Nm strtoumax ,
41.Nm strtouq
42.Nd "convert a string to an unsigned long, unsigned long long or uintmax_t integer"
43.Sh SYNOPSIS
44.Fd #include <stdlib.h>
45.Fd #include <limits.h>
46.Ft unsigned long
47.Fn strtoul "const char *nptr" "char **endptr" "int base"
48.Pp
49.Ft unsigned long long
50.Fn strtoull "const char *nptr" "char **endptr" "int base"
51.Pp
52.Fd #include <inttypes.h>
53.Ft uintmax_t
54.Fn strtoumax "const char *nptr" "char **endptr" "int base"
55.Pp
56.Fd #include <sys/types.h>
57.Fd #include <stdlib.h>
58.Fd #include <limits.h>
59.Ft u_quad_t
60.Fn strtouq "const char *nptr" "char **endptr" "int base"
61.Sh DESCRIPTION
62The
63.Fn strtoul
64function converts the string in
65.Fa nptr
66to an
67.Li unsigned long
68value.
69The
70.Fn strtoull
71function converts the string in
72.Fa nptr
73to an
74.Li unsigned long long
75value.
76The
77.Fn strtoumax
78function converts the string in
79.Fa nptr
80to a
81.Li umaxint_t
82value.
83The
84.Fn strtouq
85function is a deprecated equivalent of
86.Fn strtoull
87and is provided for backwards compatibility with legacy programs.
88The conversion is done according to the given
89.Fa base ,
90which must be a number between 2 and 36 inclusive
91or the special value 0.
92If the string in
93.Fa nptr
94represents a negative number, it will be converted to its unsigned equivalent.
95This behavior is consistent with what happens when a signed integer type is
96cast to its unsigned counterpart.
97.Pp
98The string may begin with an arbitrary amount of whitespace
99(as determined by
100.Xr isspace 3 )
101followed by a single optional
102.Ql +
103or
104.Ql -
105sign.
106If
107.Fa base
108is zero or 16, the string may then include a
109.Ql 0x
110prefix, and the number will be read in base 16; otherwise, a zero
111.Fa base
112is taken as 10 (decimal) unless the next character is
113.Ql 0 ,
114in which case it is taken as 8 (octal).
115.Pp
116The remainder of the string is converted to an
117.Li unsigned long
118value in the obvious manner, stopping at the end of the string
119or at the first character that does not produce a valid digit
120in the given base.
121(In bases above 10, the letter
122.Ql A
123in either upper or lower case represents 10,
124.Ql B
125represents 11, and so forth, with
126.Ql Z
127representing 35.)
128.Pp
129If
130.Fa endptr
131is non-null,
132.Fn strtoul
133stores the address of the first invalid character in
134.Fa *endptr .
135If there were no digits at all, however,
136.Fn strtoul
137stores the original value of
138.Fa nptr
139in
140.Fa *endptr .
141(Thus, if
142.Fa *nptr
143is not
144.Ql \e0
145but
146.Fa **endptr
147is
148.Ql \e0
149on return, the entire string was valid.)
150.Sh RETURN VALUES
151The
152.Fn strtoul ,
153.Fn strtoull ,
154.Fn strtoumax
155and
156.Fn strtouq
157functions return either the result of the conversion or,
158if there was a leading minus sign,
159the negation of the result of the conversion,
160unless the original (non-negated) value would overflow.
161If overflow occurs,
162.Fn strtoul
163returns
164.Dv ULONG_MAX ,
165.Fn strtoull
166returns
167.Dv ULLONG_MAX ,
168.Fn strtoumax
169returns
170.Dv UINTMAX_MAX ,
171.Fn strtouq
172returns
173.Dv ULLONG_MAX
174and the global variable
175.Va errno
176is set to
177.Er ERANGE .
178.Pp
179There is no way to determine if
180.Fn strtoul
181has processed a negative number (and returned an unsigned value) short of
182examining the string in
183.Fa nptr
184directly.
185.Sh EXAMPLES
186Ensuring that a string is a valid number (i.e., in range and containing no
187trailing characters) requires clearing
188.Va errno
189beforehand explicitly since
190.Va errno
191is not changed on a successful call to
192.Fn strtoul ,
193and the return value of
194.Fn strtoul
195cannot be used unambiguously to signal an error:
196.Bd -literal -offset indent
197char *ep;
198unsigned long ulval;
199
200\&...
201
202errno = 0;
203ulval = strtoul(buf, &ep, 10);
204if (buf[0] == '\e0' || *ep != '\e0')
205 goto not_a_number;
206if (errno == ERANGE && ulval == ULONG_MAX)
207 goto out_of_range;
208.Ed
209.Pp
210This example will accept
211.Dq 12
212but not
213.Dq 12foo
214or
215.Dq 12\en .
216If trailing whitespace is acceptable, further checks must be done on
217.Va *ep ;
218alternately, use
219.Xr sscanf 3 .
220.Sh ERRORS
221.Bl -tag -width Er
222.It Bq Er ERANGE
223The given string was out of range; the value converted has been clamped.
224.El
225.Sh SEE ALSO
226.Xr sscanf 3 ,
227.Xr strtol 3
228.Sh STANDARDS
229The
230.Fn strtoul ,
231.Fn strtoull ,
232and
233.Fn strtoumax
234functions conform to
235.St -ansiC-99 .
236The
237.Fn strtouq
238function is a
239.Bx
240extension and is provided for backwards compatibility with legacy programs.
241.Sh BUGS
242Ignores 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..d7dddab778
--- /dev/null
+++ b/src/lib/libc/stdlib/strtoul.c
@@ -0,0 +1,102 @@
1/* $OpenBSD: strtoul.c,v 1.7 2005/08/08 08:05:37 espie Exp $ */
2/*
3 * Copyright (c) 1990 Regents of the University of California.
4 * 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
31#include <ctype.h>
32#include <errno.h>
33#include <limits.h>
34#include <stdlib.h>
35
36/*
37 * Convert a string to an unsigned long integer.
38 *
39 * Ignores `locale' stuff. Assumes that the upper and lower case
40 * alphabets and digits are each contiguous.
41 */
42unsigned long
43strtoul(const char *nptr, char **endptr, int base)
44{
45 const char *s;
46 unsigned long acc, cutoff;
47 int c;
48 int neg, any, cutlim;
49
50 /*
51 * See strtol for comments as to the logic used.
52 */
53 s = nptr;
54 do {
55 c = (unsigned char) *s++;
56 } while (isspace(c));
57 if (c == '-') {
58 neg = 1;
59 c = *s++;
60 } else {
61 neg = 0;
62 if (c == '+')
63 c = *s++;
64 }
65 if ((base == 0 || base == 16) &&
66 c == '0' && (*s == 'x' || *s == 'X')) {
67 c = s[1];
68 s += 2;
69 base = 16;
70 }
71 if (base == 0)
72 base = c == '0' ? 8 : 10;
73
74 cutoff = ULONG_MAX / (unsigned long)base;
75 cutlim = ULONG_MAX % (unsigned long)base;
76 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
77 if (isdigit(c))
78 c -= '0';
79 else if (isalpha(c))
80 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
81 else
82 break;
83 if (c >= base)
84 break;
85 if (any < 0)
86 continue;
87 if (acc > cutoff || acc == cutoff && c > cutlim) {
88 any = -1;
89 acc = ULONG_MAX;
90 errno = ERANGE;
91 } else {
92 any = 1;
93 acc *= (unsigned long)base;
94 acc += c;
95 }
96 }
97 if (neg && any > 0)
98 acc = -acc;
99 if (endptr != 0)
100 *endptr = (char *) (any ? s - 1 : nptr);
101 return (acc);
102}
diff --git a/src/lib/libc/stdlib/strtoull.c b/src/lib/libc/stdlib/strtoull.c
new file mode 100644
index 0000000000..37859776f9
--- /dev/null
+++ b/src/lib/libc/stdlib/strtoull.c
@@ -0,0 +1,115 @@
1/* $OpenBSD: strtoull.c,v 1.5 2005/08/08 08:05:37 espie Exp $ */
2/*-
3 * Copyright (c) 1992 The Regents of the University of California.
4 * 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
31#include <sys/types.h>
32
33#include <ctype.h>
34#include <errno.h>
35#include <limits.h>
36#include <stdlib.h>
37
38/*
39 * Convert a string to an unsigned long long.
40 *
41 * Ignores `locale' stuff. Assumes that the upper and lower case
42 * alphabets and digits are each contiguous.
43 */
44unsigned long long
45strtoull(const char *nptr, char **endptr, int base)
46{
47 const char *s;
48 unsigned long long acc, cutoff;
49 int c;
50 int neg, any, cutlim;
51
52 /*
53 * See strtoq for comments as to the logic used.
54 */
55 s = nptr;
56 do {
57 c = (unsigned char) *s++;
58 } while (isspace(c));
59 if (c == '-') {
60 neg = 1;
61 c = *s++;
62 } else {
63 neg = 0;
64 if (c == '+')
65 c = *s++;
66 }
67 if ((base == 0 || base == 16) &&
68 c == '0' && (*s == 'x' || *s == 'X')) {
69 c = s[1];
70 s += 2;
71 base = 16;
72 }
73 if (base == 0)
74 base = c == '0' ? 8 : 10;
75
76 cutoff = ULLONG_MAX / (unsigned long long)base;
77 cutlim = ULLONG_MAX % (unsigned long long)base;
78 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
79 if (isdigit(c))
80 c -= '0';
81 else if (isalpha(c))
82 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
83 else
84 break;
85 if (c >= base)
86 break;
87 if (any < 0)
88 continue;
89 if (acc > cutoff || (acc == cutoff && c > cutlim)) {
90 any = -1;
91 acc = ULLONG_MAX;
92 errno = ERANGE;
93 } else {
94 any = 1;
95 acc *= (unsigned long long)base;
96 acc += c;
97 }
98 }
99 if (neg && any > 0)
100 acc = -acc;
101 if (endptr != 0)
102 *endptr = (char *) (any ? s - 1 : nptr);
103 return (acc);
104}
105
106#ifdef __weak_alias
107__weak_alias(strtouq, strtoull);
108#else
109u_quad_t
110strtouq(const char *nptr, char **endptr, int base)
111{
112
113 return ((u_quad_t)strtoull(nptr, endptr, base));
114}
115#endif
diff --git a/src/lib/libc/stdlib/strtoumax.c b/src/lib/libc/stdlib/strtoumax.c
new file mode 100644
index 0000000000..ce6e2c00f1
--- /dev/null
+++ b/src/lib/libc/stdlib/strtoumax.c
@@ -0,0 +1,102 @@
1/* $OpenBSD: strtoumax.c,v 1.1 2006/01/13 17:58:09 millert Exp $ */
2
3/*-
4 * Copyright (c) 1992 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. 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#include <ctype.h>
33#include <errno.h>
34#include <inttypes.h>
35
36/*
37 * Convert a string to a uintmax_t.
38 *
39 * Ignores `locale' stuff. Assumes that the upper and lower case
40 * alphabets and digits are each contiguous.
41 */
42uintmax_t
43strtoumax(const char *nptr, char **endptr, int base)
44{
45 const char *s;
46 uintmax_t acc, cutoff;
47 int c;
48 int neg, any, cutlim;
49
50 /*
51 * See strtoq for comments as to the logic used.
52 */
53 s = nptr;
54 do {
55 c = (unsigned char) *s++;
56 } while (isspace(c));
57 if (c == '-') {
58 neg = 1;
59 c = *s++;
60 } else {
61 neg = 0;
62 if (c == '+')
63 c = *s++;
64 }
65 if ((base == 0 || base == 16) &&
66 c == '0' && (*s == 'x' || *s == 'X')) {
67 c = s[1];
68 s += 2;
69 base = 16;
70 }
71 if (base == 0)
72 base = c == '0' ? 8 : 10;
73
74 cutoff = UINTMAX_MAX / (uintmax_t)base;
75 cutlim = UINTMAX_MAX % (uintmax_t)base;
76 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
77 if (isdigit(c))
78 c -= '0';
79 else if (isalpha(c))
80 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
81 else
82 break;
83 if (c >= base)
84 break;
85 if (any < 0)
86 continue;
87 if (acc > cutoff || (acc == cutoff && c > cutlim)) {
88 any = -1;
89 acc = UINTMAX_MAX;
90 errno = ERANGE;
91 } else {
92 any = 1;
93 acc *= (uintmax_t)base;
94 acc += c;
95 }
96 }
97 if (neg && any > 0)
98 acc = -acc;
99 if (endptr != 0)
100 *endptr = (char *) (any ? s - 1 : nptr);
101 return (acc);
102}
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..14ddcae8d3
--- /dev/null
+++ b/src/lib/libc/stdlib/system.c
@@ -0,0 +1,74 @@
1/* $OpenBSD: system.c,v 1.8 2005/08/08 08:05:37 espie Exp $ */
2/*
3 * Copyright (c) 1988 The Regents of the University of California.
4 * 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
31#include <sys/types.h>
32#include <sys/wait.h>
33#include <signal.h>
34#include <stdlib.h>
35#include <unistd.h>
36#include <paths.h>
37
38extern char **environ;
39
40int
41system(const char *command)
42{
43 pid_t pid;
44 sig_t intsave, quitsave;
45 sigset_t mask, omask;
46 int pstat;
47 char *argp[] = {"sh", "-c", NULL, NULL};
48
49 if (!command) /* just checking... */
50 return(1);
51
52 argp[2] = (char *)command;
53
54 sigemptyset(&mask);
55 sigaddset(&mask, SIGCHLD);
56 sigprocmask(SIG_BLOCK, &mask, &omask);
57 switch (pid = vfork()) {
58 case -1: /* error */
59 sigprocmask(SIG_SETMASK, &omask, NULL);
60 return(-1);
61 case 0: /* child */
62 sigprocmask(SIG_SETMASK, &omask, NULL);
63 execve(_PATH_BSHELL, argp, environ);
64 _exit(127);
65 }
66
67 intsave = signal(SIGINT, SIG_IGN);
68 quitsave = signal(SIGQUIT, SIG_IGN);
69 pid = waitpid(pid, (int *)&pstat, 0);
70 sigprocmask(SIG_SETMASK, &omask, NULL);
71 (void)signal(SIGINT, intsave);
72 (void)signal(SIGQUIT, quitsave);
73 return (pid == -1 ? -1 : pstat);
74}
diff --git a/src/lib/libc/stdlib/tfind.c b/src/lib/libc/stdlib/tfind.c
new file mode 100644
index 0000000000..ff6bcd742d
--- /dev/null
+++ b/src/lib/libc/stdlib/tfind.c
@@ -0,0 +1,41 @@
1/* $OpenBSD: tfind.c,v 1.5 2005/03/30 18:51:49 pat Exp $ */
2
3/*
4 * Tree search generalized from Knuth (6.2.2) Algorithm T just like
5 * the AT&T man page says.
6 *
7 * The node_t structure is for internal use only, lint doesn't grok it.
8 *
9 * Written by reading the System V Interface Definition, not the code.
10 *
11 * Totally public domain.
12 */
13/*LINTLIBRARY*/
14#include <search.h>
15
16typedef struct node_t
17{
18 char *key;
19 struct node_t *llink, *rlink;
20} node;
21
22/* find a node, or return 0 */
23void *
24tfind(const void *vkey, void * const *vrootp,
25 int (*compar)(const void *, const void *))
26{
27 char *key = (char *)vkey;
28 node **rootp = (node **)vrootp;
29
30 if (rootp == (struct node_t **)0)
31 return ((struct node_t *)0);
32 while (*rootp != (struct node_t *)0) { /* T1: */
33 int r;
34 if ((r = (*compar)(key, (*rootp)->key)) == 0) /* T2: */
35 return (*rootp); /* key found */
36 rootp = (r < 0) ?
37 &(*rootp)->llink : /* T3: follow left branch */
38 &(*rootp)->rlink; /* T4: follow right branch */
39 }
40 return (node *)0;
41}
diff --git a/src/lib/libc/stdlib/tsearch.3 b/src/lib/libc/stdlib/tsearch.3
new file mode 100644
index 0000000000..0dc5c0c374
--- /dev/null
+++ b/src/lib/libc/stdlib/tsearch.3
@@ -0,0 +1,127 @@
1.\" $OpenBSD: tsearch.3,v 1.15 2006/04/04 19:07:23 otto 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 and a pointer to the new root will be returned.
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
117.Sh STANDARDS
118These functions conform to
119.St -p1003.1-2004 .
120.Sh CAVEATS
121The
122.St -p1003.1-2004
123standard does not specify what value should be returned when deleting the
124root node.
125Since implementations vary, the user of the
126.Fn tdelete
127function should not rely on a specific behaviour.
diff --git a/src/lib/libc/stdlib/tsearch.c b/src/lib/libc/stdlib/tsearch.c
new file mode 100644
index 0000000000..667c57731b
--- /dev/null
+++ b/src/lib/libc/stdlib/tsearch.c
@@ -0,0 +1,121 @@
1/* $OpenBSD: tsearch.c,v 1.6 2006/04/04 11:21:50 moritz Exp $ */
2
3/*
4 * Tree search generalized from Knuth (6.2.2) Algorithm T just like
5 * the AT&T man page says.
6 *
7 * The node_t structure is for internal use only, lint doesn't grok it.
8 *
9 * Written by reading the System V Interface Definition, not the code.
10 *
11 * Totally public domain.
12 */
13/*LINTLIBRARY*/
14
15#include <search.h>
16#include <stdlib.h>
17
18typedef struct node_t {
19 char *key;
20 struct node_t *left, *right;
21} node;
22
23/* find or insert datum into search tree */
24void *
25tsearch(const void *vkey, void **vrootp,
26 int (*compar)(const void *, const void *))
27{
28 node *q;
29 char *key = (char *)vkey;
30 node **rootp = (node **)vrootp;
31
32 if (rootp == (struct node_t **)0)
33 return ((void *)0);
34 while (*rootp != (struct node_t *)0) { /* Knuth's T1: */
35 int r;
36
37 if ((r = (*compar)(key, (*rootp)->key)) == 0) /* T2: */
38 return ((void *)*rootp); /* we found it! */
39 rootp = (r < 0) ?
40 &(*rootp)->left : /* T3: follow left branch */
41 &(*rootp)->right; /* T4: follow right branch */
42 }
43 q = (node *) malloc(sizeof(node)); /* T5: key not found */
44 if (q != (struct node_t *)0) { /* make new node */
45 *rootp = q; /* link new node to old */
46 q->key = key; /* initialize new node */
47 q->left = q->right = (struct node_t *)0;
48 }
49 return ((void *)q);
50}
51
52/* delete node with given key */
53void *
54tdelete(const void *vkey, void **vrootp,
55 int (*compar)(const void *, const void *))
56{
57 node **rootp = (node **)vrootp;
58 char *key = (char *)vkey;
59 node *p;
60 node *q;
61 node *r;
62 int cmp;
63
64 if (rootp == (struct node_t **)0 || (p = *rootp) == (struct node_t *)0)
65 return ((struct node_t *)0);
66 while ((cmp = (*compar)(key, (*rootp)->key)) != 0) {
67 p = *rootp;
68 rootp = (cmp < 0) ?
69 &(*rootp)->left : /* follow left branch */
70 &(*rootp)->right; /* follow right branch */
71 if (*rootp == (struct node_t *)0)
72 return ((void *)0); /* key not found */
73 }
74 r = (*rootp)->right; /* D1: */
75 if ((q = (*rootp)->left) == (struct node_t *)0) /* Left (struct node_t *)0? */
76 q = r;
77 else if (r != (struct node_t *)0) { /* Right link is null? */
78 if (r->left == (struct node_t *)0) { /* D2: Find successor */
79 r->left = q;
80 q = r;
81 } else { /* D3: Find (struct node_t *)0 link */
82 for (q = r->left; q->left != (struct node_t *)0; q = r->left)
83 r = q;
84 r->left = q->right;
85 q->left = (*rootp)->left;
86 q->right = (*rootp)->right;
87 }
88 }
89 if (p == *rootp)
90 p = q;
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(node *root, void (*action)(const void *, VISIT, int), int level)
99{
100 if (root->left == (struct node_t *)0 && root->right == (struct node_t *)0)
101 (*action)(root, leaf, level);
102 else {
103 (*action)(root, preorder, level);
104 if (root->left != (struct node_t *)0)
105 trecurse(root->left, action, level + 1);
106 (*action)(root, postorder, level);
107 if (root->right != (struct node_t *)0)
108 trecurse(root->right, action, level + 1);
109 (*action)(root, endorder, level);
110 }
111}
112
113/* Walk the nodes of a tree */
114void
115twalk(const void *vroot, void (*action)(const void *, VISIT, int))
116{
117 node *root = (node *)vroot;
118
119 if (root != (node *)0 && action != (void (*)(const void *, VISIT, int))0)
120 trecurse(root, action, 0);
121}