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.inc73
-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.c78
-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.c209
-rw-r--r--src/lib/libc/stdlib/atexit.h51
-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/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.c105
-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.c59
-rw-r--r--src/lib/libc/stdlib/gcvt.c111
-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.3371
-rw-r--r--src/lib/libc/stdlib/getopt_long.3464
-rw-r--r--src/lib/libc/stdlib/getopt_long.c517
-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.3184
-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.c38
-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.3456
-rw-r--r--src/lib/libc/stdlib/malloc.c1398
-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.3129
-rw-r--r--src/lib/libc/stdlib/strtod.c2459
-rw-r--r--src/lib/libc/stdlib/strtof.c39
-rw-r--r--src/lib/libc/stdlib/strtoimax.c140
-rw-r--r--src/lib/libc/stdlib/strtol.3264
-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.3248
-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.3104
-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, 15139 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..09db4ce793
--- /dev/null
+++ b/src/lib/libc/stdlib/Makefile.inc
@@ -0,0 +1,73 @@
1# $OpenBSD: Makefile.inc,v 1.39 2008/08/22 17:14:56 otto 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 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 strtof.c strtol.c \
11 strtoll.c 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+=strtod.3 strtof.3
68MLINKS+=strtol.3 strtoll.3 strtol.3 strtoq.3 strtol.3 strtoimax.3
69MLINKS+=strtoul.3 strtoull.3 strtoul.3 strtouq.3 strtoul.3 strtoumax.3
70MLINKS+=tsearch.3 tfind.3
71MLINKS+=tsearch.3 tdelete.3
72MLINKS+=tsearch.3 twalk.3
73MLINKS+=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..6eec5ce3b3
--- /dev/null
+++ b/src/lib/libc/stdlib/a64l.3
@@ -0,0 +1,133 @@
1.\" $OpenBSD: a64l.3,v 1.10 2007/05/31 19:19:31 jmc 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 $Mdocdate: May 31 2007 $
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..4ec85882b2
--- /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.8 2007/05/31 19:19:31 jmc Exp $
33.\"
34.Dd $Mdocdate: May 31 2007 $
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..244e3b28aa
--- /dev/null
+++ b/src/lib/libc/stdlib/abort.c
@@ -0,0 +1,78 @@
1/* $OpenBSD: abort.c,v 1.15 2007/09/03 14:40:16 millert 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 /* the cleanup routine lives in fns[0] on the last page */
58 while (p != NULL && p->next != NULL)
59 p = p->next;
60 /* the check for fn_dso == NULL is mostly paranoia */
61 if (p != NULL && p->fns[0].fn_dso == NULL &&
62 p->fns[0].fn_ptr.std_func != NULL) {
63 cleanup_called = 1;
64 (*p->fns[0].fn_ptr.std_func)();
65 }
66 }
67
68 (void)kill(getpid(), SIGABRT);
69
70 /*
71 * if SIGABRT ignored, or caught and the handler returns, do
72 * it again, only harder.
73 */
74 (void)signal(SIGABRT, SIG_DFL);
75 (void)_thread_sys_sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
76 (void)kill(getpid(), SIGABRT);
77 _exit(1);
78}
diff --git a/src/lib/libc/stdlib/abs.3 b/src/lib/libc/stdlib/abs.3
new file mode 100644
index 0000000000..c4135f9c84
--- /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.8 2007/05/31 19:19:31 jmc Exp $
33.\"
34.Dd $Mdocdate: May 31 2007 $
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..d7fddb04c2
--- /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.11 2007/05/31 19:19:31 jmc Exp $
29.\"
30.Dd $Mdocdate: May 31 2007 $
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..0615feabb1
--- /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.8 2007/05/31 19:19:31 jmc Exp $
33.\"
34.Dd $Mdocdate: May 31 2007 $
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..4d28fb5ef6
--- /dev/null
+++ b/src/lib/libc/stdlib/atexit.c
@@ -0,0 +1,209 @@
1/* $OpenBSD: atexit.c,v 1.14 2007/09/05 20:47:47 chl 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 <string.h>
36#include <unistd.h>
37#include "atexit.h"
38#include "thread_private.h"
39
40int __atexit_invalid = 1;
41struct atexit *__atexit;
42
43/*
44 * Function pointers are stored in a linked list of pages. The list
45 * is initially empty, and pages are allocated on demand. The first
46 * function pointer in the first allocated page (the last one in
47 * the linked list) is reserved for the cleanup function.
48 *
49 * Outside the following functions, all pages are mprotect()'ed
50 * to prevent unintentional/malicious corruption.
51 */
52
53/*
54 * Register a function to be performed at exit or when a shared object
55 * with the given dso handle is unloaded dynamically. Also used as
56 * the backend for atexit(). For more info on this API, see:
57 *
58 * http://www.codesourcery.com/cxx-abi/abi.html#dso-dtor
59 */
60int
61__cxa_atexit(void (*func)(void *), void *arg, void *dso)
62{
63 struct atexit *p = __atexit;
64 struct atexit_fn *fnp;
65 int pgsize = getpagesize();
66 int ret = -1;
67
68 if (pgsize < sizeof(*p))
69 return (-1);
70 _ATEXIT_LOCK();
71 p = __atexit;
72 if (p != NULL) {
73 if (p->ind + 1 >= p->max)
74 p = NULL;
75 else if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
76 goto unlock;
77 }
78 if (p == NULL) {
79 p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
80 MAP_ANON | MAP_PRIVATE, -1, 0);
81 if (p == MAP_FAILED)
82 goto unlock;
83 if (__atexit == NULL) {
84 memset(&p->fns[0], 0, sizeof(p->fns[0]));
85 p->ind = 1;
86 } else
87 p->ind = 0;
88 p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
89 sizeof(p->fns[0]);
90 p->next = __atexit;
91 __atexit = p;
92 if (__atexit_invalid)
93 __atexit_invalid = 0;
94 }
95 fnp = &p->fns[p->ind++];
96 fnp->fn_ptr.cxa_func = func;
97 fnp->fn_arg = arg;
98 fnp->fn_dso = dso;
99 if (mprotect(p, pgsize, PROT_READ))
100 goto unlock;
101 ret = 0;
102unlock:
103 _ATEXIT_UNLOCK();
104 return (ret);
105}
106
107/*
108 * Register a function to be performed at exit.
109 */
110int
111atexit(void (*func)(void))
112{
113 return (__cxa_atexit((void (*)(void *))func, NULL, NULL));
114}
115
116/*
117 * Call all handlers registered with __cxa_atexit() for the shared
118 * object owning 'dso'.
119 * Note: if 'dso' is NULL, then all remaining handlers are called.
120 */
121void
122__cxa_finalize(void *dso)
123{
124 struct atexit *p, *q;
125 struct atexit_fn fn;
126 int n, pgsize = getpagesize();
127 static int call_depth;
128
129 if (__atexit_invalid)
130 return;
131
132 call_depth++;
133
134 for (p = __atexit; p != NULL; p = p->next) {
135 for (n = p->ind; --n >= 0;) {
136 if (p->fns[n].fn_ptr.cxa_func == NULL)
137 continue; /* already called */
138 if (dso != NULL && dso != p->fns[n].fn_dso)
139 continue; /* wrong DSO */
140
141 /*
142 * Mark handler as having been already called to avoid
143 * dupes and loops, then call the appropriate function.
144 */
145 fn = p->fns[n];
146 if (mprotect(p, pgsize, PROT_READ | PROT_WRITE) == 0) {
147 p->fns[n].fn_ptr.cxa_func = NULL;
148 mprotect(p, pgsize, PROT_READ);
149 }
150 if (dso != NULL)
151 (*fn.fn_ptr.cxa_func)(fn.fn_arg);
152 else
153 (*fn.fn_ptr.std_func)();
154 }
155 }
156
157 /*
158 * If called via exit(), unmap the pages since we have now run
159 * all the handlers. We defer this until calldepth == 0 so that
160 * we don't unmap things prematurely if called recursively.
161 */
162 if (dso == NULL && --call_depth == 0) {
163 for (p = __atexit; p != NULL; ) {
164 q = p;
165 p = p->next;
166 munmap(q, pgsize);
167 }
168 __atexit = NULL;
169 }
170}
171
172/*
173 * Register the cleanup function
174 */
175void
176__atexit_register_cleanup(void (*func)(void))
177{
178 struct atexit *p;
179 int pgsize = getpagesize();
180
181 if (pgsize < sizeof(*p))
182 return;
183 _ATEXIT_LOCK();
184 p = __atexit;
185 while (p != NULL && p->next != NULL)
186 p = p->next;
187 if (p == NULL) {
188 p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
189 MAP_ANON | MAP_PRIVATE, -1, 0);
190 if (p == MAP_FAILED)
191 goto unlock;
192 p->ind = 1;
193 p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
194 sizeof(p->fns[0]);
195 p->next = NULL;
196 __atexit = p;
197 if (__atexit_invalid)
198 __atexit_invalid = 0;
199 } else {
200 if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
201 goto unlock;
202 }
203 p->fns[0].fn_ptr.std_func = func;
204 p->fns[0].fn_arg = NULL;
205 p->fns[0].fn_dso = NULL;
206 mprotect(p, pgsize, PROT_READ);
207unlock:
208 _ATEXIT_UNLOCK();
209}
diff --git a/src/lib/libc/stdlib/atexit.h b/src/lib/libc/stdlib/atexit.h
new file mode 100644
index 0000000000..1b23565dd0
--- /dev/null
+++ b/src/lib/libc/stdlib/atexit.h
@@ -0,0 +1,51 @@
1/* $OpenBSD: atexit.h,v 1.7 2007/09/03 14:40:16 millert 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 struct atexit_fn {
38 union {
39 void (*std_func)(void);
40 void (*cxa_func)(void *);
41 } fn_ptr;
42 void *fn_arg; /* argument for CXA callback */
43 void *fn_dso; /* shared module handle */
44 } fns[1]; /* the table itself */
45};
46
47extern int __atexit_invalid;
48extern struct atexit *__atexit; /* points to head of LIFO stack */
49
50int __cxa_atexit(void (*)(void *), void *, void *);
51void __cxa_finalize(void *);
diff --git a/src/lib/libc/stdlib/atof.3 b/src/lib/libc/stdlib/atof.3
new file mode 100644
index 0000000000..2538d0c879
--- /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.5 2007/05/31 19:19:31 jmc Exp $
33.\"
34.Dd $Mdocdate: May 31 2007 $
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..0c6b62b25f
--- /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.9 2007/05/31 19:19:31 jmc Exp $
33.\"
34.Dd $Mdocdate: May 31 2007 $
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..3c5551182d
--- /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.7 2007/05/31 19:19:31 jmc Exp $
33.\"
34.Dd $Mdocdate: May 31 2007 $
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..608a61f4ce
--- /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.5 2007/05/31 19:19:31 jmc Exp $
33.\"
34.Dd $Mdocdate: May 31 2007 $
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..4877a1023e
--- /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.7 2007/05/31 19:19:31 jmc Exp $
33.\"
34.Dd $Mdocdate: May 31 2007 $
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/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..4a48ab1ea4
--- /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.9 2007/05/31 19:19:31 jmc Exp $
31.\"
32.Dd $Mdocdate: May 31 2007 $
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..0717a2c02a
--- /dev/null
+++ b/src/lib/libc/stdlib/ecvt.3
@@ -0,0 +1,165 @@
1.\" $OpenBSD: ecvt.3,v 1.8 2007/05/31 19:19:31 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 $Mdocdate: May 31 2007 $
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..719370a8f3
--- /dev/null
+++ b/src/lib/libc/stdlib/ecvt.c
@@ -0,0 +1,105 @@
1/* $OpenBSD: ecvt.c,v 1.6 2006/10/29 18:45:56 deraadt 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 **);
28extern void __freedtoa(char *);
29static char *__cvt(double, int, int *, int *, int, int);
30
31static char *
32__cvt(double value, int ndigit, int *decpt, int *sign, int fmode, int pad)
33{
34 static char *s;
35 char *p, *rve, c;
36 size_t siz;
37
38 if (ndigit == 0) {
39 *sign = value < 0.0;
40 *decpt = 0;
41 return ("");
42 }
43
44 if (s) {
45 free(s);
46 s = NULL;
47 }
48
49 if (ndigit < 0)
50 siz = -ndigit + 1;
51 else
52 siz = ndigit + 1;
53
54
55 /* __dtoa() doesn't allocate space for 0 so we do it by hand */
56 if (value == 0.0) {
57 *decpt = 1 - fmode; /* 1 for 'e', 0 for 'f' */
58 *sign = 0;
59 if ((rve = s = (char *)malloc(siz)) == NULL)
60 return(NULL);
61 *rve++ = '0';
62 *rve = '\0';
63 } else {
64 p = __dtoa(value, fmode + 2, ndigit, decpt, sign, &rve);
65 if (*decpt == 9999) {
66 /* Infinity or Nan, convert to inf or nan like printf */
67 *decpt = 0;
68 c = *p;
69 __freedtoa(p);
70 return(c == 'I' ? "inf" : "nan");
71 }
72 /* Make a local copy and adjust rve to be in terms of s */
73 if (pad && fmode)
74 siz += *decpt;
75 if ((s = (char *)malloc(siz)) == NULL) {
76 __freedtoa(p);
77 return(NULL);
78 }
79 (void) strlcpy(s, p, siz);
80 rve = s + (rve - p);
81 __freedtoa(p);
82 }
83
84 /* Add trailing zeros */
85 if (pad) {
86 siz -= rve - s;
87 while (--siz)
88 *rve++ = '0';
89 *rve = '\0';
90 }
91
92 return(s);
93}
94
95char *
96ecvt(double value, int ndigit, int *decpt, int *sign)
97{
98 return(__cvt(value, ndigit, decpt, sign, 0, 1));
99}
100
101char *
102fcvt(double value, int ndigit, int *decpt, int *sign)
103{
104 return(__cvt(value, ndigit, decpt, sign, 1, 1));
105}
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..45eae80a08
--- /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.11 2007/05/31 19:19:31 jmc Exp $
33.\"
34.Dd $Mdocdate: May 31 2007 $
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..83fe3d2de5
--- /dev/null
+++ b/src/lib/libc/stdlib/exit.c
@@ -0,0 +1,59 @@
1/* $OpenBSD: exit.c,v 1.12 2007/09/03 14:40:16 millert 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 /*
54 * Call functions registered by atexit() or _cxa_atexit()
55 * (including the stdio cleanup routine) and then _exit().
56 */
57 __cxa_finalize(NULL);
58 _exit(status);
59}
diff --git a/src/lib/libc/stdlib/gcvt.c b/src/lib/libc/stdlib/gcvt.c
new file mode 100644
index 0000000000..c24157e465
--- /dev/null
+++ b/src/lib/libc/stdlib/gcvt.c
@@ -0,0 +1,111 @@
1/* $OpenBSD: gcvt.c,v 1.10 2006/10/29 18:45:56 deraadt 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 **);
29extern void __freedtoa(char *);
30
31char *
32gcvt(double value, int ndigit, char *buf)
33{
34 char *digits, *dst, *src;
35 int i, decpt, sign;
36 struct lconv *lconv;
37
38 lconv = localeconv();
39 if (ndigit == 0) {
40 buf[0] = '\0';
41 return (buf);
42 }
43
44 digits = __dtoa(value, 2, ndigit, &decpt, &sign, NULL);
45 if (decpt == 9999) {
46 /*
47 * Infinity or NaN, convert to inf or nan with sign.
48 * We assume the buffer is at least ndigit long.
49 */
50 snprintf(buf, ndigit + 1, "%s%s", sign ? "-" : "",
51 *digits == 'I' ? "inf" : "nan");
52 __freedtoa(digits);
53 return (buf);
54 }
55
56 dst = buf;
57 if (sign)
58 *dst++ = '-';
59
60 if (decpt < 0 || decpt > ndigit) {
61 /* exponential format (e.g. 1.2345e+13) */
62 if (--decpt < 0) {
63 sign = 1;
64 decpt = -decpt;
65 } else
66 sign = 0;
67 src = digits;
68 *dst++ = *src++;
69 *dst++ = *lconv->decimal_point;
70 while (*src != '\0')
71 *dst++ = *src++;
72 *dst++ = 'e';
73 if (sign)
74 *dst++ = '-';
75 else
76 *dst++ = '+';
77 if (decpt < 10) {
78 *dst++ = '0';
79 *dst++ = '0' + decpt;
80 *dst = '\0';
81 } else {
82 /* XXX - optimize */
83 for (sign = decpt, i = 0; (sign /= 10) != 0; i++)
84 continue;
85 dst[i + 1] = '\0';
86 while (decpt != 0) {
87 dst[i--] = '0' + decpt % 10;
88 decpt /= 10;
89 }
90 }
91 } else {
92 /* standard format */
93 for (i = 0, src = digits; i < decpt; i++) {
94 if (*src != '\0')
95 *dst++ = *src++;
96 else
97 *dst++ = '0';
98 }
99 if (*src != '\0') {
100 if (src == digits)
101 *dst++ = '0'; /* zero before decimal point */
102 *dst++ = *lconv->decimal_point;
103 for (i = decpt; digits[i] != '\0'; i++) {
104 *dst++ = digits[i];
105 }
106 }
107 *dst = '\0';
108 }
109 __freedtoa(digits);
110 return (buf);
111}
diff --git a/src/lib/libc/stdlib/getenv.3 b/src/lib/libc/stdlib/getenv.3
new file mode 100644
index 0000000000..1d8546997f
--- /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.12 2007/05/31 19:19:31 jmc Exp $
33.\"
34.Dd $Mdocdate: May 31 2007 $
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..06167cb7d6
--- /dev/null
+++ b/src/lib/libc/stdlib/getopt.3
@@ -0,0 +1,371 @@
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.40 2007/05/31 19:19:31 jmc Exp $
29.\"
30.Dd $Mdocdate: May 31 2007 $
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
303Historic
304.Bx
305versions of
306.Fn getopt
307set
308.Fa optopt
309to the last option character processed.
310However, this conflicts with
311.St -p1003.1
312which stipulates that
313.Fa optopt
314be set to the last character that caused an error.
315.Sh HISTORY
316The
317.Fn getopt
318function appeared in
319.Bx 4.3 .
320.Sh BUGS
321The
322.Fn getopt
323function was once specified to return
324.Dv EOF
325instead of \-1.
326This was changed by
327.St -p1003.2-92
328to decouple
329.Fn getopt
330from
331.Aq Pa stdio.h .
332.Pp
333It is possible to handle digits as option letters.
334This allows
335.Fn getopt
336to be used with programs that expect a number
337.Pq Dq Li \-3
338as an option.
339This practice is wrong, and should not be used in any current development.
340It is provided for backward compatibility
341.Em only .
342The following code fragment works in most cases and can handle mixed
343number and letter arguments.
344.Bd -literal -offset indent
345int aflag = 0, bflag = 0, ch, lastch = '\e0';
346int length = -1, newarg = 1, prevoptind = 1;
347
348while ((ch = getopt(argc, argv, "0123456789ab")) != -1) {
349 switch (ch) {
350 case '0': case '1': case '2': case '3': case '4':
351 case '5': case '6': case '7': case '8': case '9':
352 if (newarg || !isdigit(lastch))
353 length = 0;
354 else if (length > INT_MAX / 10)
355 usage();
356 length = (length * 10) + (ch - '0');
357 break;
358 case 'a':
359 aflag = 1;
360 break;
361 case 'b':
362 bflag = 1;
363 break;
364 default:
365 usage();
366 }
367 lastch = ch;
368 newarg = optind != prevoptind;
369 prevoptind = optind;
370}
371.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..2bab963734
--- /dev/null
+++ b/src/lib/libc/stdlib/getopt_long.3
@@ -0,0 +1,464 @@
1.\" $OpenBSD: getopt_long.3,v 1.15 2007/07/03 12:06:07 jmc Exp $
2.\" $NetBSD: getopt_long.3,v 1.11 2002/10/02 10:54:19 wiz Exp $
3.\"
4.\" Copyright (c) 1988, 1991, 1993
5.\" The Regents of the University of California. All rights reserved.
6.\"
7.\" Redistribution and use in source and binary forms, with or without
8.\" modification, are permitted provided that the following conditions
9.\" are met:
10.\" 1. Redistributions of source code must retain the above copyright
11.\" notice, this list of conditions and the following disclaimer.
12.\" 2. Redistributions in binary form must reproduce the above copyright
13.\" notice, this list of conditions and the following disclaimer in the
14.\" documentation and/or other materials provided with the distribution.
15.\" 3. Neither the name of the University nor the names of its contributors
16.\" may be used to endorse or promote products derived from this software
17.\" without specific prior written permission.
18.\"
19.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29.\" SUCH DAMAGE.
30.\"
31.\" @(#)getopt.3 8.5 (Berkeley) 4/27/95
32.\"
33.Dd $Mdocdate: July 3 2007 $
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
96Abbreviated long option names are accepted when
97.Fn getopt_long
98processes long options if the abbreviation is unique.
99An exact match is always preferred for a defined long option.
100.Pp
101The
102.Fn getopt_long
103call requires a structure to be initialized describing the long
104options.
105The structure is:
106.Bd -literal -offset indent
107struct option {
108 char *name;
109 int has_arg;
110 int *flag;
111 int val;
112};
113.Ed
114.Pp
115The
116.Fa name
117field should contain the option name without the leading double dash.
118.Pp
119The
120.Fa has_arg
121field should be one of:
122.Pp
123.Bl -tag -width "optional_argument" -compact -offset indent
124.It Dv no_argument
125no argument to the option is expected.
126.It Dv required_argument
127an argument to the option is required.
128.It Dv optional_argument
129an argument to the option may be presented.
130.El
131.Pp
132If
133.Fa flag
134is not
135.Dv NULL ,
136then the integer pointed to by it will be set to the value in the
137.Fa val
138field.
139If the
140.Fa flag
141field is
142.Dv NULL ,
143then the
144.Fa val
145field will be returned.
146Setting
147.Fa flag
148to
149.Dv NULL
150and setting
151.Fa val
152to the corresponding short option will make this function act just
153like
154.Xr getopt 3 .
155.Pp
156If the
157.Fa longindex
158field is not
159.Dv NULL ,
160then the integer pointed to by it will be set to the index of the long
161option relative to
162.Fa longopts .
163.Pp
164The last element of the
165.Fa longopts
166array has to be filled with zeroes.
167.Pp
168The
169.Fn getopt_long_only
170function behaves identically to
171.Fn getopt_long
172with the exception that long options may start with
173.Sq -
174in addition to
175.Sq -- .
176If an option starting with
177.Sq -
178does not match a long option but does match a single-character option,
179the single-character option is returned.
180.Sh RETURN VALUES
181If the
182.Fa flag
183field in
184.Li struct option
185is
186.Dv NULL ,
187.Fn getopt_long
188and
189.Fn getopt_long_only
190return the value specified in the
191.Fa val
192field, which is usually just the corresponding short option.
193If
194.Fa flag
195is not
196.Dv NULL ,
197these functions return 0 and store
198.Fa val
199in the location pointed to by
200.Fa flag .
201These functions return
202.Sq \:
203if there was a missing option argument,
204.Sq \&?
205if the user specified an unknown or ambiguous option, and
206\-1 when the argument list has been exhausted.
207.Sh EXAMPLES
208.Bd -literal
209int bflag, ch, fd;
210int daggerset;
211
212/* options descriptor */
213static struct option longopts[] = {
214 { "buffy", no_argument, NULL, 'b' },
215 { "fluoride", required_argument, NULL, 'f' },
216 { "daggerset", no_argument, &daggerset, 1 },
217 { NULL, 0, NULL, 0 }
218};
219
220bflag = 0;
221while ((ch = getopt_long(argc, argv, "bf:", longopts, NULL)) != -1)
222 switch (ch) {
223 case 'b':
224 bflag = 1;
225 break;
226 case 'f':
227 if ((fd = open(optarg, O_RDONLY, 0)) == -1)
228 err(1, "unable to open %s", optarg);
229 break;
230 case 0:
231 if (daggerset)
232 fprintf(stderr, "Buffy will use her dagger to "
233 "apply fluoride to dracula's teeth\en");
234 break;
235 default:
236 usage();
237 /* NOTREACHED */
238 }
239argc -= optind;
240argv += optind;
241.Ed
242.Sh IMPLEMENTATION DIFFERENCES
243This section describes differences to the GNU implementation
244found in glibc-2.1.3:
245.Bl -bullet
246.It
247handling of
248.Ql -
249as the first character of the option string in the presence of the
250environment variable
251.Ev POSIXLY_CORRECT :
252.Bl -tag -width "OpenBSD"
253.It GNU
254ignores
255.Ev POSIXLY_CORRECT
256and returns non-options as arguments to option
257.Ql \e1 .
258.It OpenBSD
259honors
260.Ev POSIXLY_CORRECT
261and stops at the first non-option.
262.El
263.It
264handling of
265.Ql -
266within the option string (not the first character):
267.Bl -tag -width "OpenBSD"
268.It GNU
269treats a
270.Ql -
271on the command line as a non-argument.
272.It OpenBSD
273a
274.Ql -
275within the option string matches a
276.Ql -
277(single dash) on the command line.
278This functionality is provided for backward compatibility with
279programs, such as
280.Xr su 1 ,
281that use
282.Ql -
283as an option flag.
284This practice is wrong, and should not be used in any current development.
285.El
286.It
287handling of
288.Ql ::
289in the option string in the presence of
290.Ev POSIXLY_CORRECT :
291.Bl -tag -width "OpenBSD"
292.It Both
293GNU and
294.Ox
295ignore
296.Ev POSIXLY_CORRECT
297here and take
298.Ql ::
299to mean the preceding option takes an optional argument.
300.El
301.It
302return value in case of missing argument if first character
303(after
304.Ql +
305or
306.Ql - )
307in the option string is not
308.Ql \&: :
309.Bl -tag -width "OpenBSD"
310.It GNU
311returns
312.Ql \&?
313.It OpenBSD
314returns
315.Ql \&:
316(since
317.Ox Ns 's
318.Xr getopt 3
319does).
320.El
321.It
322handling of
323.Ql --a
324in
325.Xr getopt 3 :
326.Bl -tag -width "OpenBSD"
327.It GNU
328parses this as option
329.Ql - ,
330option
331.Ql a .
332.It OpenBSD
333parses this as
334.Ql -- ,
335and returns \-1 (ignoring the
336.Ql a )
337(because the original
338.Fn getopt
339did.)
340.El
341.It
342setting of
343.Va optopt
344for long options with
345.Va flag
346.No non- Ns Dv NULL :
347.Bl -tag -width "OpenBSD"
348.It GNU
349sets
350.Va optopt
351to
352.Va val .
353.It OpenBSD
354sets
355.Va optopt
356to 0 (since
357.Va val
358would never be returned).
359.El
360.It
361handling of
362.Ql -W
363with
364.Ql W;
365in the option string in
366.Xr getopt 3
367(not
368.Fn getopt_long ) :
369.Bl -tag -width "OpenBSD"
370.It GNU
371causes a segmentation fault.
372.It OpenBSD
373no special handling is done;
374.Ql W;
375is interpreted as two separate options, neither of which take an argument.
376.El
377.It
378setting of
379.Va optarg
380for long options without an argument that are invoked via
381.Ql -W
382(with
383.Ql W;
384in the option string):
385.Bl -tag -width "OpenBSD"
386.It GNU
387sets
388.Va optarg
389to the option name (the argument of
390.Ql -W ) .
391.It OpenBSD
392sets
393.Va optarg
394to
395.Dv NULL
396(the argument of the long option).
397.El
398.It
399handling of
400.Ql -W
401with an argument that is not (a prefix to) a known long option
402(with
403.Ql W;
404in the option string):
405.Bl -tag -width "OpenBSD"
406.It GNU
407returns
408.Ql -W
409with
410.Va optarg
411set to the unknown option.
412.It OpenBSD
413treats this as an error (unknown option) and returns
414.Ql \&?
415with
416.Va optopt
417set to 0 and
418.Va optarg
419set to
420.Dv NULL
421(as GNU's man page documents).
422.El
423.It
424The error messages are different.
425.It
426.Ox
427does not permute the argument vector at the same points in
428the calling sequence as GNU does.
429The aspects normally used by the caller
430(ordering after \-1 is returned, value of
431.Va optind
432relative to current positions) are the same, though.
433(We do fewer variable swaps.)
434.El
435.Sh ENVIRONMENT
436.Bl -tag -width Ev
437.It Ev POSIXLY_CORRECT
438If set, option processing stops when the first non-option is found and
439a leading
440.Sq -
441or
442.Sq +
443in the
444.Ar optstring
445is ignored.
446.El
447.Sh SEE ALSO
448.Xr getopt 3
449.Sh HISTORY
450The
451.Fn getopt_long
452and
453.Fn getopt_long_only
454functions first appeared in GNU libiberty.
455This implementation first appeared in
456.Ox 3.3 .
457.Sh BUGS
458The
459.Ar argv
460argument is not really
461.Dv const
462as its elements may be permuted (unless
463.Ev POSIXLY_CORRECT
464is 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..73d97c0ed3
--- /dev/null
+++ b/src/lib/libc/stdlib/getopt_long.c
@@ -0,0 +1,517 @@
1/* $OpenBSD: getopt_long.c,v 1.23 2007/10/31 12:34:57 chl 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 *
39 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
40 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
41 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
43 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
44 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
45 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
46 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
47 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
49 * POSSIBILITY OF SUCH DAMAGE.
50 */
51
52#include <err.h>
53#include <errno.h>
54#include <getopt.h>
55#include <stdlib.h>
56#include <string.h>
57
58#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */
59
60#ifdef REPLACE_GETOPT
61int opterr = 1; /* if error message should be printed */
62int optind = 1; /* index into parent argv vector */
63int optopt = '?'; /* character checked for validity */
64int optreset; /* reset getopt */
65char *optarg; /* argument associated with option */
66#endif
67
68#define PRINT_ERROR ((opterr) && (*options != ':'))
69
70#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
71#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
72#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
73
74/* return values */
75#define BADCH (int)'?'
76#define BADARG ((*options == ':') ? (int)':' : (int)'?')
77#define INORDER (int)1
78
79#define EMSG ""
80
81static int getopt_internal(int, char * const *, const char *,
82 const struct option *, int *, int);
83static int parse_long_options(char * const *, const char *,
84 const struct option *, int *, int);
85static int gcd(int, int);
86static void permute_args(int, int, int, char * const *);
87
88static char *place = EMSG; /* option letter processing */
89
90/* XXX: set optreset to 1 rather than these two */
91static int nonopt_start = -1; /* first non option argument (for permute) */
92static int nonopt_end = -1; /* first option after non options (for permute) */
93
94/* Error messages */
95static const char recargchar[] = "option requires an argument -- %c";
96static const char recargstring[] = "option requires an argument -- %s";
97static const char ambig[] = "ambiguous option -- %.*s";
98static const char noarg[] = "option doesn't take an argument -- %.*s";
99static const char illoptchar[] = "unknown option -- %c";
100static const char illoptstring[] = "unknown option -- %s";
101
102/*
103 * Compute the greatest common divisor of a and b.
104 */
105static int
106gcd(int a, int b)
107{
108 int c;
109
110 c = a % b;
111 while (c != 0) {
112 a = b;
113 b = c;
114 c = a % b;
115 }
116
117 return (b);
118}
119
120/*
121 * Exchange the block from nonopt_start to nonopt_end with the block
122 * from nonopt_end to opt_end (keeping the same order of arguments
123 * in each block).
124 */
125static void
126permute_args(int panonopt_start, int panonopt_end, int opt_end,
127 char * const *nargv)
128{
129 int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
130 char *swap;
131
132 /*
133 * compute lengths of blocks and number and size of cycles
134 */
135 nnonopts = panonopt_end - panonopt_start;
136 nopts = opt_end - panonopt_end;
137 ncycle = gcd(nnonopts, nopts);
138 cyclelen = (opt_end - panonopt_start) / ncycle;
139
140 for (i = 0; i < ncycle; i++) {
141 cstart = panonopt_end+i;
142 pos = cstart;
143 for (j = 0; j < cyclelen; j++) {
144 if (pos >= panonopt_end)
145 pos -= nnonopts;
146 else
147 pos += nopts;
148 swap = nargv[pos];
149 /* LINTED const cast */
150 ((char **) nargv)[pos] = nargv[cstart];
151 /* LINTED const cast */
152 ((char **)nargv)[cstart] = swap;
153 }
154 }
155}
156
157/*
158 * parse_long_options --
159 * Parse long options in argc/argv argument vector.
160 * Returns -1 if short_too is set and the option does not match long_options.
161 */
162static int
163parse_long_options(char * const *nargv, const char *options,
164 const struct option *long_options, int *idx, int short_too)
165{
166 char *current_argv, *has_equal;
167 size_t current_argv_len;
168 int i, match;
169
170 current_argv = place;
171 match = -1;
172
173 optind++;
174
175 if ((has_equal = strchr(current_argv, '=')) != NULL) {
176 /* argument found (--option=arg) */
177 current_argv_len = has_equal - current_argv;
178 has_equal++;
179 } else
180 current_argv_len = strlen(current_argv);
181
182 for (i = 0; long_options[i].name; i++) {
183 /* find matching long option */
184 if (strncmp(current_argv, long_options[i].name,
185 current_argv_len))
186 continue;
187
188 if (strlen(long_options[i].name) == current_argv_len) {
189 /* exact match */
190 match = i;
191 break;
192 }
193 /*
194 * If this is a known short option, don't allow
195 * a partial match of a single character.
196 */
197 if (short_too && current_argv_len == 1)
198 continue;
199
200 if (match == -1) /* partial match */
201 match = i;
202 else {
203 /* ambiguous abbreviation */
204 if (PRINT_ERROR)
205 warnx(ambig, (int)current_argv_len,
206 current_argv);
207 optopt = 0;
208 return (BADCH);
209 }
210 }
211 if (match != -1) { /* option found */
212 if (long_options[match].has_arg == no_argument
213 && has_equal) {
214 if (PRINT_ERROR)
215 warnx(noarg, (int)current_argv_len,
216 current_argv);
217 /*
218 * XXX: GNU sets optopt to val regardless of flag
219 */
220 if (long_options[match].flag == NULL)
221 optopt = long_options[match].val;
222 else
223 optopt = 0;
224 return (BADARG);
225 }
226 if (long_options[match].has_arg == required_argument ||
227 long_options[match].has_arg == optional_argument) {
228 if (has_equal)
229 optarg = has_equal;
230 else if (long_options[match].has_arg ==
231 required_argument) {
232 /*
233 * optional argument doesn't use next nargv
234 */
235 optarg = nargv[optind++];
236 }
237 }
238 if ((long_options[match].has_arg == required_argument)
239 && (optarg == NULL)) {
240 /*
241 * Missing argument; leading ':' indicates no error
242 * should be generated.
243 */
244 if (PRINT_ERROR)
245 warnx(recargstring,
246 current_argv);
247 /*
248 * XXX: GNU sets optopt to val regardless of flag
249 */
250 if (long_options[match].flag == NULL)
251 optopt = long_options[match].val;
252 else
253 optopt = 0;
254 --optind;
255 return (BADARG);
256 }
257 } else { /* unknown option */
258 if (short_too) {
259 --optind;
260 return (-1);
261 }
262 if (PRINT_ERROR)
263 warnx(illoptstring, current_argv);
264 optopt = 0;
265 return (BADCH);
266 }
267 if (idx)
268 *idx = match;
269 if (long_options[match].flag) {
270 *long_options[match].flag = long_options[match].val;
271 return (0);
272 } else
273 return (long_options[match].val);
274}
275
276/*
277 * getopt_internal --
278 * Parse argc/argv argument vector. Called by user level routines.
279 */
280static int
281getopt_internal(int nargc, char * const *nargv, const char *options,
282 const struct option *long_options, int *idx, int flags)
283{
284 char *oli; /* option letter list index */
285 int optchar, short_too;
286 static int posixly_correct = -1;
287
288 if (options == NULL)
289 return (-1);
290
291 /*
292 * Disable GNU extensions if POSIXLY_CORRECT is set or options
293 * string begins with a '+'.
294 */
295 if (posixly_correct == -1)
296 posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
297 if (posixly_correct || *options == '+')
298 flags &= ~FLAG_PERMUTE;
299 else if (*options == '-')
300 flags |= FLAG_ALLARGS;
301 if (*options == '+' || *options == '-')
302 options++;
303
304 /*
305 * XXX Some GNU programs (like cvs) set optind to 0 instead of
306 * XXX using optreset. Work around this braindamage.
307 */
308 if (optind == 0)
309 optind = optreset = 1;
310
311 optarg = NULL;
312 if (optreset)
313 nonopt_start = nonopt_end = -1;
314start:
315 if (optreset || !*place) { /* update scanning pointer */
316 optreset = 0;
317 if (optind >= nargc) { /* end of argument vector */
318 place = EMSG;
319 if (nonopt_end != -1) {
320 /* do permutation, if we have to */
321 permute_args(nonopt_start, nonopt_end,
322 optind, nargv);
323 optind -= nonopt_end - nonopt_start;
324 }
325 else if (nonopt_start != -1) {
326 /*
327 * If we skipped non-options, set optind
328 * to the first of them.
329 */
330 optind = nonopt_start;
331 }
332 nonopt_start = nonopt_end = -1;
333 return (-1);
334 }
335 if (*(place = nargv[optind]) != '-' ||
336 (place[1] == '\0' && strchr(options, '-') == NULL)) {
337 place = EMSG; /* found non-option */
338 if (flags & FLAG_ALLARGS) {
339 /*
340 * GNU extension:
341 * return non-option as argument to option 1
342 */
343 optarg = nargv[optind++];
344 return (INORDER);
345 }
346 if (!(flags & FLAG_PERMUTE)) {
347 /*
348 * If no permutation wanted, stop parsing
349 * at first non-option.
350 */
351 return (-1);
352 }
353 /* do permutation */
354 if (nonopt_start == -1)
355 nonopt_start = optind;
356 else if (nonopt_end != -1) {
357 permute_args(nonopt_start, nonopt_end,
358 optind, nargv);
359 nonopt_start = optind -
360 (nonopt_end - nonopt_start);
361 nonopt_end = -1;
362 }
363 optind++;
364 /* process next argument */
365 goto start;
366 }
367 if (nonopt_start != -1 && nonopt_end == -1)
368 nonopt_end = optind;
369
370 /*
371 * If we have "-" do nothing, if "--" we are done.
372 */
373 if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
374 optind++;
375 place = EMSG;
376 /*
377 * We found an option (--), so if we skipped
378 * non-options, we have to permute.
379 */
380 if (nonopt_end != -1) {
381 permute_args(nonopt_start, nonopt_end,
382 optind, nargv);
383 optind -= nonopt_end - nonopt_start;
384 }
385 nonopt_start = nonopt_end = -1;
386 return (-1);
387 }
388 }
389
390 /*
391 * Check long options if:
392 * 1) we were passed some
393 * 2) the arg is not just "-"
394 * 3) either the arg starts with -- we are getopt_long_only()
395 */
396 if (long_options != NULL && place != nargv[optind] &&
397 (*place == '-' || (flags & FLAG_LONGONLY))) {
398 short_too = 0;
399 if (*place == '-')
400 place++; /* --foo long option */
401 else if (*place != ':' && strchr(options, *place) != NULL)
402 short_too = 1; /* could be short option too */
403
404 optchar = parse_long_options(nargv, options, long_options,
405 idx, short_too);
406 if (optchar != -1) {
407 place = EMSG;
408 return (optchar);
409 }
410 }
411
412 if ((optchar = (int)*place++) == (int)':' ||
413 (optchar == (int)'-' && *place != '\0') ||
414 (oli = strchr(options, optchar)) == NULL) {
415 /*
416 * If the user specified "-" and '-' isn't listed in
417 * options, return -1 (non-option) as per POSIX.
418 * Otherwise, it is an unknown option character (or ':').
419 */
420 if (optchar == (int)'-' && *place == '\0')
421 return (-1);
422 if (!*place)
423 ++optind;
424 if (PRINT_ERROR)
425 warnx(illoptchar, optchar);
426 optopt = optchar;
427 return (BADCH);
428 }
429 if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
430 /* -W long-option */
431 if (*place) /* no space */
432 /* NOTHING */;
433 else if (++optind >= nargc) { /* no arg */
434 place = EMSG;
435 if (PRINT_ERROR)
436 warnx(recargchar, optchar);
437 optopt = optchar;
438 return (BADARG);
439 } else /* white space */
440 place = nargv[optind];
441 optchar = parse_long_options(nargv, options, long_options,
442 idx, 0);
443 place = EMSG;
444 return (optchar);
445 }
446 if (*++oli != ':') { /* doesn't take argument */
447 if (!*place)
448 ++optind;
449 } else { /* takes (optional) argument */
450 optarg = NULL;
451 if (*place) /* no white space */
452 optarg = place;
453 else if (oli[1] != ':') { /* arg not optional */
454 if (++optind >= nargc) { /* no arg */
455 place = EMSG;
456 if (PRINT_ERROR)
457 warnx(recargchar, optchar);
458 optopt = optchar;
459 return (BADARG);
460 } else
461 optarg = nargv[optind];
462 }
463 place = EMSG;
464 ++optind;
465 }
466 /* dump back option letter */
467 return (optchar);
468}
469
470#ifdef REPLACE_GETOPT
471/*
472 * getopt --
473 * Parse argc/argv argument vector.
474 *
475 * [eventually this will replace the BSD getopt]
476 */
477int
478getopt(int nargc, char * const *nargv, const char *options)
479{
480
481 /*
482 * We don't pass FLAG_PERMUTE to getopt_internal() since
483 * the BSD getopt(3) (unlike GNU) has never done this.
484 *
485 * Furthermore, since many privileged programs call getopt()
486 * before dropping privileges it makes sense to keep things
487 * as simple (and bug-free) as possible.
488 */
489 return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
490}
491#endif /* REPLACE_GETOPT */
492
493/*
494 * getopt_long --
495 * Parse argc/argv argument vector.
496 */
497int
498getopt_long(int nargc, char * const *nargv, const char *options,
499 const struct option *long_options, int *idx)
500{
501
502 return (getopt_internal(nargc, nargv, options, long_options, idx,
503 FLAG_PERMUTE));
504}
505
506/*
507 * getopt_long_only --
508 * Parse argc/argv argument vector.
509 */
510int
511getopt_long_only(int nargc, char * const *nargv, const char *options,
512 const struct option *long_options, int *idx)
513{
514
515 return (getopt_internal(nargc, nargv, options, long_options, idx,
516 FLAG_PERMUTE|FLAG_LONGONLY));
517}
diff --git a/src/lib/libc/stdlib/getsubopt.3 b/src/lib/libc/stdlib/getsubopt.3
new file mode 100644
index 0000000000..9f35df703f
--- /dev/null
+++ b/src/lib/libc/stdlib/getsubopt.3
@@ -0,0 +1,145 @@
1.\" $OpenBSD: getsubopt.3,v 1.12 2007/05/31 19:19:31 jmc Exp $
2.\"
3.\" Copyright (c) 1990, 1991, 1993
4.\" The Regents of the University of California. All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution.
14.\" 3. Neither the name of the University nor the names of its contributors
15.\" may be used to endorse or promote products derived from this software
16.\" without specific prior written permission.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28.\" SUCH DAMAGE.
29.\"
30.\" @(#)getsubopt.3 8.1 (Berkeley) 6/9/93
31.\"
32.Dd $Mdocdate: May 31 2007 $
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..4ff17a087d
--- /dev/null
+++ b/src/lib/libc/stdlib/hcreate.3
@@ -0,0 +1,184 @@
1.\" $OpenBSD: hcreate.3,v 1.5 2008/06/26 05:42:05 ray 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.\"
19.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29.\" POSSIBILITY OF SUCH DAMAGE.
30.\"
31.Dd $Mdocdate: June 26 2008 $
32.Dt HCREATE 3
33.Os
34.Sh NAME
35.Nm hcreate ,
36.Nm hdestroy ,
37.Nm hsearch
38.Nd manage hash search table
39.Sh SYNOPSIS
40.In search.h
41.Ft int
42.Fn hcreate "size_t nel"
43.Ft void
44.Fn hdestroy "void"
45.Ft ENTRY *
46.Fn hsearch "ENTRY item" "ACTION action"
47.Sh DESCRIPTION
48The
49.Fn hcreate ,
50.Fn hdestroy ,
51and
52.Fn hsearch
53functions manage hash search tables.
54.Pp
55The
56.Fn hcreate
57function allocates and initializes the table.
58The
59.Fa nel
60argument specifies an estimate of the maximum number of entries to be held
61by the table.
62Unless further memory allocation fails, supplying an insufficient
63.Fa nel
64value will not result in functional harm, although a performance degradation
65may occur.
66Initialization using the
67.Fn hcreate
68function is mandatory prior to any access operations using
69.Fn hsearch .
70.Pp
71The
72.Fn hdestroy
73function destroys a table previously created using
74.Fn hcreate .
75After a call to
76.Fn hdestroy ,
77the data can no longer be accessed.
78.Pp
79The
80.Fn hsearch
81function is used to search to the hash table.
82It returns a pointer into the
83hash table indicating the address of an item.
84The
85.Fa item
86argument is of type
87.Dv ENTRY ,
88a structural type which contains the following members:
89.Pp
90.Bl -tag -compact -offset indent -width voidX*dataXX
91.It Fa char *key
92comparison key.
93.It Fa void *data
94pointer to data associated with
95.Fa key .
96.El
97.Pp
98The key comparison function used by
99.Fn hsearch
100is
101.Xr strcmp 3 .
102.Pp
103The
104.Fa action
105argument is of type
106.Dv ACTION ,
107an enumeration type which defines the following values:
108.Bl -tag -offset indent -width ENTERXX
109.It Dv ENTER
110Insert
111.Fa item
112into the hash table.
113If an existing item with the same key is found, it is not replaced.
114Note that the
115.Fa key
116and
117.Fa data
118elements of
119.Fa item
120are used directly by the new table entry.
121The storage for the
122key must not be modified during the lifetime of the hash table.
123.It Dv FIND
124Search the hash table without inserting
125.Fa item .
126.El
127.Sh RETURN VALUES
128If successful, the
129.Fn hcreate
130function returns a non-zero value.
131Otherwise, a value of 0 is returned and
132.Va errno
133is set to indicate the error.
134.Pp
135The
136.Fn hdestroy
137functions
138returns no value.
139.Pp
140If successful, the
141.Fn hsearch
142function returns a pointer to a hash table entry matching
143the provided key.
144If the action is
145.Dv FIND
146and the item was not found, or if the action is
147.Dv ENTER
148and the insertion failed,
149.Dv NULL
150is returned and
151.Va errno
152is set to indicate the error.
153If the action is
154.Dv ENTER
155and an entry already existed in the table matching the given
156key, the existing entry is returned and is not replaced.
157.Sh ERRORS
158The
159.Fn hcreate
160and
161.Fn hsearch
162functions will fail if:
163.Bl -tag -width Er
164.It Bq Er ENOMEM
165Insufficient memory is available.
166.El
167.Sh SEE ALSO
168.Xr bsearch 3 ,
169.Xr lsearch 3 ,
170.Xr malloc 3 ,
171.Xr strcmp 3
172.Sh STANDARDS
173These functions conform to
174.St -p1003.1-2004 .
175.Sh HISTORY
176The
177.Fn hcreate ,
178.Fn hdestroy
179and
180.Fn hsearch
181functions first appeared in
182.At V .
183.Sh BUGS
184The 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..094f32c173
--- /dev/null
+++ b/src/lib/libc/stdlib/hcreate.c
@@ -0,0 +1,191 @@
1/* $OpenBSD: hcreate.c,v 1.4 2007/09/02 15:19:17 deraadt 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 = calloc(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..10933e0a66
--- /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.3 2007/05/31 19:19:31 jmc Exp $
33.\"
34.Dd $Mdocdate: May 31 2007 $
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 intmax_t
43.Fn imaxabs "intmax_t 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..c4dee627aa
--- /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.3 2007/05/31 19:19:31 jmc Exp $
33.\"
34.Dd $Mdocdate: May 31 2007 $
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..dcb2b0d158
--- /dev/null
+++ b/src/lib/libc/stdlib/insque.3
@@ -0,0 +1,106 @@
1.\" $OpenBSD: insque.3,v 1.7 2007/05/31 19:19:31 jmc Exp $
2.\" Copyright (c) 1993 John Brezak
3.\" All rights reserved.
4.\"
5.\" Redistribution and use in source and binary forms, with or without
6.\" modification, are permitted provided that the following conditions
7.\" are met:
8.\" 1. Redistributions of source code must retain the above copyright
9.\" notice, this list of conditions and the following disclaimer.
10.\" 2. Redistributions in binary form must reproduce the above copyright
11.\" notice, this list of conditions and the following disclaimer in the
12.\" documentation and/or other materials provided with the distribution.
13.\" 3. The name of the author may be used to endorse or promote products
14.\" derived from this software without specific prior written permission.
15.\"
16.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND
17.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
20.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26.\" SUCH DAMAGE.
27.\"
28.\"
29.Dd $Mdocdate: May 31 2007 $
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..21c134fe5d
--- /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.9 2007/05/31 19:19:31 jmc Exp $
33.\"
34.Dd $Mdocdate: May 31 2007 $
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..9627776899
--- /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.9 2007/05/31 19:19:31 jmc Exp $
33.\"
34.Dd $Mdocdate: May 31 2007 $
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..fc2cd8261c
--- /dev/null
+++ b/src/lib/libc/stdlib/llabs.c
@@ -0,0 +1,38 @@
1/* $OpenBSD: llabs.c,v 1.3 2007/01/08 19:39:25 deraadt 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 <stdlib.h>
33
34long long
35llabs(long long j)
36{
37 return (j < 0 ? -j : j);
38}
diff --git a/src/lib/libc/stdlib/lldiv.3 b/src/lib/libc/stdlib/lldiv.3
new file mode 100644
index 0000000000..a5be188ba2
--- /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.2 2007/05/31 19:19:31 jmc Exp $
33.\"
34.Dd $Mdocdate: May 31 2007 $
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..e13ef4ec74
--- /dev/null
+++ b/src/lib/libc/stdlib/lsearch.3
@@ -0,0 +1,108 @@
1.\" $OpenBSD: lsearch.3,v 1.8 2007/05/31 19:19:31 jmc 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 $Mdocdate: May 31 2007 $
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..b9d62d04d0
--- /dev/null
+++ b/src/lib/libc/stdlib/malloc.3
@@ -0,0 +1,456 @@
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.54 2008/08/07 18:41:47 otto Exp $
34.\"
35.Dd $Mdocdate: August 7 2008 $
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 (size && num > SIZE_MAX / 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 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 either placed on a list of free pages to make it available for future
126allocation or, if required, to be returned to the kernel using
127.Xr munmap 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 when allocating; this is pronounced
248.Dq Duh .
249\&:-)
250Freed chunks are filled with 0xdf.
251.It Cm N
252Do not output warning messages when encountering possible corruption
253or bad pointers.
254.It Cm P
255.Dq Move allocations within a page.
256Allocations larger than half a page but smaller that a page
257are aligned to the end of a page to catch buffer overruns in more
258cases.
259.It Cm R
260.Dq realloc .
261Always reallocate when
262.Fn realloc
263is called, even if the initial allocation was big enough.
264This can substantially aid in compacting memory.
265.\".Pp
266.\".It Cm U
267.\".Dq utrace .
268.\"Generate entries for
269.\".Xr ktrace 1
270.\"for all operations.
271.\"Consult the source for this one.
272.It Cm X
273.Dq xmalloc .
274Rather than return failure,
275.Xr abort 3
276the program with a diagnostic message on stderr.
277It is the intention that this option be set at compile time by
278including in the source:
279.Bd -literal -offset indent
280extern char *malloc_options;
281malloc_options = "X";
282.Ed
283.Pp
284Note that this will cause code that is supposed to handle
285out-of-memory conditions gracefully to abort instead.
286.It Cm Z
287.Dq Zero .
288Fill some junk into the area allocated (see
289.Cm J ) ,
290except for the exact length the user asked for, which is zeroed.
291.It Cm <
292.Dq Half the cache size .
293Decrease the size of the free page cache by a factor of two.
294.It Cm >
295.Dq Double the cache size .
296Increase the size of the free page cache by a factor of two.
297.El
298.Pp
299So to set a systemwide reduction of cache size and coredumps on problems:
300.Li ln -s 'A<' /etc/malloc.conf
301.Pp
302The
303.Cm J
304and
305.Cm Z
306flags are mostly for testing and debugging.
307If a program changes behavior if either of these options are used,
308it is buggy.
309.Pp
310The default number of free pages cached is 64.
311.Sh RETURN VALUES
312The
313.Fn malloc
314and
315.Fn calloc
316functions return a pointer to the allocated space if successful; otherwise,
317a null pointer is returned and
318.Va errno
319is set to
320.Er ENOMEM .
321.Pp
322The
323.Fn free
324and
325.Fn cfree
326functions return no value.
327.Pp
328The
329.Fn realloc
330function returns a pointer to the (possibly moved) allocated space
331if successful; otherwise, a null pointer is returned and
332.Va errno
333is set to
334.Er ENOMEM .
335.Sh ENVIRONMENT
336.Bl -tag -width Ev
337.It Ev MALLOC_OPTIONS
338See above.
339.El
340.Sh FILES
341.Bl -tag -width "/etc/malloc.conf"
342.It Pa /etc/malloc.conf
343symbolic link to filename containing option flags
344.El
345.Sh DIAGNOSTICS
346If
347.Fn malloc ,
348.Fn calloc ,
349.Fn realloc ,
350or
351.Fn free
352detect an error or warning condition,
353a message will be printed to file descriptor
3542 (not using stdio).
355Errors will always result in the process being
356.Xr abort 3 'ed.
357If the
358.Cm A
359option has been specified, warnings will also
360.Xr abort 3
361the process.
362.Pp
363Here is a brief description of the error messages and what they mean:
364.Bl -tag -width Ds
365.It Dq out of memory
366If the
367.Cm A
368option is specified it is an error for
369.Fn malloc ,
370.Fn calloc ,
371or
372.Fn realloc
373to return
374.Dv NULL .
375.It Dq malloc init mmap failed
376This is a rather weird condition that is most likely to indicate a
377seriously overloaded system or a ulimit restriction.
378.It any other error
379.Fn malloc
380detected an internal error;
381consult sources and/or wizards.
382.El
383.Pp
384Here is a brief description of the warning messages and what they mean:
385.Bl -tag -width Ds
386.It Dq bogus pointer (double free?)
387An attempt to
388.Fn free
389or
390.Fn realloc
391an unallocated pointer was made.
392.It Dq chunk is already free
393There was an attempt to free a chunk that had already been freed.
394.It Dq modified chunk-pointer
395The pointer passed to
396.Fn free
397or
398.Fn realloc
399has been modified.
400.It Dq recursive call
401An attempt was made to call recursively into these functions, i.e., from a
402signal handler.
403This behavior is not supported.
404In particular, signal handlers should
405.Em not
406use any of the
407.Fn malloc
408functions nor utilize any other functions which may call
409.Fn malloc
410(e.g.,
411.Xr stdio 3
412routines).
413.It Dq unknown char in MALLOC_OPTIONS
414We found something we didn't understand.
415.It Dq malloc cache overflow/underflow
416The internal malloc page cache has been corrupted.
417.It Dq malloc free slot lost
418The internal malloc page cache has been corrupted.
419.It Dq guard size
420An inconsistent guard size was detected.
421.El
422.Sh SEE ALSO
423.Xr brk 2 ,
424.Xr mmap 2 ,
425.Xr munmap 2 ,
426.Xr alloca 3 ,
427.Xr getpagesize 3
428.Sh STANDARDS
429The
430.Fn malloc
431function conforms to
432.St -ansiC .
433.Sh HISTORY
434The present implementation of
435.Fn malloc
436started out as a filesystem on a drum
437attached to a 20-bit binary challenged computer built with discrete germanium
438transistors, and it has since graduated to handle primary storage rather than
439secondary.
440.Pp
441The main difference from other
442.Fn malloc
443implementations are believed to be that
444the free pages are not accessed until allocated.
445Most
446.Fn malloc
447implementations will store a data structure containing a,
448possibly double-, linked list in the free chunks of memory, used to tie
449all the free memory together.
450That is a quite suboptimal thing to do.
451Every time the free-list is traversed, all the otherwise unused, and very
452likely paged out, pages get faulted into primary memory, just to see what
453lies after them in the list.
454.Pp
455On systems which are paging, this can increase the page-faults
456of 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..be80640e81
--- /dev/null
+++ b/src/lib/libc/stdlib/malloc.c
@@ -0,0 +1,1398 @@
1/* $OpenBSD: malloc.c,v 1.98 2008/08/25 17:56:17 otto Exp $ */
2/*
3 * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
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
18/*
19 * Parts of this code, mainly the sub page sized chunk management code is
20 * derived from the malloc implementation with the following license:
21 */
22/*
23 * ----------------------------------------------------------------------------
24 * "THE BEER-WARE LICENSE" (Revision 42):
25 * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you
26 * can do whatever you want with this stuff. If we meet some day, and you think
27 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
28 * ----------------------------------------------------------------------------
29 */
30
31/* #define MALLOC_STATS */
32
33#include <sys/types.h>
34#include <sys/param.h>
35#include <sys/mman.h>
36#include <sys/uio.h>
37#include <errno.h>
38#include <stdint.h>
39#include <stdlib.h>
40#include <string.h>
41#include <stdio.h>
42#include <unistd.h>
43
44#ifdef MALLOC_STATS
45#include <fcntl.h>
46#endif
47
48#include "thread_private.h"
49
50#define MALLOC_MINSHIFT 4
51#define MALLOC_MAXSHIFT 16
52
53#if defined(__sparc__) && !defined(__sparcv9__)
54#define MALLOC_PAGESHIFT (13U)
55#else
56#define MALLOC_PAGESHIFT (PGSHIFT)
57#endif
58
59#define MALLOC_PAGESIZE (1UL << MALLOC_PAGESHIFT)
60#define MALLOC_MINSIZE (1UL << MALLOC_MINSHIFT)
61#define MALLOC_PAGEMASK (MALLOC_PAGESIZE - 1)
62#define MASK_POINTER(p) ((void *)(((uintptr_t)(p)) & ~MALLOC_PAGEMASK))
63
64#define MALLOC_MAXCHUNK (1 << (MALLOC_PAGESHIFT-1))
65#define MALLOC_MAXCACHE 256
66#define MALLOC_DELAYED_CHUNKS 16 /* should be power of 2 */
67
68#define PAGEROUND(x) (((x) + (MALLOC_PAGEMASK)) & ~MALLOC_PAGEMASK)
69
70/*
71 * What to use for Junk. This is the byte value we use to fill with
72 * when the 'J' option is enabled. Use SOME_JUNK right after alloc,
73 * and SOME_FREEJUNK right before free.
74 */
75#define SOME_JUNK 0xd0 /* as in "Duh" :-) */
76#define SOME_FREEJUNK 0xdf
77
78#define MMAP(sz) mmap(NULL, (size_t)(sz), PROT_READ | PROT_WRITE, \
79 MAP_ANON | MAP_PRIVATE, -1, (off_t) 0)
80
81struct region_info {
82 void *p; /* page; low bits used to mark chunks */
83 uintptr_t size; /* size for pages, or chunk_info pointer */
84};
85
86struct dir_info {
87 u_int32_t canary1;
88 struct region_info *r; /* region slots */
89 size_t regions_total; /* number of region slots */
90 size_t regions_bits; /* log2 of total */
91 size_t regions_free; /* number of free slots */
92 /* list of free chunk info structs */
93 struct chunk_info *chunk_info_list;
94 /* lists of chunks with free slots */
95 struct chunk_info *chunk_dir[MALLOC_MAXSHIFT];
96 size_t free_regions_size; /* free pages cached */
97 /* free pages cache */
98 struct region_info free_regions[MALLOC_MAXCACHE];
99 /* delayed free chunk slots */
100 void *delayed_chunks[MALLOC_DELAYED_CHUNKS];
101#ifdef MALLOC_STATS
102 size_t inserts;
103 size_t insert_collisions;
104 size_t finds;
105 size_t find_collisions;
106 size_t deletes;
107 size_t delete_moves;
108#define STATS_INC(x) ((x)++)
109#define STATS_ZERO(x) ((x) = 0)
110#else
111#define STATS_INC(x) /* nothing */
112#define STATS_ZERO(x) /* nothing */
113#endif /* MALLOC_STATS */
114 u_int32_t canary2;
115};
116
117
118/*
119 * This structure describes a page worth of chunks.
120 *
121 * How many bits per u_long in the bitmap
122 */
123#define MALLOC_BITS (NBBY * sizeof(u_long))
124struct chunk_info {
125 struct chunk_info *next; /* next on the free list */
126 void *page; /* pointer to the page */
127 u_int32_t canary;
128 u_short size; /* size of this page's chunks */
129 u_short shift; /* how far to shift for this size */
130 u_short free; /* how many free chunks */
131 u_short total; /* how many chunk */
132 /* which chunks are free */
133 u_long bits[(MALLOC_PAGESIZE / MALLOC_MINSIZE) / MALLOC_BITS];
134};
135
136static struct dir_info g_pool;
137static char *malloc_func; /* current function */
138char *malloc_options; /* compile-time options */
139
140static int malloc_abort = 1; /* abort() on error */
141static int malloc_active; /* status of malloc */
142static int malloc_freeprot; /* mprotect free pages PROT_NONE? */
143static int malloc_hint; /* call madvice on free pages? */
144static int malloc_junk; /* junk fill? */
145static int malloc_move; /* move allocations to end of page? */
146static int malloc_realloc; /* always realloc? */
147static int malloc_silent; /* avoid outputting warnings? */
148static int malloc_xmalloc; /* xmalloc behaviour? */
149static int malloc_zero; /* zero fill? */
150static size_t malloc_guard; /* use guard pages after allocations? */
151
152static u_int malloc_cache = 64; /* free pages we cache */
153static size_t malloc_guarded; /* bytes used for guards */
154static size_t malloc_used; /* bytes allocated */
155
156#ifdef MALLOC_STATS
157static int malloc_stats; /* dump statistics at end */
158#endif
159
160static size_t rbytesused; /* random bytes used */
161static u_char rbytes[4096]; /* random bytes */
162static u_char getrbyte(void);
163
164extern char *__progname;
165
166/* low bits of r->p determine size: 0 means >= page size and p->size holding
167 * real size, otherwise r->size is a shift count, or 1 for malloc(0)
168 */
169#define REALSIZE(sz, r) \
170 (sz) = (uintptr_t)(r)->p & MALLOC_PAGEMASK, \
171 (sz) = ((sz) == 0 ? (r)->size : ((sz) == 1 ? 0 : (1 << ((sz)-1))))
172
173static inline size_t
174hash(void *p)
175{
176 size_t sum;
177 union {
178 uintptr_t p;
179 unsigned short a[sizeof(void *) / sizeof(short)];
180 } u;
181 u.p = (uintptr_t)p >> MALLOC_PAGESHIFT;
182 sum = u.a[0];
183 sum = (sum << 7) - sum + u.a[1];
184#ifdef __LP64__
185 sum = (sum << 7) - sum + u.a[2];
186 sum = (sum << 7) - sum + u.a[3];
187#endif
188 return sum;
189}
190
191#ifdef MALLOC_STATS
192static void
193dump_chunk(int fd, struct chunk_info *p, int fromfreelist)
194{
195 char buf[64];
196
197 while (p) {
198 snprintf(buf, sizeof(buf), "chunk %d %d/%d %p\n", p->size,
199 p->free, p->total, p->page);
200 write(fd, buf, strlen(buf));
201 if (!fromfreelist)
202 break;
203 p = p->next;
204 if (p != NULL) {
205 snprintf(buf, sizeof(buf), " ");
206 write(fd, buf, strlen(buf));
207 }
208 }
209}
210
211static void
212dump_free_chunk_info(int fd, struct dir_info *d)
213{
214 char buf[64];
215 int i;
216
217 snprintf(buf, sizeof(buf), "Free chunk structs:\n");
218 write(fd, buf, strlen(buf));
219 for (i = 0; i < MALLOC_MAXSHIFT; i++) {
220 struct chunk_info *p = d->chunk_dir[i];
221 if (p != NULL) {
222 snprintf(buf, sizeof(buf), "%2d) ", i);
223 write(fd, buf, strlen(buf));
224 dump_chunk(fd, p, 1);
225 }
226 }
227
228}
229
230static void
231dump_free_page_info(int fd, struct dir_info *d)
232{
233 char buf[64];
234 int i;
235
236 snprintf(buf, sizeof(buf), "Free pages cached: %zu\n",
237 d->free_regions_size);
238 write(fd, buf, strlen(buf));
239 for (i = 0; i < malloc_cache; i++) {
240 if (d->free_regions[i].p != NULL) {
241 snprintf(buf, sizeof(buf), "%2d) ", i);
242 write(fd, buf, strlen(buf));
243 snprintf(buf, sizeof(buf), "free at %p: %zu\n",
244 d->free_regions[i].p, d->free_regions[i].size);
245 write(fd, buf, strlen(buf));
246 }
247 }
248}
249
250static void
251malloc_dump1(int fd, struct dir_info *d)
252{
253 char buf[64];
254 size_t i, realsize;
255
256 snprintf(buf, sizeof(buf), "Malloc dir of %s at %p\n", __progname, d);
257 write(fd, buf, strlen(buf));
258 snprintf(buf, sizeof(buf), "Regions slots %zu\n", d->regions_total);
259 write(fd, buf, strlen(buf));
260 snprintf(buf, sizeof(buf), "Finds %zu/%zu %f\n", d->finds,
261 d->find_collisions,
262 1.0 + (double)d->find_collisions / d->finds);
263 write(fd, buf, strlen(buf));
264 snprintf(buf, sizeof(buf), "Inserts %zu/%zu %f\n", d->inserts,
265 d->insert_collisions,
266 1.0 + (double)d->insert_collisions / d->inserts);
267 write(fd, buf, strlen(buf));
268 snprintf(buf, sizeof(buf), "Deletes %zu/%zu\n", d->deletes,
269 d->delete_moves);
270 write(fd, buf, strlen(buf));
271 snprintf(buf, sizeof(buf), "Regions slots free %zu\n", d->regions_free);
272 write(fd, buf, strlen(buf));
273 for (i = 0; i < d->regions_total; i++) {
274 if (d->r[i].p != NULL) {
275 size_t h = hash(d->r[i].p) &
276 (d->regions_total - 1);
277 snprintf(buf, sizeof(buf), "%4zx) #%zx %zd ",
278 i, h, h - i);
279 write(fd, buf, strlen(buf));
280 REALSIZE(realsize, &d->r[i]);
281 if (realsize > MALLOC_MAXCHUNK) {
282 snprintf(buf, sizeof(buf),
283 "%p: %zu\n", d->r[i].p, realsize);
284 write(fd, buf, strlen(buf));
285 } else
286 dump_chunk(fd,
287 (struct chunk_info *)d->r[i].size, 0);
288 }
289 }
290 dump_free_chunk_info(fd, d);
291 dump_free_page_info(fd, d);
292 snprintf(buf, sizeof(buf), "In use %zu\n", malloc_used);
293 write(fd, buf, strlen(buf));
294 snprintf(buf, sizeof(buf), "Guarded %zu\n", malloc_guarded);
295 write(fd, buf, strlen(buf));
296}
297
298
299void
300malloc_dump(int fd)
301{
302 malloc_dump1(fd, &g_pool);
303}
304
305static void
306malloc_exit(void)
307{
308 char *q = "malloc() warning: Couldn't dump stats\n";
309 int save_errno = errno, fd;
310
311 fd = open("malloc.out", O_RDWR|O_APPEND);
312 if (fd != -1) {
313 malloc_dump(fd);
314 close(fd);
315 } else
316 write(STDERR_FILENO, q, strlen(q));
317 errno = save_errno;
318}
319#endif /* MALLOC_STATS */
320
321
322
323static void
324wrterror(char *p)
325{
326 char *q = " error: ";
327 struct iovec iov[5];
328
329 iov[0].iov_base = __progname;
330 iov[0].iov_len = strlen(__progname);
331 iov[1].iov_base = malloc_func;
332 iov[1].iov_len = strlen(malloc_func);
333 iov[2].iov_base = q;
334 iov[2].iov_len = strlen(q);
335 iov[3].iov_base = p;
336 iov[3].iov_len = strlen(p);
337 iov[4].iov_base = "\n";
338 iov[4].iov_len = 1;
339 writev(STDERR_FILENO, iov, 5);
340
341#ifdef MALLOC_STATS
342 if (malloc_stats)
343 malloc_dump(STDERR_FILENO);
344#endif /* MALLOC_STATS */
345 //malloc_active--;
346 if (malloc_abort)
347 abort();
348}
349
350static void
351wrtwarning(char *p)
352{
353 char *q = " warning: ";
354 struct iovec iov[5];
355
356 if (malloc_abort)
357 wrterror(p);
358 else if (malloc_silent)
359 return;
360
361 iov[0].iov_base = __progname;
362 iov[0].iov_len = strlen(__progname);
363 iov[1].iov_base = malloc_func;
364 iov[1].iov_len = strlen(malloc_func);
365 iov[2].iov_base = q;
366 iov[2].iov_len = strlen(q);
367 iov[3].iov_base = p;
368 iov[3].iov_len = strlen(p);
369 iov[4].iov_base = "\n";
370 iov[4].iov_len = 1;
371
372 writev(STDERR_FILENO, iov, 5);
373}
374
375/*
376 * Cache maintenance. We keep at most malloc_cache pages cached.
377 * If the cache is becoming full, unmap pages in the cache for real,
378 * and then add the region to the cache
379 * Opposed to the regular region data structure, the sizes in the
380 * cache are in MALLOC_PAGESIZE units.
381 */
382static void
383unmap(struct dir_info *d, void *p, size_t sz)
384{
385 size_t psz = sz >> MALLOC_PAGESHIFT;
386 size_t rsz, tounmap;
387 struct region_info *r;
388 u_int i, offset;
389
390 if (sz != PAGEROUND(sz)) {
391 wrterror("munmap round");
392 return;
393 }
394
395 if (psz > malloc_cache) {
396 if (munmap(p, sz))
397 wrterror("munmap");
398 malloc_used -= sz;
399 return;
400 }
401 tounmap = 0;
402 rsz = malloc_cache - d->free_regions_size;
403 if (psz > rsz)
404 tounmap = psz - rsz;
405 d->free_regions_size -= tounmap;
406 offset = getrbyte();
407 for (i = 0; tounmap > 0 && i < malloc_cache; i++) {
408 r = &d->free_regions[(i + offset) & (malloc_cache - 1)];
409 if (r->p != NULL) {
410 if (r->size <= tounmap) {
411 rsz = r->size << MALLOC_PAGESHIFT;
412 if (munmap(r->p, rsz))
413 wrterror("munmap");
414 tounmap -= r->size;
415 r->p = NULL;
416 r->size = 0;
417 malloc_used -= rsz;
418 } else {
419 rsz = tounmap << MALLOC_PAGESHIFT;
420 if (munmap((char *)r->p + ((r->size - tounmap)
421 << MALLOC_PAGESHIFT), rsz))
422 wrterror("munmap");
423 r->size -= tounmap ;
424 tounmap = 0;
425 malloc_used -= rsz;
426 }
427 }
428 }
429 if (tounmap > 0)
430 wrtwarning("malloc cache underflow");
431 for (i = 0; i < malloc_cache; i++) {
432 r = &d->free_regions[i];
433 if (r->p == NULL) {
434 if (malloc_hint)
435 madvise(p, sz, MADV_FREE);
436 if (malloc_freeprot)
437 mprotect(p, sz, PROT_NONE);
438 r->p = p;
439 r->size = psz;
440 d->free_regions_size += psz;
441 break;
442 }
443 }
444 if (i == malloc_cache)
445 wrtwarning("malloc free slot lost");
446 if (d->free_regions_size > malloc_cache)
447 wrtwarning("malloc cache overflow");
448}
449
450static void *
451map(struct dir_info *d, size_t sz, int zero_fill)
452{
453 size_t psz = sz >> MALLOC_PAGESHIFT;
454 struct region_info *r, *big = NULL;
455 u_int i, offset;
456 void *p;
457
458 if (sz != PAGEROUND(sz)) {
459 wrterror("map round");
460 return NULL;
461 }
462 if (psz > d->free_regions_size) {
463 p = MMAP(sz);
464 if (p != MAP_FAILED)
465 malloc_used += sz;
466 /* zero fill not needed */
467 return p;
468 }
469 offset = getrbyte();
470 for (i = 0; i < malloc_cache; i++) {
471 r = &d->free_regions[(i + offset) & (malloc_cache - 1)];
472 if (r->p != NULL) {
473 if (r->size == psz) {
474 p = r->p;
475 if (malloc_freeprot)
476 mprotect(p, sz, PROT_READ | PROT_WRITE);
477 if (malloc_hint)
478 madvise(p, sz, MADV_NORMAL);
479 r->p = NULL;
480 r->size = 0;
481 d->free_regions_size -= psz;
482 if (zero_fill)
483 memset(p, 0, sz);
484 return p;
485 } else if (r->size > psz)
486 big = r;
487 }
488 }
489 if (big != NULL) {
490 r = big;
491 p = (char *)r->p + ((r->size - psz) << MALLOC_PAGESHIFT);
492 if (malloc_freeprot)
493 mprotect(p, sz, PROT_READ | PROT_WRITE);
494 if (malloc_hint)
495 madvise(p, sz, MADV_NORMAL);
496 r->size -= psz;
497 d->free_regions_size -= psz;
498 if (zero_fill)
499 memset(p, 0, sz);
500 return p;
501 }
502 p = MMAP(sz);
503 if (p != MAP_FAILED)
504 malloc_used += sz;
505 if (d->free_regions_size > malloc_cache)
506 wrtwarning("malloc cache");
507 /* zero fill not needed */
508 return p;
509}
510
511static void
512rbytes_init(void)
513{
514 arc4random_buf(rbytes, sizeof(rbytes));
515 rbytesused = 0;
516}
517
518static u_char
519getrbyte(void)
520{
521 if (rbytesused >= sizeof(rbytes))
522 rbytes_init();
523 return rbytes[rbytesused++];
524}
525
526/*
527 * Initialize a dir_info, which should have been cleared by caller
528 */
529static int
530omalloc_init(struct dir_info *d)
531{
532 char *p, b[64];
533 int i, j, save_errno = errno;
534 size_t regioninfo_size;
535
536 rbytes_init();
537
538 for (i = 0; i < 3; i++) {
539 switch (i) {
540 case 0:
541 j = readlink("/etc/malloc.conf", b, sizeof b - 1);
542 if (j <= 0)
543 continue;
544 b[j] = '\0';
545 p = b;
546 break;
547 case 1:
548 if (issetugid() == 0)
549 p = getenv("MALLOC_OPTIONS");
550 else
551 continue;
552 break;
553 case 2:
554 p = malloc_options;
555 break;
556 default:
557 p = NULL;
558 }
559
560 for (; p != NULL && *p != '\0'; p++) {
561 switch (*p) {
562 case '>':
563 malloc_cache <<= 1;
564 if (malloc_cache > MALLOC_MAXCACHE)
565 malloc_cache = MALLOC_MAXCACHE;
566 break;
567 case '<':
568 malloc_cache >>= 1;
569 break;
570 case 'a':
571 malloc_abort = 0;
572 break;
573 case 'A':
574 malloc_abort = 1;
575 break;
576#ifdef MALLOC_STATS
577 case 'd':
578 malloc_stats = 0;
579 break;
580 case 'D':
581 malloc_stats = 1;
582 break;
583#endif /* MALLOC_STATS */
584 case 'f':
585 malloc_freeprot = 0;
586 break;
587 case 'F':
588 malloc_freeprot = 1;
589 break;
590 case 'g':
591 malloc_guard = 0;
592 break;
593 case 'G':
594 malloc_guard = MALLOC_PAGESIZE;
595 break;
596 case 'h':
597 malloc_hint = 0;
598 break;
599 case 'H':
600 malloc_hint = 1;
601 break;
602 case 'j':
603 malloc_junk = 0;
604 break;
605 case 'J':
606 malloc_junk = 1;
607 break;
608 case 'n':
609 malloc_silent = 0;
610 break;
611 case 'N':
612 malloc_silent = 1;
613 break;
614 case 'p':
615 malloc_move = 0;
616 break;
617 case 'P':
618 malloc_move = 1;
619 break;
620 case 'r':
621 malloc_realloc = 0;
622 break;
623 case 'R':
624 malloc_realloc = 1;
625 break;
626 case 'x':
627 malloc_xmalloc = 0;
628 break;
629 case 'X':
630 malloc_xmalloc = 1;
631 break;
632 case 'z':
633 malloc_zero = 0;
634 break;
635 case 'Z':
636 malloc_zero = 1;
637 break;
638 default:
639 j = malloc_abort;
640 malloc_abort = 0;
641 wrtwarning("unknown char in MALLOC_OPTIONS");
642 malloc_abort = j;
643 break;
644 }
645 }
646 }
647
648 /*
649 * We want junk in the entire allocation, and zero only in the part
650 * the user asked for.
651 */
652 if (malloc_zero)
653 malloc_junk = 1;
654
655#ifdef MALLOC_STATS
656 if (malloc_stats && (atexit(malloc_exit) == -1))
657 wrtwarning("atexit(2) failed."
658 " Will not be able to dump malloc stats on exit");
659#endif /* MALLOC_STATS */
660
661 errno = save_errno;
662
663 d->regions_bits = 9;
664 d->regions_free = d->regions_total = 1 << d->regions_bits;
665 regioninfo_size = d->regions_total * sizeof(struct region_info);
666 d->r = MMAP(regioninfo_size);
667 if (d->r == MAP_FAILED) {
668 wrterror("malloc init mmap failed");
669 d->regions_total = 0;
670 return 1;
671 }
672 malloc_used += regioninfo_size;
673 memset(d->r, 0, regioninfo_size);
674 d->canary1 = arc4random();
675 d->canary2 = ~d->canary1;
676 return 0;
677}
678
679static int
680omalloc_grow(struct dir_info *d)
681{
682 size_t newbits;
683 size_t newtotal;
684 size_t newsize;
685 size_t mask;
686 size_t i;
687 struct region_info *p;
688
689 if (d->regions_total > SIZE_MAX / sizeof(struct region_info) / 2 )
690 return 1;
691
692 newbits = d->regions_bits + 1;
693 newtotal = d->regions_total * 2;
694 newsize = newtotal * sizeof(struct region_info);
695 mask = newtotal - 1;
696
697 p = MMAP(newsize);
698 if (p == MAP_FAILED)
699 return 1;
700
701 malloc_used += newsize;
702 memset(p, 0, newsize);
703 STATS_ZERO(d->inserts);
704 STATS_ZERO(d->insert_collisions);
705 for (i = 0; i < d->regions_total; i++) {
706 void *q = d->r[i].p;
707 if (q != NULL) {
708 size_t index = hash(q) & mask;
709 STATS_INC(d->inserts);
710 while (p[index].p != NULL) {
711 index = (index - 1) & mask;
712 STATS_INC(d->insert_collisions);
713 }
714 p[index] = d->r[i];
715 }
716 }
717 /* avoid pages containing meta info to end up in cache */
718 if (munmap(d->r, d->regions_total * sizeof(struct region_info)))
719 wrterror("munmap");
720 else
721 malloc_used -= d->regions_total * sizeof(struct region_info);
722 d->regions_free = d->regions_free + d->regions_total;
723 d->regions_total = newtotal;
724 d->regions_bits = newbits;
725 d->r = p;
726 return 0;
727}
728
729static struct chunk_info *
730alloc_chunk_info(struct dir_info *d)
731{
732 struct chunk_info *p;
733 int i;
734
735 if (d->chunk_info_list == NULL) {
736 p = MMAP(MALLOC_PAGESIZE);
737 if (p == MAP_FAILED)
738 return NULL;
739 malloc_used += MALLOC_PAGESIZE;
740 for (i = 0; i < MALLOC_PAGESIZE / sizeof(*p); i++) {
741 p[i].next = d->chunk_info_list;
742 d->chunk_info_list = &p[i];
743 }
744 }
745 p = d->chunk_info_list;
746 d->chunk_info_list = p->next;
747 memset(p, 0, sizeof *p);
748 p->canary = d->canary1;
749 return p;
750}
751
752
753static void
754put_chunk_info(struct dir_info *d, struct chunk_info *p)
755{
756 p->next = d->chunk_info_list;
757 d->chunk_info_list = p;
758}
759
760static int
761insert(struct dir_info *d, void *p, size_t sz)
762{
763 size_t index;
764 size_t mask;
765 void *q;
766
767 if (d->regions_free * 4 < d->regions_total) {
768 if (omalloc_grow(d))
769 return 1;
770 }
771 mask = d->regions_total - 1;
772 index = hash(p) & mask;
773 q = d->r[index].p;
774 STATS_INC(d->inserts);
775 while (q != NULL) {
776 index = (index - 1) & mask;
777 q = d->r[index].p;
778 STATS_INC(d->insert_collisions);
779 }
780 d->r[index].p = p;
781 d->r[index].size = sz;
782 d->regions_free--;
783 return 0;
784}
785
786static struct region_info *
787find(struct dir_info *d, void *p)
788{
789 size_t index;
790 size_t mask = d->regions_total - 1;
791 void *q, *r;
792
793 if (d->canary1 != ~d->canary2)
794 wrterror("internal struct corrupt");
795 p = MASK_POINTER(p);
796 index = hash(p) & mask;
797 r = d->r[index].p;
798 q = MASK_POINTER(r);
799 STATS_INC(d->finds);
800 while (q != p && r != NULL) {
801 index = (index - 1) & mask;
802 r = d->r[index].p;
803 q = MASK_POINTER(r);
804 STATS_INC(d->find_collisions);
805 }
806 return q == p ? &d->r[index] : NULL;
807}
808
809static void
810delete(struct dir_info *d, struct region_info *ri)
811{
812 /* algorithm R, Knuth Vol III section 6.4 */
813 size_t mask = d->regions_total - 1;
814 size_t i, j, r;
815
816 if (d->regions_total & (d->regions_total - 1))
817 wrterror("regions_total not 2^x");
818 d->regions_free++;
819 STATS_INC(g_pool.deletes);
820
821 i = ri - d->r;
822 for (;;) {
823 d->r[i].p = NULL;
824 d->r[i].size = 0;
825 j = i;
826 for (;;) {
827 i = (i - 1) & mask;
828 if (d->r[i].p == NULL)
829 return;
830 r = hash(d->r[i].p) & mask;
831 if ((i <= r && r < j) || (r < j && j < i) ||
832 (j < i && i <= r))
833 continue;
834 d->r[j] = d->r[i];
835 STATS_INC(g_pool.delete_moves);
836 break;
837 }
838
839 }
840}
841
842/*
843 * Allocate a page of chunks
844 */
845static struct chunk_info *
846omalloc_make_chunks(struct dir_info *d, int bits)
847{
848 struct chunk_info *bp;
849 void *pp;
850 long i, k;
851
852 /* Allocate a new bucket */
853 pp = map(d, MALLOC_PAGESIZE, 0);
854 if (pp == MAP_FAILED)
855 return NULL;
856
857 bp = alloc_chunk_info(d);
858 if (bp == NULL) {
859 unmap(d, pp, MALLOC_PAGESIZE);
860 return NULL;
861 }
862
863 /* memory protect the page allocated in the malloc(0) case */
864 if (bits == 0) {
865 bp->size = 0;
866 bp->shift = 1;
867 i = MALLOC_MINSIZE - 1;
868 while (i >>= 1)
869 bp->shift++;
870 bp->total = bp->free = MALLOC_PAGESIZE >> bp->shift;
871 bp->page = pp;
872
873 k = mprotect(pp, MALLOC_PAGESIZE, PROT_NONE);
874 if (k < 0) {
875 unmap(d, pp, MALLOC_PAGESIZE);
876 put_chunk_info(d, bp);
877 return NULL;
878 }
879 } else {
880 bp->size = (1UL << bits);
881 bp->shift = bits;
882 bp->total = bp->free = MALLOC_PAGESIZE >> bits;
883 bp->page = pp;
884 }
885
886 /* set all valid bits in the bitmap */
887 k = bp->total;
888 i = 0;
889
890 /* Do a bunch at a time */
891 for (; (k - i) >= MALLOC_BITS; i += MALLOC_BITS)
892 bp->bits[i / MALLOC_BITS] = ~0UL;
893
894 for (; i < k; i++)
895 bp->bits[i / MALLOC_BITS] |= 1UL << (i % MALLOC_BITS);
896
897 bp->next = d->chunk_dir[bits];
898 d->chunk_dir[bits] = bp;
899
900 bits++;
901 if ((uintptr_t)pp & bits)
902 wrterror("pp & bits");
903
904 insert(d, (void *)((uintptr_t)pp | bits), (uintptr_t)bp);
905 return bp;
906}
907
908
909/*
910 * Allocate a chunk
911 */
912static void *
913malloc_bytes(struct dir_info *d, size_t size)
914{
915 int i, j;
916 size_t k;
917 u_long u, *lp;
918 struct chunk_info *bp;
919
920 /* Don't bother with anything less than this */
921 /* unless we have a malloc(0) requests */
922 if (size != 0 && size < MALLOC_MINSIZE)
923 size = MALLOC_MINSIZE;
924
925 /* Find the right bucket */
926 if (size == 0)
927 j = 0;
928 else {
929 j = MALLOC_MINSHIFT;
930 i = (size - 1) >> (MALLOC_MINSHIFT - 1);
931 while (i >>= 1)
932 j++;
933 }
934
935 /* If it's empty, make a page more of that size chunks */
936 bp = d->chunk_dir[j];
937 if (bp == NULL && (bp = omalloc_make_chunks(d, j)) == NULL)
938 return NULL;
939
940 if (bp->canary != d->canary1)
941 wrterror("chunk info corrupted");
942 /* Find first word of bitmap which isn't empty */
943 for (lp = bp->bits; !*lp; lp++)
944 /* EMPTY */;
945
946 /* Find that bit, and tweak it */
947 u = 1;
948 k = 0;
949 while (!(*lp & u)) {
950 u += u;
951 k++;
952 }
953
954 /* advance a random # of positions */
955 i = (getrbyte() & (MALLOC_DELAYED_CHUNKS - 1)) % bp->free;
956 while (i > 0) {
957 u += u;
958 k++;
959 if (k >= MALLOC_BITS) {
960 lp++;
961 u = 1;
962 k = 0;
963 }
964 if (lp - bp->bits > (bp->total - 1) / MALLOC_BITS) {
965 wrterror("chunk overflow");
966 errno = EFAULT;
967 return (NULL);
968 }
969 if (*lp & u)
970 i--;
971 }
972
973 *lp ^= u;
974
975 /* If there are no more free, remove from free-list */
976 if (!--bp->free) {
977 d->chunk_dir[j] = bp->next;
978 bp->next = NULL;
979 }
980 /* Adjust to the real offset of that chunk */
981 k += (lp - bp->bits) * MALLOC_BITS;
982 k <<= bp->shift;
983
984 if (malloc_junk && bp->size > 0)
985 memset((char *)bp->page + k, SOME_JUNK, bp->size);
986 return ((char *)bp->page + k);
987}
988
989
990/*
991 * Free a chunk, and possibly the page it's on, if the page becomes empty.
992 */
993static void
994free_bytes(struct dir_info *d, struct region_info *r, void *ptr)
995{
996 struct chunk_info *info, **mp;
997 long i;
998
999 info = (struct chunk_info *)r->size;
1000 if (info->canary != d->canary1)
1001 wrterror("chunk info corrupted");
1002
1003 /* Find the chunk number on the page */
1004 i = ((uintptr_t)ptr & MALLOC_PAGEMASK) >> info->shift;
1005
1006 if ((uintptr_t)ptr & ((1UL << (info->shift)) - 1)) {
1007 wrtwarning("modified chunk-pointer");
1008 return;
1009 }
1010 if (info->bits[i / MALLOC_BITS] & (1UL << (i % MALLOC_BITS))) {
1011 wrtwarning("chunk is already free");
1012 return;
1013 }
1014
1015 info->bits[i / MALLOC_BITS] |= 1UL << (i % MALLOC_BITS);
1016 info->free++;
1017
1018 if (info->size != 0)
1019 mp = d->chunk_dir + info->shift;
1020 else
1021 mp = d->chunk_dir;
1022
1023 if (info->free == 1) {
1024 /* Page became non-full */
1025
1026 /* Insert in address order */
1027 while (*mp != NULL && (*mp)->next != NULL &&
1028 (*mp)->next->page < info->page)
1029 mp = &(*mp)->next;
1030 info->next = *mp;
1031 *mp = info;
1032 return;
1033 }
1034 if (info->free != info->total)
1035 return;
1036
1037 /* Find & remove this page in the queue */
1038 while (*mp != info) {
1039 mp = &((*mp)->next);
1040 if (!*mp) {
1041 wrterror("not on queue");
1042 errno = EFAULT;
1043 return;
1044 }
1045 }
1046 *mp = info->next;
1047
1048 if (info->size == 0 && !malloc_freeprot)
1049 mprotect(info->page, MALLOC_PAGESIZE, PROT_READ | PROT_WRITE);
1050 unmap(d, info->page, MALLOC_PAGESIZE);
1051
1052 delete(d, r);
1053 put_chunk_info(d, info);
1054}
1055
1056
1057
1058static void *
1059omalloc(size_t sz, int zero_fill)
1060{
1061 void *p;
1062 size_t psz;
1063
1064 if (sz > MALLOC_MAXCHUNK) {
1065 if (sz >= SIZE_MAX - malloc_guard - MALLOC_PAGESIZE) {
1066 errno = ENOMEM;
1067 return NULL;
1068 }
1069 sz += malloc_guard;
1070 psz = PAGEROUND(sz);
1071 p = map(&g_pool, psz, zero_fill);
1072 if (p == MAP_FAILED) {
1073 errno = ENOMEM;
1074 return NULL;
1075 }
1076 if (insert(&g_pool, p, sz)) {
1077 unmap(&g_pool, p, psz);
1078 errno = ENOMEM;
1079 return NULL;
1080 }
1081 if (malloc_guard) {
1082 if (mprotect((char *)p + psz - malloc_guard,
1083 malloc_guard, PROT_NONE))
1084 wrterror("mprotect");
1085 malloc_guarded += malloc_guard;
1086 }
1087
1088 if (malloc_move &&
1089 sz - malloc_guard < MALLOC_PAGESIZE - MALLOC_MINSIZE) {
1090 /* fill whole allocation */
1091 if (malloc_junk)
1092 memset(p, SOME_JUNK, psz - malloc_guard);
1093 /* shift towards the end */
1094 p = ((char *)p) + ((MALLOC_PAGESIZE - MALLOC_MINSIZE -
1095 (sz - malloc_guard)) & ~(MALLOC_MINSIZE-1));
1096 /* fill zeros if needed and overwritten above */
1097 if (zero_fill && malloc_junk)
1098 memset(p, 0, sz - malloc_guard);
1099 } else {
1100 if (malloc_junk) {
1101 if (zero_fill)
1102 memset(p + sz - malloc_guard,
1103 SOME_JUNK, psz - sz);
1104 else
1105 memset(p,
1106 SOME_JUNK, psz - malloc_guard);
1107 }
1108 }
1109
1110 } else {
1111 /* takes care of SOME_JUNK */
1112 p = malloc_bytes(&g_pool, sz);
1113 if (zero_fill && p != NULL && sz > 0)
1114 memset(p, 0, sz);
1115 }
1116
1117 return p;
1118}
1119
1120/*
1121 * Common function for handling recursion. Only
1122 * print the error message once, to avoid making the problem
1123 * potentially worse.
1124 */
1125static void
1126malloc_recurse(void)
1127{
1128 static int noprint;
1129
1130 if (noprint == 0) {
1131 noprint = 1;
1132 wrtwarning("recursive call");
1133 }
1134 malloc_active--;
1135 _MALLOC_UNLOCK();
1136 errno = EDEADLK;
1137}
1138
1139void *
1140malloc(size_t size)
1141{
1142 void *r;
1143
1144 _MALLOC_LOCK();
1145 malloc_func = " in malloc():";
1146 if (!g_pool.regions_total) {
1147 if (omalloc_init(&g_pool)) {
1148 _MALLOC_UNLOCK();
1149 if (malloc_xmalloc)
1150 wrterror("out of memory");
1151 errno = ENOMEM;
1152 return NULL;
1153 }
1154 }
1155 if (malloc_active++) {
1156 malloc_recurse();
1157 return NULL;
1158 }
1159 r = omalloc(size, malloc_zero);
1160 malloc_active--;
1161 _MALLOC_UNLOCK();
1162 if (r == NULL && malloc_xmalloc) {
1163 wrterror("out of memory");
1164 errno = ENOMEM;
1165 }
1166 return r;
1167}
1168
1169static void
1170ofree(void *p)
1171{
1172 struct region_info *r;
1173 size_t sz;
1174
1175 r = find(&g_pool, p);
1176 if (r == NULL) {
1177 wrtwarning("bogus pointer (double free?)");
1178 return;
1179 }
1180 REALSIZE(sz, r);
1181 if (sz > MALLOC_MAXCHUNK) {
1182 if (sz - malloc_guard >= MALLOC_PAGESIZE - MALLOC_MINSIZE) {
1183 if (r->p != p)
1184 wrtwarning("bogus pointer");
1185 } else {
1186#if notyetbecause_of_realloc
1187 /* shifted towards the end */
1188 if (p != ((char *)r->p) + ((MALLOC_PAGESIZE -
1189 MALLOC_MINSIZE - sz - malloc_guard) &
1190 ~(MALLOC_MINSIZE-1))) {
1191 }
1192#endif
1193 p = r->p;
1194 }
1195 if (malloc_guard) {
1196 if (sz < malloc_guard)
1197 wrtwarning("guard size");
1198 if (!malloc_freeprot) {
1199 if (mprotect((char *)p + PAGEROUND(sz) -
1200 malloc_guard, malloc_guard,
1201 PROT_READ | PROT_WRITE))
1202 wrterror("mprotect");
1203 }
1204 malloc_guarded -= malloc_guard;
1205 }
1206 if (malloc_junk)
1207 memset(p, SOME_FREEJUNK, PAGEROUND(sz) - malloc_guard);
1208 unmap(&g_pool, p, PAGEROUND(sz));
1209 delete(&g_pool, r);
1210 } else {
1211 void *tmp;
1212 int i;
1213
1214 if (malloc_junk && sz > 0)
1215 memset(p, SOME_FREEJUNK, sz);
1216 i = getrbyte() & (MALLOC_DELAYED_CHUNKS - 1);
1217 tmp = p;
1218 p = g_pool.delayed_chunks[i];
1219 g_pool.delayed_chunks[i] = tmp;
1220 if (p != NULL) {
1221 r = find(&g_pool, p);
1222 if (r == NULL) {
1223 wrtwarning("bogus pointer (double free?)");
1224 return;
1225 }
1226 free_bytes(&g_pool, r, p);
1227 }
1228 }
1229}
1230
1231void
1232free(void *ptr)
1233{
1234 /* This is legal. */
1235 if (ptr == NULL)
1236 return;
1237
1238 _MALLOC_LOCK();
1239 malloc_func = " in free():";
1240 if (malloc_active++) {
1241 malloc_recurse();
1242 return;
1243 }
1244 ofree(ptr);
1245 malloc_active--;
1246 _MALLOC_UNLOCK();
1247}
1248
1249
1250static void *
1251orealloc(void *p, size_t newsz)
1252{
1253 struct region_info *r;
1254 size_t oldsz, goldsz, gnewsz;
1255 void *q;
1256
1257 if (p == NULL)
1258 return omalloc(newsz, 0);
1259
1260 r = find(&g_pool, p);
1261 if (r == NULL) {
1262 wrtwarning("bogus pointer (double free?)");
1263 return NULL;
1264 }
1265 if (newsz >= SIZE_MAX - malloc_guard - MALLOC_PAGESIZE) {
1266 errno = ENOMEM;
1267 return NULL;
1268 }
1269
1270 REALSIZE(oldsz, r);
1271 goldsz = oldsz;
1272 if (oldsz > MALLOC_MAXCHUNK) {
1273 if (oldsz < malloc_guard)
1274 wrtwarning("guard size");
1275 oldsz -= malloc_guard;
1276 }
1277
1278 gnewsz = newsz;
1279 if (gnewsz > MALLOC_MAXCHUNK)
1280 gnewsz += malloc_guard;
1281
1282 if (newsz > MALLOC_MAXCHUNK && oldsz > MALLOC_MAXCHUNK && p == r->p &&
1283 !malloc_realloc) {
1284 size_t roldsz = PAGEROUND(goldsz);
1285 size_t rnewsz = PAGEROUND(gnewsz);
1286
1287 if (rnewsz < roldsz) {
1288 if (malloc_guard) {
1289 if (mprotect((char *)p + roldsz - malloc_guard,
1290 malloc_guard, PROT_READ | PROT_WRITE))
1291 wrterror("mprotect");
1292 if (mprotect((char *)p + rnewsz - malloc_guard,
1293 malloc_guard, PROT_NONE))
1294 wrterror("mprotect");
1295 }
1296 unmap(&g_pool, (char *)p + rnewsz, roldsz - rnewsz);
1297 r->size = gnewsz;
1298 return p;
1299 } else if (rnewsz == roldsz) {
1300 if (newsz > oldsz && malloc_junk)
1301 memset((char *)p + newsz, SOME_JUNK,
1302 rnewsz - malloc_guard - newsz);
1303 r->size = gnewsz;
1304 return p;
1305 }
1306 }
1307 if (newsz <= oldsz && newsz > oldsz / 2 && !malloc_realloc) {
1308 if (malloc_junk && newsz > 0)
1309 memset((char *)p + newsz, SOME_JUNK, oldsz - newsz);
1310 return p;
1311 } else if (newsz != oldsz || malloc_realloc) {
1312 q = omalloc(newsz, 0);
1313 if (q == NULL)
1314 return NULL;
1315 if (newsz != 0 && oldsz != 0)
1316 memcpy(q, p, oldsz < newsz ? oldsz : newsz);
1317 ofree(p);
1318 return q;
1319 } else
1320 return p;
1321}
1322
1323void *
1324realloc(void *ptr, size_t size)
1325{
1326 void *r;
1327
1328 _MALLOC_LOCK();
1329 malloc_func = " in realloc():";
1330 if (!g_pool.regions_total) {
1331 if (omalloc_init(&g_pool)) {
1332 _MALLOC_UNLOCK();
1333 if (malloc_xmalloc)
1334 wrterror("out of memory");
1335 errno = ENOMEM;
1336 return NULL;
1337 }
1338 }
1339 if (malloc_active++) {
1340 malloc_recurse();
1341 return NULL;
1342 }
1343
1344 r = orealloc(ptr, size);
1345
1346 malloc_active--;
1347 _MALLOC_UNLOCK();
1348 if (r == NULL && malloc_xmalloc) {
1349 wrterror("out of memory");
1350 errno = ENOMEM;
1351 }
1352 return r;
1353}
1354
1355
1356#define MUL_NO_OVERFLOW (1UL << (sizeof(size_t) * 4))
1357
1358void *
1359calloc(size_t nmemb, size_t size)
1360{
1361 void *r;
1362
1363 _MALLOC_LOCK();
1364 malloc_func = " in calloc():";
1365 if (!g_pool.regions_total) {
1366 if (omalloc_init(&g_pool)) {
1367 _MALLOC_UNLOCK();
1368 if (malloc_xmalloc)
1369 wrterror("out of memory");
1370 errno = ENOMEM;
1371 return NULL;
1372 }
1373 }
1374 if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
1375 nmemb > 0 && SIZE_MAX / nmemb < size) {
1376 _MALLOC_UNLOCK();
1377 if (malloc_xmalloc)
1378 wrterror("out of memory");
1379 errno = ENOMEM;
1380 return NULL;
1381 }
1382
1383 if (malloc_active++) {
1384 malloc_recurse();
1385 return NULL;
1386 }
1387
1388 size *= nmemb;
1389 r = omalloc(size, 1);
1390
1391 malloc_active--;
1392 _MALLOC_UNLOCK();
1393 if (r == NULL && malloc_xmalloc) {
1394 wrterror("out of memory");
1395 errno = ENOMEM;
1396 }
1397 return r;
1398}
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..e022e9c1f4
--- /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.11 2007/05/31 19:19:31 jmc Exp $
33.\"
34.Dd $Mdocdate: May 31 2007 $
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..59776bdf2d
--- /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.8 2007/05/31 19:19:31 jmc Exp $
33.\"
34.Dd $Mdocdate: May 31 2007 $
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..92c75d5365
--- /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.15 2007/05/31 19:19:31 jmc Exp $
33.\"
34.Dd $Mdocdate: May 31 2007 $
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..b90a557718
--- /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.11 2007/05/31 19:19:31 jmc Exp $
29.\"
30.Dd $Mdocdate: May 31 2007 $
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..49d03b52d5
--- /dev/null
+++ b/src/lib/libc/stdlib/radixsort.c
@@ -0,0 +1,294 @@
1/* $OpenBSD: radixsort.c,v 1.9 2007/09/02 15:19:17 deraadt 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 = calloc(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..df4feaacdb
--- /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.10 2007/05/31 19:19:31 jmc Exp $
33.\"
34.Dd $Mdocdate: May 31 2007 $
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..0e8ca5389b
--- /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.11 2007/05/31 19:19:31 jmc Exp $
13.\"
14.Dd $Mdocdate: May 31 2007 $
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..ed05df162b
--- /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.19 2007/05/31 19:19:31 jmc Exp $
29.\"
30.Dd $Mdocdate: May 31 2007 $
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..c64fc3d637
--- /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.15 2007/07/06 15:42:04 millert Exp $
32.\"
33.Dd $Mdocdate: July 6 2007 $
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 <limits.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..979334203e
--- /dev/null
+++ b/src/lib/libc/stdlib/strtod.3
@@ -0,0 +1,129 @@
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.12 2008/06/13 23:50:49 jmc Exp $
33.\"
34.Dd $Mdocdate: June 13 2008 $
35.Dt STRTOD 3
36.Os
37.Sh NAME
38.Nm strtod ,
39.Nm strtof
40.Nd convert
41.Tn ASCII
42string to double or float
43.Sh SYNOPSIS
44.Fd #include <math.h>
45.Fd #include <stdlib.h>
46.Ft double
47.Fn strtod "const char *nptr" "char **endptr"
48.Pp
49.Ft float
50.Fn strtof "const char *nptr" "char **endptr"
51.Sh DESCRIPTION
52The
53.Fn strtod
54function converts the initial portion of the string pointed to by
55.Fa nptr
56to
57.Li double
58representation.
59The
60.Fn strtof
61function converts the initial portion of the string pointed to by
62.Fa nptr
63to
64.Li float
65representation.
66.Pp
67The expected form of the string is an optional plus
68.Pq Ql +
69or minus sign
70.Pq Ql -
71followed by a sequence of digits optionally containing
72a decimal-point character, optionally followed by an exponent.
73An exponent consists of an
74.Sq E
75or
76.Sq e ,
77followed by an optional plus or minus sign, followed by a sequence of digits.
78.Pp
79Leading whitespace characters in the string (as defined by the
80.Xr isspace 3
81function) are skipped.
82.Sh RETURN VALUES
83The
84.Fn strtod
85and
86.Fn strtof
87functions return the converted value, if any.
88.Pp
89If
90.Fa endptr
91is not
92.Dv NULL ,
93a pointer to the character after the last character used
94in the conversion is stored in the location referenced by
95.Fa endptr .
96.Pp
97If no conversion is performed, zero is returned and the value of
98.Fa nptr
99is stored in the location referenced by
100.Fa endptr .
101.Pp
102If the correct value would cause overflow, plus or minus
103.Dv HUGE_VAL
104is returned (according to the sign of the value), and
105.Er ERANGE
106is stored in
107.Va errno .
108If the correct value would cause underflow, zero is returned and
109.Er ERANGE
110is stored in
111.Va errno .
112.Sh ERRORS
113.Bl -tag -width Er
114.It Bq Er ERANGE
115Overflow or underflow occurred.
116.El
117.Sh SEE ALSO
118.Xr atof 3 ,
119.Xr atoi 3 ,
120.Xr atol 3 ,
121.Xr strtol 3 ,
122.Xr strtoul 3
123.Sh STANDARDS
124The
125.Fn strtod
126and
127.Fn strtof
128functions conform to
129.St -ansiC .
diff --git a/src/lib/libc/stdlib/strtod.c b/src/lib/libc/stdlib/strtod.c
new file mode 100644
index 0000000000..4dc3d65a26
--- /dev/null
+++ b/src/lib/libc/stdlib/strtod.c
@@ -0,0 +1,2459 @@
1/* $OpenBSD: strtod.c,v 1.30 2006/10/30 18:30:52 deraadt 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#include <sys/types.h>
93#if defined(__m68k__) || defined(__sparc__) || defined(__i386__) || \
94 defined(__mips__) || defined(__mips64__) || defined(__ns32k__) || \
95 defined(__alpha__) || defined(__powerpc__) || defined(__m88k__) || \
96 defined(__hppa__) || defined(__amd64__) || defined(__sh__) || \
97 defined(__sparc64__) || \
98 (defined(__arm__) && defined(__VFP_FP__))
99
100#if BYTE_ORDER == BIG_ENDIAN
101#define IEEE_BIG_ENDIAN
102#else
103#define IEEE_LITTLE_ENDIAN
104#endif
105#endif
106
107#if defined(__arm__) && !defined(__VFP_FP__)
108/*
109 * Although the CPU is little endian the FP has different
110 * byte and word endianness. The byte order is still little endian
111 * but the word order is big endian.
112 */
113#define IEEE_BIG_ENDIAN
114#endif
115
116#ifdef __vax__
117#define VAX
118#endif
119
120#define Long int32_t
121#define ULong u_int32_t
122
123#ifdef DEBUG
124#include "stdio.h"
125#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);}
126#endif
127
128#include "thread_private.h"
129
130_THREAD_PRIVATE_KEY(dtoa);
131_THREAD_PRIVATE_KEY(pow5mult);
132
133#ifdef __cplusplus
134#include "malloc.h"
135#include "memory.h"
136#else
137#include "stdlib.h"
138#include "string.h"
139#include "locale.h"
140#endif
141
142#ifdef MALLOC
143extern void *MALLOC(size_t);
144#else
145#define MALLOC malloc
146#endif
147
148#include "ctype.h"
149#include "errno.h"
150
151#ifdef Bad_float_h
152#ifdef IEEE_BIG_ENDIAN
153#define IEEE_ARITHMETIC
154#endif
155#ifdef IEEE_LITTLE_ENDIAN
156#define IEEE_ARITHMETIC
157#endif
158
159#ifdef IEEE_ARITHMETIC
160#define DBL_DIG 15
161#define DBL_MAX_10_EXP 308
162#define DBL_MAX_EXP 1024
163#define FLT_RADIX 2
164#define FLT_ROUNDS 1
165#define DBL_MAX 1.7976931348623157e+308
166#endif
167
168#ifdef IBM
169#define DBL_DIG 16
170#define DBL_MAX_10_EXP 75
171#define DBL_MAX_EXP 63
172#define FLT_RADIX 16
173#define FLT_ROUNDS 0
174#define DBL_MAX 7.2370055773322621e+75
175#endif
176
177#ifdef VAX
178#define DBL_DIG 16
179#define DBL_MAX_10_EXP 38
180#define DBL_MAX_EXP 127
181#define FLT_RADIX 2
182#define FLT_ROUNDS 1
183#define DBL_MAX 1.7014118346046923e+38
184#endif
185
186#ifndef LONG_MAX
187#define LONG_MAX 2147483647
188#endif
189#else
190#include "float.h"
191#endif
192#ifndef __MATH_H__
193#include "math.h"
194#endif
195
196#ifdef __cplusplus
197extern "C" {
198#endif
199
200#ifndef CONST
201#define CONST const
202#endif
203
204#ifdef Unsigned_Shifts
205#define Sign_Extend(a,b) if (b < 0) a |= 0xffff0000;
206#else
207#define Sign_Extend(a,b) /*no-op*/
208#endif
209
210#if defined(IEEE_LITTLE_ENDIAN) + defined(IEEE_BIG_ENDIAN) + defined(VAX) + \
211 defined(IBM) != 1
212#error Exactly one of IEEE_LITTLE_ENDIAN IEEE_BIG_ENDIAN, VAX, or IBM should be defined.
213#endif
214
215typedef union {
216 double d;
217 ULong ul[2];
218} _double;
219#define value(x) ((x).d)
220#ifdef IEEE_LITTLE_ENDIAN
221#define word0(x) ((x).ul[1])
222#define word1(x) ((x).ul[0])
223#else
224#define word0(x) ((x).ul[0])
225#define word1(x) ((x).ul[1])
226#endif
227
228/* The following definition of Storeinc is appropriate for MIPS processors.
229 * An alternative that might be better on some machines is
230 * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff)
231 */
232#if defined(IEEE_LITTLE_ENDIAN) + defined(VAX) + defined(__arm__)
233#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \
234((unsigned short *)a)[0] = (unsigned short)c, a++)
235#else
236#define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \
237((unsigned short *)a)[1] = (unsigned short)c, a++)
238#endif
239
240/* #define P DBL_MANT_DIG */
241/* Ten_pmax = floor(P*log(2)/log(5)) */
242/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */
243/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */
244/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */
245
246#if defined(IEEE_LITTLE_ENDIAN) + defined(IEEE_BIG_ENDIAN)
247#define Exp_shift 20
248#define Exp_shift1 20
249#define Exp_msk1 0x100000
250#define Exp_msk11 0x100000
251#define Exp_mask 0x7ff00000
252#define P 53
253#define Bias 1023
254#define IEEE_Arith
255#define Emin (-1022)
256#define Exp_1 0x3ff00000
257#define Exp_11 0x3ff00000
258#define Ebits 11
259#define Frac_mask 0xfffff
260#define Frac_mask1 0xfffff
261#define Ten_pmax 22
262#define Bletch 0x10
263#define Bndry_mask 0xfffff
264#define Bndry_mask1 0xfffff
265#define LSB 1
266#define Sign_bit 0x80000000
267#define Log2P 1
268#define Tiny0 0
269#define Tiny1 1
270#define Quick_max 14
271#define Int_max 14
272#define Infinite(x) (word0(x) == 0x7ff00000) /* sufficient test for here */
273#else
274#undef Sudden_Underflow
275#define Sudden_Underflow
276#ifdef IBM
277#define Exp_shift 24
278#define Exp_shift1 24
279#define Exp_msk1 0x1000000
280#define Exp_msk11 0x1000000
281#define Exp_mask 0x7f000000
282#define P 14
283#define Bias 65
284#define Exp_1 0x41000000
285#define Exp_11 0x41000000
286#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */
287#define Frac_mask 0xffffff
288#define Frac_mask1 0xffffff
289#define Bletch 4
290#define Ten_pmax 22
291#define Bndry_mask 0xefffff
292#define Bndry_mask1 0xffffff
293#define LSB 1
294#define Sign_bit 0x80000000
295#define Log2P 4
296#define Tiny0 0x100000
297#define Tiny1 0
298#define Quick_max 14
299#define Int_max 15
300#else /* VAX */
301#define Exp_shift 23
302#define Exp_shift1 7
303#define Exp_msk1 0x80
304#define Exp_msk11 0x800000
305#define Exp_mask 0x7f80
306#define P 56
307#define Bias 129
308#define Exp_1 0x40800000
309#define Exp_11 0x4080
310#define Ebits 8
311#define Frac_mask 0x7fffff
312#define Frac_mask1 0xffff007f
313#define Ten_pmax 24
314#define Bletch 2
315#define Bndry_mask 0xffff007f
316#define Bndry_mask1 0xffff007f
317#define LSB 0x10000
318#define Sign_bit 0x8000
319#define Log2P 1
320#define Tiny0 0x80
321#define Tiny1 0
322#define Quick_max 15
323#define Int_max 15
324#endif
325#endif
326
327#ifndef IEEE_Arith
328#define ROUND_BIASED
329#endif
330
331#ifdef RND_PRODQUOT
332#define rounded_product(a,b) a = rnd_prod(a, b)
333#define rounded_quotient(a,b) a = rnd_quot(a, b)
334extern double rnd_prod(double, double), rnd_quot(double, double);
335#else
336#define rounded_product(a,b) a *= b
337#define rounded_quotient(a,b) a /= b
338#endif
339
340#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1))
341#define Big1 0xffffffff
342
343#ifndef Just_16
344/* When Pack_32 is not defined, we store 16 bits per 32-bit Long.
345 * This makes some inner loops simpler and sometimes saves work
346 * during multiplications, but it often seems to make things slightly
347 * slower. Hence the default is now to store 32 bits per Long.
348 */
349#ifndef Pack_32
350#define Pack_32
351#endif
352#endif
353
354#define Kmax 15
355
356#ifdef __cplusplus
357extern "C" double strtod(const char *s00, char **se);
358extern "C" char *__dtoa(double d, int mode, int ndigits,
359 int *decpt, int *sign, char **rve);
360#endif
361
362 struct
363Bigint {
364 struct Bigint *next;
365 int k, maxwds, sign, wds;
366 ULong x[1];
367 };
368
369 typedef struct Bigint Bigint;
370
371 static Bigint *freelist[Kmax+1];
372
373#define PRIVATE_MEM 2304
374#define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
375 static double private_mem[PRIVATE_mem], *pmem_next = private_mem;
376
377 static Bigint *
378Balloc(int k)
379{
380 int x;
381 unsigned int len;
382 Bigint *rv;
383
384 _THREAD_PRIVATE_MUTEX_LOCK(dtoa);
385 if ((rv = freelist[k])) {
386 freelist[k] = rv->next;
387 }
388 else {
389 x = 1 << k;
390 len = (sizeof(Bigint) + (x-1)*sizeof(Long) + sizeof(double) - 1)
391 /sizeof(double);
392 if (pmem_next - private_mem + len <= PRIVATE_mem) {
393 rv = (Bigint *)pmem_next;
394 pmem_next += len;
395 }
396 else
397 rv = (Bigint *)MALLOC(len *sizeof(double));
398 rv->k = k;
399 rv->maxwds = x;
400 }
401 _THREAD_PRIVATE_MUTEX_UNLOCK(dtoa);
402 rv->sign = rv->wds = 0;
403 return rv;
404 }
405
406 static void
407Bfree(Bigint *v)
408{
409 if (v) {
410 _THREAD_PRIVATE_MUTEX_LOCK(dtoa);
411 v->next = freelist[v->k];
412 freelist[v->k] = v;
413 _THREAD_PRIVATE_MUTEX_UNLOCK(dtoa);
414 }
415 }
416
417#define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \
418y->wds*sizeof(Long) + 2*sizeof(int))
419
420/* return value is only used as a simple string, so mis-aligned parts
421 * inside the Bigint are not at risk on strict align architectures
422 */
423 static char *
424rv_alloc(int i)
425{
426 int j, k, *r;
427
428 j = sizeof(ULong);
429 for(k = 0;
430 sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= i;
431 j <<= 1)
432 k++;
433 r = (int*)Balloc(k);
434 *r = k;
435 return (char *)(r+1);
436 }
437
438 static char *
439nrv_alloc(char *s, char **rve, int n)
440{
441 char *rv, *t;
442
443 t = rv = rv_alloc(n);
444 while((*t = *s++) !=0)
445 t++;
446 if (rve)
447 *rve = t;
448 return rv;
449 }
450
451 void
452__freedtoa(char *s)
453{
454 Bigint *b = (Bigint *)((int *)s - 1);
455 b->maxwds = 1 << (b->k = *(int*)b);
456 Bfree(b);
457 }
458
459 static Bigint *
460multadd(Bigint *b, int m, int a) /* multiply by m and add a */
461{
462 int i, wds;
463 ULong *x, y;
464#ifdef Pack_32
465 ULong xi, z;
466#endif
467 Bigint *b1;
468
469 wds = b->wds;
470 x = b->x;
471 i = 0;
472 do {
473#ifdef Pack_32
474 xi = *x;
475 y = (xi & 0xffff) * m + a;
476 z = (xi >> 16) * m + (y >> 16);
477 a = (int)(z >> 16);
478 *x++ = (z << 16) + (y & 0xffff);
479#else
480 y = *x * m + a;
481 a = (int)(y >> 16);
482 *x++ = y & 0xffff;
483#endif
484 }
485 while(++i < wds);
486 if (a) {
487 if (wds >= b->maxwds) {
488 b1 = Balloc(b->k+1);
489 Bcopy(b1, b);
490 Bfree(b);
491 b = b1;
492 }
493 b->x[wds++] = a;
494 b->wds = wds;
495 }
496 return b;
497 }
498
499 static Bigint *
500s2b(CONST char *s, int nd0, int nd, ULong y9)
501{
502 Bigint *b;
503 int i, k;
504 Long x, y;
505
506 x = (nd + 8) / 9;
507 for(k = 0, y = 1; x > y; y <<= 1, k++) ;
508#ifdef Pack_32
509 b = Balloc(k);
510 b->x[0] = y9;
511 b->wds = 1;
512#else
513 b = Balloc(k+1);
514 b->x[0] = y9 & 0xffff;
515 b->wds = (b->x[1] = y9 >> 16) ? 2 : 1;
516#endif
517
518 i = 9;
519 if (9 < nd0) {
520 s += 9;
521 do b = multadd(b, 10, *s++ - '0');
522 while(++i < nd0);
523 s++;
524 }
525 else
526 s += 10;
527 for(; i < nd; i++)
528 b = multadd(b, 10, *s++ - '0');
529 return b;
530 }
531
532 static int
533hi0bits(ULong x)
534{
535 int k = 0;
536
537 if (!(x & 0xffff0000)) {
538 k = 16;
539 x <<= 16;
540 }
541 if (!(x & 0xff000000)) {
542 k += 8;
543 x <<= 8;
544 }
545 if (!(x & 0xf0000000)) {
546 k += 4;
547 x <<= 4;
548 }
549 if (!(x & 0xc0000000)) {
550 k += 2;
551 x <<= 2;
552 }
553 if (!(x & 0x80000000)) {
554 k++;
555 if (!(x & 0x40000000))
556 return 32;
557 }
558 return k;
559 }
560
561 static int
562lo0bits(ULong *y)
563{
564 int k;
565 ULong x = *y;
566
567 if (x & 7) {
568 if (x & 1)
569 return 0;
570 if (x & 2) {
571 *y = x >> 1;
572 return 1;
573 }
574 *y = x >> 2;
575 return 2;
576 }
577 k = 0;
578 if (!(x & 0xffff)) {
579 k = 16;
580 x >>= 16;
581 }
582 if (!(x & 0xff)) {
583 k += 8;
584 x >>= 8;
585 }
586 if (!(x & 0xf)) {
587 k += 4;
588 x >>= 4;
589 }
590 if (!(x & 0x3)) {
591 k += 2;
592 x >>= 2;
593 }
594 if (!(x & 1)) {
595 k++;
596 x >>= 1;
597 if (!(x & 1))
598 return 32;
599 }
600 *y = x;
601 return k;
602 }
603
604 static Bigint *
605i2b(int i)
606{
607 Bigint *b;
608
609 b = Balloc(1);
610 b->x[0] = i;
611 b->wds = 1;
612 return b;
613 }
614
615 static Bigint *
616mult(Bigint *a, Bigint *b)
617{
618 Bigint *c;
619 int k, wa, wb, wc;
620 ULong carry, y, z;
621 ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
622#ifdef Pack_32
623 ULong z2;
624#endif
625
626 if (a->wds < b->wds) {
627 c = a;
628 a = b;
629 b = c;
630 }
631 k = a->k;
632 wa = a->wds;
633 wb = b->wds;
634 wc = wa + wb;
635 if (wc > a->maxwds)
636 k++;
637 c = Balloc(k);
638 for(x = c->x, xa = x + wc; x < xa; x++)
639 *x = 0;
640 xa = a->x;
641 xae = xa + wa;
642 xb = b->x;
643 xbe = xb + wb;
644 xc0 = c->x;
645#ifdef Pack_32
646 for(; xb < xbe; xb++, xc0++) {
647 if ((y = *xb & 0xffff)) {
648 x = xa;
649 xc = xc0;
650 carry = 0;
651 do {
652 z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
653 carry = z >> 16;
654 z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
655 carry = z2 >> 16;
656 Storeinc(xc, z2, z);
657 }
658 while(x < xae);
659 *xc = carry;
660 }
661 if ((y = *xb >> 16)) {
662 x = xa;
663 xc = xc0;
664 carry = 0;
665 z2 = *xc;
666 do {
667 z = (*x & 0xffff) * y + (*xc >> 16) + carry;
668 carry = z >> 16;
669 Storeinc(xc, z, z2);
670 z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
671 carry = z2 >> 16;
672 }
673 while(x < xae);
674 *xc = z2;
675 }
676 }
677#else
678 for(; xb < xbe; xc0++) {
679 if (y = *xb++) {
680 x = xa;
681 xc = xc0;
682 carry = 0;
683 do {
684 z = *x++ * y + *xc + carry;
685 carry = z >> 16;
686 *xc++ = z & 0xffff;
687 }
688 while(x < xae);
689 *xc = carry;
690 }
691 }
692#endif
693 for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
694 c->wds = wc;
695 return c;
696 }
697
698 static Bigint *p5s;
699
700 static Bigint *
701pow5mult(Bigint *b, int k)
702{
703 Bigint *b1, *p5, *p51;
704 int i;
705 static int p05[3] = { 5, 25, 125 };
706
707 if ((i = k & 3))
708 b = multadd(b, p05[i-1], 0);
709
710 if (!(k >>= 2))
711 return b;
712 if (!(p5 = p5s)) {
713 /* first time */
714 _THREAD_PRIVATE_MUTEX_LOCK(pow5mult);
715 p5 = p5s = i2b(625);
716 p5->next = 0;
717 _THREAD_PRIVATE_MUTEX_UNLOCK(pow5mult);
718 }
719 for(;;) {
720 if (k & 1) {
721 b1 = mult(b, p5);
722 Bfree(b);
723 b = b1;
724 }
725 if (!(k >>= 1))
726 break;
727 if (!(p51 = p5->next)) {
728 _THREAD_PRIVATE_MUTEX_LOCK(pow5mult);
729 if (!(p51 = p5->next)) {
730 p51 = p5->next = mult(p5,p5);
731 p51->next = 0;
732 }
733 _THREAD_PRIVATE_MUTEX_UNLOCK(pow5mult);
734 }
735 p5 = p51;
736 }
737 return b;
738 }
739
740 static Bigint *
741lshift(Bigint *b, int k)
742{
743 int i, k1, n, n1;
744 Bigint *b1;
745 ULong *x, *x1, *xe, z;
746
747#ifdef Pack_32
748 n = k >> 5;
749#else
750 n = k >> 4;
751#endif
752 k1 = b->k;
753 n1 = n + b->wds + 1;
754 for(i = b->maxwds; n1 > i; i <<= 1)
755 k1++;
756 b1 = Balloc(k1);
757 x1 = b1->x;
758 for(i = 0; i < n; i++)
759 *x1++ = 0;
760 x = b->x;
761 xe = x + b->wds;
762#ifdef Pack_32
763 if (k &= 0x1f) {
764 k1 = 32 - k;
765 z = 0;
766 do {
767 *x1++ = *x << k | z;
768 z = *x++ >> k1;
769 }
770 while(x < xe);
771 if ((*x1 = z))
772 ++n1;
773 }
774#else
775 if (k &= 0xf) {
776 k1 = 16 - k;
777 z = 0;
778 do {
779 *x1++ = *x << k & 0xffff | z;
780 z = *x++ >> k1;
781 }
782 while(x < xe);
783 if (*x1 = z)
784 ++n1;
785 }
786#endif
787 else do
788 *x1++ = *x++;
789 while(x < xe);
790 b1->wds = n1 - 1;
791 Bfree(b);
792 return b1;
793 }
794
795 static int
796cmp(Bigint *a, Bigint *b)
797{
798 ULong *xa, *xa0, *xb, *xb0;
799 int i, j;
800
801 i = a->wds;
802 j = b->wds;
803#ifdef DEBUG
804 if (i > 1 && !a->x[i-1])
805 Bug("cmp called with a->x[a->wds-1] == 0");
806 if (j > 1 && !b->x[j-1])
807 Bug("cmp called with b->x[b->wds-1] == 0");
808#endif
809 if (i -= j)
810 return i;
811 xa0 = a->x;
812 xa = xa0 + j;
813 xb0 = b->x;
814 xb = xb0 + j;
815 for(;;) {
816 if (*--xa != *--xb)
817 return *xa < *xb ? -1 : 1;
818 if (xa <= xa0)
819 break;
820 }
821 return 0;
822 }
823
824 static Bigint *
825diff(Bigint *a, Bigint *b)
826{
827 Bigint *c;
828 int i, wa, wb;
829 Long borrow, y; /* We need signed shifts here. */
830 ULong *xa, *xae, *xb, *xbe, *xc;
831#ifdef Pack_32
832 Long z;
833#endif
834
835 i = cmp(a,b);
836 if (!i) {
837 c = Balloc(0);
838 c->wds = 1;
839 c->x[0] = 0;
840 return c;
841 }
842 if (i < 0) {
843 c = a;
844 a = b;
845 b = c;
846 i = 1;
847 }
848 else
849 i = 0;
850 c = Balloc(a->k);
851 c->sign = i;
852 wa = a->wds;
853 xa = a->x;
854 xae = xa + wa;
855 wb = b->wds;
856 xb = b->x;
857 xbe = xb + wb;
858 xc = c->x;
859 borrow = 0;
860#ifdef Pack_32
861 do {
862 y = (*xa & 0xffff) - (*xb & 0xffff) + borrow;
863 borrow = y >> 16;
864 Sign_Extend(borrow, y);
865 z = (*xa++ >> 16) - (*xb++ >> 16) + borrow;
866 borrow = z >> 16;
867 Sign_Extend(borrow, z);
868 Storeinc(xc, z, y);
869 }
870 while(xb < xbe);
871 while(xa < xae) {
872 y = (*xa & 0xffff) + borrow;
873 borrow = y >> 16;
874 Sign_Extend(borrow, y);
875 z = (*xa++ >> 16) + borrow;
876 borrow = z >> 16;
877 Sign_Extend(borrow, z);
878 Storeinc(xc, z, y);
879 }
880#else
881 do {
882 y = *xa++ - *xb++ + borrow;
883 borrow = y >> 16;
884 Sign_Extend(borrow, y);
885 *xc++ = y & 0xffff;
886 }
887 while(xb < xbe);
888 while(xa < xae) {
889 y = *xa++ + borrow;
890 borrow = y >> 16;
891 Sign_Extend(borrow, y);
892 *xc++ = y & 0xffff;
893 }
894#endif
895 while(!*--xc)
896 wa--;
897 c->wds = wa;
898 return c;
899 }
900
901 static double
902ulp(double _x)
903{
904 _double x;
905 Long L;
906 _double a;
907
908 value(x) = _x;
909 L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1;
910#ifndef Sudden_Underflow
911 if (L > 0) {
912#endif
913#ifdef IBM
914 L |= Exp_msk1 >> 4;
915#endif
916 word0(a) = L;
917 word1(a) = 0;
918#ifndef Sudden_Underflow
919 }
920 else {
921 L = -L >> Exp_shift;
922 if (L < Exp_shift) {
923 word0(a) = 0x80000 >> L;
924 word1(a) = 0;
925 }
926 else {
927 word0(a) = 0;
928 L -= Exp_shift;
929 word1(a) = L >= 31 ? 1 : 1 << 31 - L;
930 }
931 }
932#endif
933 return value(a);
934 }
935
936 static double
937b2d(Bigint *a, int *e)
938{
939 ULong *xa, *xa0, w, y, z;
940 int k;
941 _double d;
942#ifdef VAX
943 ULong d0, d1;
944#else
945#define d0 word0(d)
946#define d1 word1(d)
947#endif
948
949 xa0 = a->x;
950 xa = xa0 + a->wds;
951 y = *--xa;
952#ifdef DEBUG
953 if (!y) Bug("zero y in b2d");
954#endif
955 k = hi0bits(y);
956 *e = 32 - k;
957#ifdef Pack_32
958 if (k < Ebits) {
959 d0 = Exp_1 | y >> Ebits - k;
960 w = xa > xa0 ? *--xa : 0;
961 d1 = y << (32-Ebits) + k | w >> Ebits - k;
962 goto ret_d;
963 }
964 z = xa > xa0 ? *--xa : 0;
965 if (k -= Ebits) {
966 d0 = Exp_1 | y << k | z >> 32 - k;
967 y = xa > xa0 ? *--xa : 0;
968 d1 = z << k | y >> 32 - k;
969 }
970 else {
971 d0 = Exp_1 | y;
972 d1 = z;
973 }
974#else
975 if (k < Ebits + 16) {
976 z = xa > xa0 ? *--xa : 0;
977 d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
978 w = xa > xa0 ? *--xa : 0;
979 y = xa > xa0 ? *--xa : 0;
980 d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
981 goto ret_d;
982 }
983 z = xa > xa0 ? *--xa : 0;
984 w = xa > xa0 ? *--xa : 0;
985 k -= Ebits + 16;
986 d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
987 y = xa > xa0 ? *--xa : 0;
988 d1 = w << k + 16 | y << k;
989#endif
990 ret_d:
991#ifdef VAX
992 word0(d) = d0 >> 16 | d0 << 16;
993 word1(d) = d1 >> 16 | d1 << 16;
994#else
995#undef d0
996#undef d1
997#endif
998 return value(d);
999 }
1000
1001 static Bigint *
1002d2b(double _d, int *e, int *bits)
1003{
1004 Bigint *b;
1005 int de, i, k;
1006 ULong *x, y, z;
1007 _double d;
1008#ifdef VAX
1009 ULong d0, d1;
1010#endif
1011
1012 value(d) = _d;
1013#ifdef VAX
1014 d0 = word0(d) >> 16 | word0(d) << 16;
1015 d1 = word1(d) >> 16 | word1(d) << 16;
1016#else
1017#define d0 word0(d)
1018#define d1 word1(d)
1019#endif
1020
1021#ifdef Pack_32
1022 b = Balloc(1);
1023#else
1024 b = Balloc(2);
1025#endif
1026 x = b->x;
1027
1028 z = d0 & Frac_mask;
1029 d0 &= 0x7fffffff; /* clear sign bit, which we ignore */
1030#ifdef Sudden_Underflow
1031 de = (int)(d0 >> Exp_shift);
1032#ifndef IBM
1033 z |= Exp_msk11;
1034#endif
1035#else
1036 if (de = (int)(d0 >> Exp_shift))
1037 z |= Exp_msk1;
1038#endif
1039#ifdef Pack_32
1040 if (y = d1) {
1041 if (k = lo0bits(&y)) {
1042 x[0] = y | z << 32 - k;
1043 z >>= k;
1044 }
1045 else
1046 x[0] = y;
1047 i = b->wds = (x[1] = z) ? 2 : 1;
1048 }
1049 else {
1050#ifdef DEBUG
1051 if (!z)
1052 Bug("Zero passed to d2b");
1053#endif
1054 k = lo0bits(&z);
1055 x[0] = z;
1056 i = b->wds = 1;
1057 k += 32;
1058 }
1059#else
1060 if (y = d1) {
1061 if (k = lo0bits(&y))
1062 if (k >= 16) {
1063 x[0] = y | z << 32 - k & 0xffff;
1064 x[1] = z >> k - 16 & 0xffff;
1065 x[2] = z >> k;
1066 i = 2;
1067 }
1068 else {
1069 x[0] = y & 0xffff;
1070 x[1] = y >> 16 | z << 16 - k & 0xffff;
1071 x[2] = z >> k & 0xffff;
1072 x[3] = z >> k+16;
1073 i = 3;
1074 }
1075 else {
1076 x[0] = y & 0xffff;
1077 x[1] = y >> 16;
1078 x[2] = z & 0xffff;
1079 x[3] = z >> 16;
1080 i = 3;
1081 }
1082 }
1083 else {
1084#ifdef DEBUG
1085 if (!z)
1086 Bug("Zero passed to d2b");
1087#endif
1088 k = lo0bits(&z);
1089 if (k >= 16) {
1090 x[0] = z;
1091 i = 0;
1092 }
1093 else {
1094 x[0] = z & 0xffff;
1095 x[1] = z >> 16;
1096 i = 1;
1097 }
1098 k += 32;
1099 }
1100 while(!x[i])
1101 --i;
1102 b->wds = i + 1;
1103#endif
1104#ifndef Sudden_Underflow
1105 if (de) {
1106#endif
1107#ifdef IBM
1108 *e = (de - Bias - (P-1) << 2) + k;
1109 *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask);
1110#else
1111 *e = de - Bias - (P-1) + k;
1112 *bits = P - k;
1113#endif
1114#ifndef Sudden_Underflow
1115 }
1116 else {
1117 *e = de - Bias - (P-1) + 1 + k;
1118#ifdef Pack_32
1119 *bits = 32*i - hi0bits(x[i-1]);
1120#else
1121 *bits = (i+2)*16 - hi0bits(x[i]);
1122#endif
1123 }
1124#endif
1125 return b;
1126 }
1127#undef d0
1128#undef d1
1129
1130 static double
1131ratio(Bigint *a, Bigint *b)
1132{
1133 _double da, db;
1134 int k, ka, kb;
1135
1136 value(da) = b2d(a, &ka);
1137 value(db) = b2d(b, &kb);
1138#ifdef Pack_32
1139 k = ka - kb + 32*(a->wds - b->wds);
1140#else
1141 k = ka - kb + 16*(a->wds - b->wds);
1142#endif
1143#ifdef IBM
1144 if (k > 0) {
1145 word0(da) += (k >> 2)*Exp_msk1;
1146 if (k &= 3)
1147 da *= 1 << k;
1148 }
1149 else {
1150 k = -k;
1151 word0(db) += (k >> 2)*Exp_msk1;
1152 if (k &= 3)
1153 db *= 1 << k;
1154 }
1155#else
1156 if (k > 0)
1157 word0(da) += k*Exp_msk1;
1158 else {
1159 k = -k;
1160 word0(db) += k*Exp_msk1;
1161 }
1162#endif
1163 return value(da) / value(db);
1164 }
1165
1166static CONST double
1167tens[] = {
1168 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
1169 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
1170 1e20, 1e21, 1e22
1171#ifdef VAX
1172 , 1e23, 1e24
1173#endif
1174 };
1175
1176#ifdef IEEE_Arith
1177static CONST double bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
1178static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
1179#define n_bigtens 5
1180#else
1181#ifdef IBM
1182static CONST double bigtens[] = { 1e16, 1e32, 1e64 };
1183static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64 };
1184#define n_bigtens 3
1185#else
1186static CONST double bigtens[] = { 1e16, 1e32 };
1187static CONST double tinytens[] = { 1e-16, 1e-32 };
1188#define n_bigtens 2
1189#endif
1190#endif
1191
1192 double
1193strtod(CONST char *s00, char **se)
1194{
1195 int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
1196 e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
1197 CONST char *s, *s0, *s1;
1198 double aadj, aadj1, adj;
1199 /*
1200 * volatile forces mem update for FPUs where reg size != sizeof double,
1201 * which should trigger ERANGE in the case of underflow.
1202 */
1203 volatile _double rv;
1204 _double rv0;
1205 Long L;
1206 ULong y, z;
1207 Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
1208
1209 CONST char decimal_point = localeconv()->decimal_point[0];
1210
1211 sign = nz0 = nz = 0;
1212 value(rv) = 0.;
1213
1214
1215 for(s = s00; isspace((unsigned char) *s); s++)
1216 ;
1217
1218 if (*s == '-') {
1219 sign = 1;
1220 s++;
1221 } else if (*s == '+') {
1222 s++;
1223 }
1224
1225 if (*s == '\0') {
1226 s = s00;
1227 goto ret;
1228 }
1229
1230 if (*s == '0') {
1231 nz0 = 1;
1232 while(*++s == '0') ;
1233 if (!*s)
1234 goto ret;
1235 }
1236 s0 = s;
1237 y = z = 0;
1238 for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
1239 if (nd < 9)
1240 y = 10*y + c - '0';
1241 else if (nd < 16)
1242 z = 10*z + c - '0';
1243 nd0 = nd;
1244 if (c == decimal_point) {
1245 c = *++s;
1246 if (!nd) {
1247 for(; c == '0'; c = *++s)
1248 nz++;
1249 if (c > '0' && c <= '9') {
1250 s0 = s;
1251 nf += nz;
1252 nz = 0;
1253 goto have_dig;
1254 }
1255 goto dig_done;
1256 }
1257 for(; c >= '0' && c <= '9'; c = *++s) {
1258 have_dig:
1259 nz++;
1260 if (c -= '0') {
1261 nf += nz;
1262 for(i = 1; i < nz; i++)
1263 if (nd++ < 9)
1264 y *= 10;
1265 else if (nd <= DBL_DIG + 1)
1266 z *= 10;
1267 if (nd++ < 9)
1268 y = 10*y + c;
1269 else if (nd <= DBL_DIG + 1)
1270 z = 10*z + c;
1271 nz = 0;
1272 }
1273 }
1274 }
1275 dig_done:
1276 e = 0;
1277 if (c == 'e' || c == 'E') {
1278 if (!nd && !nz && !nz0) {
1279 s = s00;
1280 goto ret;
1281 }
1282 s00 = s;
1283 esign = 0;
1284 switch(c = *++s) {
1285 case '-':
1286 esign = 1;
1287 case '+':
1288 c = *++s;
1289 }
1290 if (c >= '0' && c <= '9') {
1291 while(c == '0')
1292 c = *++s;
1293 if (c > '0' && c <= '9') {
1294 L = c - '0';
1295 s1 = s;
1296 while((c = *++s) >= '0' && c <= '9')
1297 L = 10*L + c - '0';
1298 if (s - s1 > 8 || L > 19999)
1299 /* Avoid confusion from exponents
1300 * so large that e might overflow.
1301 */
1302 e = 19999; /* safe for 16 bit ints */
1303 else
1304 e = (int)L;
1305 if (esign)
1306 e = -e;
1307 }
1308 else
1309 e = 0;
1310 }
1311 else
1312 s = s00;
1313 }
1314 if (!nd) {
1315 if (!nz && !nz0)
1316 s = s00;
1317 goto ret;
1318 }
1319 e1 = e -= nf;
1320
1321 /* Now we have nd0 digits, starting at s0, followed by a
1322 * decimal point, followed by nd-nd0 digits. The number we're
1323 * after is the integer represented by those digits times
1324 * 10**e */
1325
1326 if (!nd0)
1327 nd0 = nd;
1328 k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
1329 value(rv) = y;
1330 if (k > 9)
1331 value(rv) = tens[k - 9] * value(rv) + z;
1332 bd0 = 0;
1333 if (nd <= DBL_DIG
1334#ifndef RND_PRODQUOT
1335 && FLT_ROUNDS == 1
1336#endif
1337 ) {
1338 if (!e)
1339 goto ret;
1340 if (e > 0) {
1341 if (e <= Ten_pmax) {
1342#ifdef VAX
1343 goto vax_ovfl_check;
1344#else
1345 /* value(rv) = */ rounded_product(value(rv),
1346 tens[e]);
1347 goto ret;
1348#endif
1349 }
1350 i = DBL_DIG - nd;
1351 if (e <= Ten_pmax + i) {
1352 /* A fancier test would sometimes let us do
1353 * this for larger i values.
1354 */
1355 e -= i;
1356 value(rv) *= tens[i];
1357#ifdef VAX
1358 /* VAX exponent range is so narrow we must
1359 * worry about overflow here...
1360 */
1361 vax_ovfl_check:
1362 word0(rv) -= P*Exp_msk1;
1363 /* value(rv) = */ rounded_product(value(rv),
1364 tens[e]);
1365 if ((word0(rv) & Exp_mask)
1366 > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
1367 goto ovfl;
1368 word0(rv) += P*Exp_msk1;
1369#else
1370 /* value(rv) = */ rounded_product(value(rv),
1371 tens[e]);
1372#endif
1373 goto ret;
1374 }
1375 }
1376#ifndef Inaccurate_Divide
1377 else if (e >= -Ten_pmax) {
1378 /* value(rv) = */ rounded_quotient(value(rv),
1379 tens[-e]);
1380 goto ret;
1381 }
1382#endif
1383 }
1384 e1 += nd - k;
1385
1386 /* Get starting approximation = rv * 10**e1 */
1387
1388 if (e1 > 0) {
1389 if (i = e1 & 15)
1390 value(rv) *= tens[i];
1391 if (e1 &= ~15) {
1392 if (e1 > DBL_MAX_10_EXP) {
1393 ovfl:
1394 errno = ERANGE;
1395#ifndef Bad_float_h
1396 value(rv) = HUGE_VAL;
1397#else
1398 /* Can't trust HUGE_VAL */
1399#ifdef IEEE_Arith
1400 word0(rv) = Exp_mask;
1401 word1(rv) = 0;
1402#else
1403 word0(rv) = Big0;
1404 word1(rv) = Big1;
1405#endif
1406#endif
1407 if (bd0)
1408 goto retfree;
1409 goto ret;
1410 }
1411 if (e1 >>= 4) {
1412 for(j = 0; e1 > 1; j++, e1 >>= 1)
1413 if (e1 & 1)
1414 value(rv) *= bigtens[j];
1415 /* The last multiplication could overflow. */
1416 word0(rv) -= P*Exp_msk1;
1417 value(rv) *= bigtens[j];
1418 if ((z = word0(rv) & Exp_mask)
1419 > Exp_msk1*(DBL_MAX_EXP+Bias-P))
1420 goto ovfl;
1421 if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {
1422 /* set to largest number */
1423 /* (Can't trust DBL_MAX) */
1424 word0(rv) = Big0;
1425 word1(rv) = Big1;
1426 }
1427 else
1428 word0(rv) += P*Exp_msk1;
1429 }
1430
1431 }
1432 }
1433 else if (e1 < 0) {
1434 e1 = -e1;
1435 if (i = e1 & 15)
1436 value(rv) /= tens[i];
1437 if (e1 &= ~15) {
1438 e1 >>= 4;
1439 if (e1 >= 1 << n_bigtens)
1440 goto undfl;
1441 for(j = 0; e1 > 1; j++, e1 >>= 1)
1442 if (e1 & 1)
1443 value(rv) *= tinytens[j];
1444 /* The last multiplication could underflow. */
1445 value(rv0) = value(rv);
1446 value(rv) *= tinytens[j];
1447 if (!value(rv)) {
1448 value(rv) = 2.*value(rv0);
1449 value(rv) *= tinytens[j];
1450 if (!value(rv)) {
1451 undfl:
1452 value(rv) = 0.;
1453 errno = ERANGE;
1454 if (bd0)
1455 goto retfree;
1456 goto ret;
1457 }
1458 word0(rv) = Tiny0;
1459 word1(rv) = Tiny1;
1460 /* The refinement below will clean
1461 * this approximation up.
1462 */
1463 }
1464 }
1465 }
1466
1467 /* Now the hard part -- adjusting rv to the correct value.*/
1468
1469 /* Put digits into bd: true value = bd * 10^e */
1470
1471 bd0 = s2b(s0, nd0, nd, y);
1472
1473 for(;;) {
1474 bd = Balloc(bd0->k);
1475 Bcopy(bd, bd0);
1476 bb = d2b(value(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */
1477 bs = i2b(1);
1478
1479 if (e >= 0) {
1480 bb2 = bb5 = 0;
1481 bd2 = bd5 = e;
1482 }
1483 else {
1484 bb2 = bb5 = -e;
1485 bd2 = bd5 = 0;
1486 }
1487 if (bbe >= 0)
1488 bb2 += bbe;
1489 else
1490 bd2 -= bbe;
1491 bs2 = bb2;
1492#ifdef Sudden_Underflow
1493#ifdef IBM
1494 j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3);
1495#else
1496 j = P + 1 - bbbits;
1497#endif
1498#else
1499 i = bbe + bbbits - 1; /* logb(rv) */
1500 if (i < Emin) /* denormal */
1501 j = bbe + (P-Emin);
1502 else
1503 j = P + 1 - bbbits;
1504#endif
1505 bb2 += j;
1506 bd2 += j;
1507 i = bb2 < bd2 ? bb2 : bd2;
1508 if (i > bs2)
1509 i = bs2;
1510 if (i > 0) {
1511 bb2 -= i;
1512 bd2 -= i;
1513 bs2 -= i;
1514 }
1515 if (bb5 > 0) {
1516 bs = pow5mult(bs, bb5);
1517 bb1 = mult(bs, bb);
1518 Bfree(bb);
1519 bb = bb1;
1520 }
1521 if (bb2 > 0)
1522 bb = lshift(bb, bb2);
1523 if (bd5 > 0)
1524 bd = pow5mult(bd, bd5);
1525 if (bd2 > 0)
1526 bd = lshift(bd, bd2);
1527 if (bs2 > 0)
1528 bs = lshift(bs, bs2);
1529 delta = diff(bb, bd);
1530 dsign = delta->sign;
1531 delta->sign = 0;
1532 i = cmp(delta, bs);
1533 if (i < 0) {
1534 /* Error is less than half an ulp -- check for
1535 * special case of mantissa a power of two.
1536 */
1537 if (dsign || word1(rv) || word0(rv) & Bndry_mask)
1538 break;
1539 delta = lshift(delta,Log2P);
1540 if (cmp(delta, bs) > 0)
1541 goto drop_down;
1542 break;
1543 }
1544 if (i == 0) {
1545 /* exactly half-way between */
1546 if (dsign) {
1547 if ((word0(rv) & Bndry_mask1) == Bndry_mask1
1548 && word1(rv) == 0xffffffff) {
1549 /*boundary case -- increment exponent*/
1550 word0(rv) = (word0(rv) & Exp_mask)
1551 + Exp_msk1
1552#ifdef IBM
1553 | Exp_msk1 >> 4
1554#endif
1555 ;
1556 word1(rv) = 0;
1557 break;
1558 }
1559 }
1560 else if (!(word0(rv) & Bndry_mask) && !word1(rv)) {
1561 drop_down:
1562 /* boundary case -- decrement exponent */
1563#ifdef Sudden_Underflow
1564 L = word0(rv) & Exp_mask;
1565#ifdef IBM
1566 if (L < Exp_msk1)
1567#else
1568 if (L <= Exp_msk1)
1569#endif
1570 goto undfl;
1571 L -= Exp_msk1;
1572#else
1573 L = (word0(rv) & Exp_mask) - Exp_msk1;
1574#endif
1575 word0(rv) = L | Bndry_mask1;
1576 word1(rv) = 0xffffffff;
1577#ifdef IBM
1578 goto cont;
1579#else
1580 break;
1581#endif
1582 }
1583#ifndef ROUND_BIASED
1584 if (!(word1(rv) & LSB))
1585 break;
1586#endif
1587 if (dsign)
1588 value(rv) += ulp(value(rv));
1589#ifndef ROUND_BIASED
1590 else {
1591 value(rv) -= ulp(value(rv));
1592#ifndef Sudden_Underflow
1593 if (!value(rv))
1594 goto undfl;
1595#endif
1596 }
1597#endif
1598 break;
1599 }
1600 if ((aadj = ratio(delta, bs)) <= 2.) {
1601 if (dsign)
1602 aadj = aadj1 = 1.;
1603 else if (word1(rv) || word0(rv) & Bndry_mask) {
1604#ifndef Sudden_Underflow
1605 if (word1(rv) == Tiny1 && !word0(rv))
1606 goto undfl;
1607#endif
1608 aadj = 1.;
1609 aadj1 = -1.;
1610 }
1611 else {
1612 /* special case -- power of FLT_RADIX to be */
1613 /* rounded down... */
1614
1615 if (aadj < 2./FLT_RADIX)
1616 aadj = 1./FLT_RADIX;
1617 else
1618 aadj *= 0.5;
1619 aadj1 = -aadj;
1620 }
1621 }
1622 else {
1623 aadj *= 0.5;
1624 aadj1 = dsign ? aadj : -aadj;
1625#ifdef Check_FLT_ROUNDS
1626 switch(FLT_ROUNDS) {
1627 case 2: /* towards +infinity */
1628 aadj1 -= 0.5;
1629 break;
1630 case 0: /* towards 0 */
1631 case 3: /* towards -infinity */
1632 aadj1 += 0.5;
1633 }
1634#else
1635 if (FLT_ROUNDS == 0)
1636 aadj1 += 0.5;
1637#endif
1638 }
1639 y = word0(rv) & Exp_mask;
1640
1641 /* Check for overflow */
1642
1643 if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
1644 value(rv0) = value(rv);
1645 word0(rv) -= P*Exp_msk1;
1646 adj = aadj1 * ulp(value(rv));
1647 value(rv) += adj;
1648 if ((word0(rv) & Exp_mask) >=
1649 Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
1650 if (word0(rv0) == Big0 && word1(rv0) == Big1)
1651 goto ovfl;
1652 word0(rv) = Big0;
1653 word1(rv) = Big1;
1654 goto cont;
1655 }
1656 else
1657 word0(rv) += P*Exp_msk1;
1658 }
1659 else {
1660#ifdef Sudden_Underflow
1661 if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
1662 value(rv0) = value(rv);
1663 word0(rv) += P*Exp_msk1;
1664 adj = aadj1 * ulp(value(rv));
1665 value(rv) += adj;
1666#ifdef IBM
1667 if ((word0(rv) & Exp_mask) < P*Exp_msk1)
1668#else
1669 if ((word0(rv) & Exp_mask) <= P*Exp_msk1)
1670#endif
1671 {
1672 if (word0(rv0) == Tiny0
1673 && word1(rv0) == Tiny1)
1674 goto undfl;
1675 word0(rv) = Tiny0;
1676 word1(rv) = Tiny1;
1677 goto cont;
1678 }
1679 else
1680 word0(rv) -= P*Exp_msk1;
1681 }
1682 else {
1683 adj = aadj1 * ulp(value(rv));
1684 value(rv) += adj;
1685 }
1686#else
1687 /* Compute adj so that the IEEE rounding rules will
1688 * correctly round rv + adj in some half-way cases.
1689 * If rv * ulp(rv) is denormalized (i.e.,
1690 * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid
1691 * trouble from bits lost to denormalization;
1692 * example: 1.2e-307 .
1693 */
1694 if (y <= (P-1)*Exp_msk1 && aadj >= 1.) {
1695 aadj1 = (double)(int)(aadj + 0.5);
1696 if (!dsign)
1697 aadj1 = -aadj1;
1698 }
1699 adj = aadj1 * ulp(value(rv));
1700 value(rv) += adj;
1701#endif
1702 }
1703 z = word0(rv) & Exp_mask;
1704 if (y == z) {
1705 /* Can we stop now? */
1706 L = aadj;
1707 aadj -= L;
1708 /* The tolerances below are conservative. */
1709 if (dsign || word1(rv) || word0(rv) & Bndry_mask) {
1710 if (aadj < .4999999 || aadj > .5000001)
1711 break;
1712 }
1713 else if (aadj < .4999999/FLT_RADIX)
1714 break;
1715 }
1716 cont:
1717 Bfree(bb);
1718 Bfree(bd);
1719 Bfree(bs);
1720 Bfree(delta);
1721 }
1722 retfree:
1723 Bfree(bb);
1724 Bfree(bd);
1725 Bfree(bs);
1726 Bfree(bd0);
1727 Bfree(delta);
1728 ret:
1729 if (se)
1730 *se = (char *)s;
1731 return sign ? -value(rv) : value(rv);
1732 }
1733
1734 static int
1735quorem(Bigint *b, Bigint *S)
1736{
1737 int n;
1738 Long borrow, y;
1739 ULong carry, q, ys;
1740 ULong *bx, *bxe, *sx, *sxe;
1741#ifdef Pack_32
1742 Long z;
1743 ULong si, zs;
1744#endif
1745
1746 n = S->wds;
1747#ifdef DEBUG
1748 /*debug*/ if (b->wds > n)
1749 /*debug*/ Bug("oversize b in quorem");
1750#endif
1751 if (b->wds < n)
1752 return 0;
1753 sx = S->x;
1754 sxe = sx + --n;
1755 bx = b->x;
1756 bxe = bx + n;
1757 q = *bxe / (*sxe + 1); /* ensure q <= true quotient */
1758#ifdef DEBUG
1759 /*debug*/ if (q > 9)
1760 /*debug*/ Bug("oversized quotient in quorem");
1761#endif
1762 if (q) {
1763 borrow = 0;
1764 carry = 0;
1765 do {
1766#ifdef Pack_32
1767 si = *sx++;
1768 ys = (si & 0xffff) * q + carry;
1769 zs = (si >> 16) * q + (ys >> 16);
1770 carry = zs >> 16;
1771 y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
1772 borrow = y >> 16;
1773 Sign_Extend(borrow, y);
1774 z = (*bx >> 16) - (zs & 0xffff) + borrow;
1775 borrow = z >> 16;
1776 Sign_Extend(borrow, z);
1777 Storeinc(bx, z, y);
1778#else
1779 ys = *sx++ * q + carry;
1780 carry = ys >> 16;
1781 y = *bx - (ys & 0xffff) + borrow;
1782 borrow = y >> 16;
1783 Sign_Extend(borrow, y);
1784 *bx++ = y & 0xffff;
1785#endif
1786 }
1787 while(sx <= sxe);
1788 if (!*bxe) {
1789 bx = b->x;
1790 while(--bxe > bx && !*bxe)
1791 --n;
1792 b->wds = n;
1793 }
1794 }
1795 if (cmp(b, S) >= 0) {
1796 q++;
1797 borrow = 0;
1798 carry = 0;
1799 bx = b->x;
1800 sx = S->x;
1801 do {
1802#ifdef Pack_32
1803 si = *sx++;
1804 ys = (si & 0xffff) + carry;
1805 zs = (si >> 16) + (ys >> 16);
1806 carry = zs >> 16;
1807 y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
1808 borrow = y >> 16;
1809 Sign_Extend(borrow, y);
1810 z = (*bx >> 16) - (zs & 0xffff) + borrow;
1811 borrow = z >> 16;
1812 Sign_Extend(borrow, z);
1813 Storeinc(bx, z, y);
1814#else
1815 ys = *sx++ + carry;
1816 carry = ys >> 16;
1817 y = *bx - (ys & 0xffff) + borrow;
1818 borrow = y >> 16;
1819 Sign_Extend(borrow, y);
1820 *bx++ = y & 0xffff;
1821#endif
1822 }
1823 while(sx <= sxe);
1824 bx = b->x;
1825 bxe = bx + n;
1826 if (!*bxe) {
1827 while(--bxe > bx && !*bxe)
1828 --n;
1829 b->wds = n;
1830 }
1831 }
1832 return q;
1833 }
1834
1835/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
1836 *
1837 * Inspired by "How to Print Floating-Point Numbers Accurately" by
1838 * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101].
1839 *
1840 * Modifications:
1841 * 1. Rather than iterating, we use a simple numeric overestimate
1842 * to determine k = floor(log10(d)). We scale relevant
1843 * quantities using O(log2(k)) rather than O(k) multiplications.
1844 * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
1845 * try to generate digits strictly left to right. Instead, we
1846 * compute with fewer bits and propagate the carry if necessary
1847 * when rounding the final digit up. This is often faster.
1848 * 3. Under the assumption that input will be rounded nearest,
1849 * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
1850 * That is, we allow equality in stopping tests when the
1851 * round-nearest rule will give the same floating-point value
1852 * as would satisfaction of the stopping test with strict
1853 * inequality.
1854 * 4. We remove common factors of powers of 2 from relevant
1855 * quantities.
1856 * 5. When converting floating-point integers less than 1e16,
1857 * we use floating-point arithmetic rather than resorting
1858 * to multiple-precision integers.
1859 * 6. When asked to produce fewer than 15 digits, we first try
1860 * to get by with floating-point arithmetic; we resort to
1861 * multiple-precision integer arithmetic only if we cannot
1862 * guarantee that the floating-point calculation has given
1863 * the correctly rounded result. For k requested digits and
1864 * "uniformly" distributed input, the probability is
1865 * something like 10^(k-15) that we must resort to the Long
1866 * calculation.
1867 */
1868
1869 char *
1870__dtoa(double _d, int mode, int ndigits, int *decpt, int *sign, char **rve)
1871{
1872 /* Arguments ndigits, decpt, sign are similar to those
1873 of ecvt and fcvt; trailing zeros are suppressed from
1874 the returned string. If not null, *rve is set to point
1875 to the end of the return value. If d is +-Infinity or NaN,
1876 then *decpt is set to 9999.
1877
1878 mode:
1879 0 ==> shortest string that yields d when read in
1880 and rounded to nearest.
1881 1 ==> like 0, but with Steele & White stopping rule;
1882 e.g. with IEEE P754 arithmetic , mode 0 gives
1883 1e23 whereas mode 1 gives 9.999999999999999e22.
1884 2 ==> max(1,ndigits) significant digits. This gives a
1885 return value similar to that of ecvt, except
1886 that trailing zeros are suppressed.
1887 3 ==> through ndigits past the decimal point. This
1888 gives a return value similar to that from fcvt,
1889 except that trailing zeros are suppressed, and
1890 ndigits can be negative.
1891 4-9 should give the same return values as 2-3, i.e.,
1892 4 <= mode <= 9 ==> same return as mode
1893 2 + (mode & 1). These modes are mainly for
1894 debugging; often they run slower but sometimes
1895 faster than modes 2-3.
1896 4,5,8,9 ==> left-to-right digit generation.
1897 6-9 ==> don't try fast floating-point estimate
1898 (if applicable).
1899
1900 Values of mode other than 0-9 are treated as mode 0.
1901
1902 Sufficient space is allocated to the return value
1903 to hold the suppressed trailing zeros.
1904 */
1905
1906 int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1,
1907 j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
1908 spec_case, try_quick;
1909 Long L;
1910#ifndef Sudden_Underflow
1911 int denorm;
1912 ULong x;
1913#endif
1914 Bigint *b, *b1, *delta, *mlo, *mhi, *S;
1915 double ds;
1916 char *s, *s0;
1917 _double d, d2, eps;
1918
1919 value(d) = _d;
1920
1921 if (word0(d) & Sign_bit) {
1922 /* set sign for everything, including 0's and NaNs */
1923 *sign = 1;
1924 word0(d) &= ~Sign_bit; /* clear sign bit */
1925 }
1926 else
1927 *sign = 0;
1928
1929#if defined(IEEE_Arith) + defined(VAX)
1930#ifdef IEEE_Arith
1931 if ((word0(d) & Exp_mask) == Exp_mask)
1932#else
1933 if (word0(d) == 0x8000)
1934#endif
1935 {
1936 /* Infinity or NaN */
1937 *decpt = 9999;
1938#ifdef IEEE_Arith
1939 if (!word1(d) && !(word0(d) & 0xfffff))
1940 return nrv_alloc("Infinity", rve, 8);
1941#endif
1942 return nrv_alloc("NaN", rve, 3);
1943 }
1944#endif
1945#ifdef IBM
1946 value(d) += 0; /* normalize */
1947#endif
1948 if (!value(d)) {
1949 *decpt = 1;
1950 return nrv_alloc("0", rve, 1);
1951 }
1952
1953 b = d2b(value(d), &be, &bbits);
1954#ifdef Sudden_Underflow
1955 i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
1956#else
1957 if (i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) {
1958#endif
1959 value(d2) = value(d);
1960 word0(d2) &= Frac_mask1;
1961 word0(d2) |= Exp_11;
1962#ifdef IBM
1963 if (j = 11 - hi0bits(word0(d2) & Frac_mask))
1964 value(d2) /= 1 << j;
1965#endif
1966
1967 /* log(x) ~=~ log(1.5) + (x-1.5)/1.5
1968 * log10(x) = log(x) / log(10)
1969 * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
1970 * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
1971 *
1972 * This suggests computing an approximation k to log10(d) by
1973 *
1974 * k = (i - Bias)*0.301029995663981
1975 * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
1976 *
1977 * We want k to be too large rather than too small.
1978 * The error in the first-order Taylor series approximation
1979 * is in our favor, so we just round up the constant enough
1980 * to compensate for any error in the multiplication of
1981 * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
1982 * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
1983 * adding 1e-13 to the constant term more than suffices.
1984 * Hence we adjust the constant term to 0.1760912590558.
1985 * (We could get a more accurate k by invoking log10,
1986 * but this is probably not worthwhile.)
1987 */
1988
1989 i -= Bias;
1990#ifdef IBM
1991 i <<= 2;
1992 i += j;
1993#endif
1994#ifndef Sudden_Underflow
1995 denorm = 0;
1996 }
1997 else {
1998 /* d is denormalized */
1999
2000 i = bbits + be + (Bias + (P-1) - 1);
2001 x = i > 32 ? word0(d) << 64 - i | word1(d) >> i - 32
2002 : word1(d) << 32 - i;
2003 value(d2) = x;
2004 word0(d2) -= 31*Exp_msk1; /* adjust exponent */
2005 i -= (Bias + (P-1) - 1) + 1;
2006 denorm = 1;
2007 }
2008#endif
2009 ds = (value(d2)-1.5)*0.289529654602168 + 0.1760912590558 +
2010 i*0.301029995663981;
2011 k = (int)ds;
2012 if (ds < 0. && ds != k)
2013 k--; /* want k = floor(ds) */
2014 k_check = 1;
2015 if (k >= 0 && k <= Ten_pmax) {
2016 if (value(d) < tens[k])
2017 k--;
2018 k_check = 0;
2019 }
2020 j = bbits - i - 1;
2021 if (j >= 0) {
2022 b2 = 0;
2023 s2 = j;
2024 }
2025 else {
2026 b2 = -j;
2027 s2 = 0;
2028 }
2029 if (k >= 0) {
2030 b5 = 0;
2031 s5 = k;
2032 s2 += k;
2033 }
2034 else {
2035 b2 -= k;
2036 b5 = -k;
2037 s5 = 0;
2038 }
2039 if (mode < 0 || mode > 9)
2040 mode = 0;
2041 try_quick = 1;
2042 if (mode > 5) {
2043 mode -= 4;
2044 try_quick = 0;
2045 }
2046 leftright = 1;
2047 switch(mode) {
2048 case 0:
2049 case 1:
2050 ilim = ilim1 = -1;
2051 i = 18;
2052 ndigits = 0;
2053 break;
2054 case 2:
2055 leftright = 0;
2056 /* no break */
2057 case 4:
2058 if (ndigits <= 0)
2059 ndigits = 1;
2060 ilim = ilim1 = i = ndigits;
2061 break;
2062 case 3:
2063 leftright = 0;
2064 /* no break */
2065 case 5:
2066 i = ndigits + k + 1;
2067 ilim = i;
2068 ilim1 = i - 1;
2069 if (i <= 0)
2070 i = 1;
2071 }
2072 s = s0 = rv_alloc(i);
2073
2074 if (ilim >= 0 && ilim <= Quick_max && try_quick) {
2075
2076 /* Try to get by with floating-point arithmetic. */
2077
2078 i = 0;
2079 value(d2) = value(d);
2080 k0 = k;
2081 ilim0 = ilim;
2082 ieps = 2; /* conservative */
2083 if (k > 0) {
2084 ds = tens[k&0xf];
2085 j = k >> 4;
2086 if (j & Bletch) {
2087 /* prevent overflows */
2088 j &= Bletch - 1;
2089 value(d) /= bigtens[n_bigtens-1];
2090 ieps++;
2091 }
2092 for(; j; j >>= 1, i++)
2093 if (j & 1) {
2094 ieps++;
2095 ds *= bigtens[i];
2096 }
2097 value(d) /= ds;
2098 }
2099 else if (j1 = -k) {
2100 value(d) *= tens[j1 & 0xf];
2101 for(j = j1 >> 4; j; j >>= 1, i++)
2102 if (j & 1) {
2103 ieps++;
2104 value(d) *= bigtens[i];
2105 }
2106 }
2107 if (k_check && value(d) < 1. && ilim > 0) {
2108 if (ilim1 <= 0)
2109 goto fast_failed;
2110 ilim = ilim1;
2111 k--;
2112 value(d) *= 10.;
2113 ieps++;
2114 }
2115 value(eps) = ieps*value(d) + 7.;
2116 word0(eps) -= (P-1)*Exp_msk1;
2117 if (ilim == 0) {
2118 S = mhi = 0;
2119 value(d) -= 5.;
2120 if (value(d) > value(eps))
2121 goto one_digit;
2122 if (value(d) < -value(eps))
2123 goto no_digits;
2124 goto fast_failed;
2125 }
2126#ifndef No_leftright
2127 if (leftright) {
2128 /* Use Steele & White method of only
2129 * generating digits needed.
2130 */
2131 value(eps) = 0.5/tens[ilim-1] - value(eps);
2132 for(i = 0;;) {
2133 L = value(d);
2134 value(d) -= L;
2135 *s++ = '0' + (int)L;
2136 if (value(d) < value(eps))
2137 goto ret1;
2138 if (1. - value(d) < value(eps))
2139 goto bump_up;
2140 if (++i >= ilim)
2141 break;
2142 value(eps) *= 10.;
2143 value(d) *= 10.;
2144 }
2145 }
2146 else {
2147#endif
2148 /* Generate ilim digits, then fix them up. */
2149 value(eps) *= tens[ilim-1];
2150 for(i = 1;; i++, value(d) *= 10.) {
2151 L = value(d);
2152 value(d) -= L;
2153 *s++ = '0' + (int)L;
2154 if (i == ilim) {
2155 if (value(d) > 0.5 + value(eps))
2156 goto bump_up;
2157 else if (value(d) < 0.5 - value(eps)) {
2158 while(*--s == '0');
2159 s++;
2160 goto ret1;
2161 }
2162 break;
2163 }
2164 }
2165#ifndef No_leftright
2166 }
2167#endif
2168 fast_failed:
2169 s = s0;
2170 value(d) = value(d2);
2171 k = k0;
2172 ilim = ilim0;
2173 }
2174
2175 /* Do we have a "small" integer? */
2176
2177 if (be >= 0 && k <= Int_max) {
2178 /* Yes. */
2179 ds = tens[k];
2180 if (ndigits < 0 && ilim <= 0) {
2181 S = mhi = 0;
2182 if (ilim < 0 || value(d) <= 5*ds)
2183 goto no_digits;
2184 goto one_digit;
2185 }
2186 for(i = 1;; i++) {
2187 L = value(d) / ds;
2188 value(d) -= L*ds;
2189#ifdef Check_FLT_ROUNDS
2190 /* If FLT_ROUNDS == 2, L will usually be high by 1 */
2191 if (value(d) < 0) {
2192 L--;
2193 value(d) += ds;
2194 }
2195#endif
2196 *s++ = '0' + (int)L;
2197 if (i == ilim) {
2198 value(d) += value(d);
2199 if (value(d) > ds || value(d) == ds && L & 1) {
2200 bump_up:
2201 while(*--s == '9')
2202 if (s == s0) {
2203 k++;
2204 *s = '0';
2205 break;
2206 }
2207 ++*s++;
2208 }
2209 break;
2210 }
2211 if (!(value(d) *= 10.))
2212 break;
2213 }
2214 goto ret1;
2215 }
2216
2217 m2 = b2;
2218 m5 = b5;
2219 mhi = mlo = 0;
2220 if (leftright) {
2221 if (mode < 2) {
2222 i =
2223#ifndef Sudden_Underflow
2224 denorm ? be + (Bias + (P-1) - 1 + 1) :
2225#endif
2226#ifdef IBM
2227 1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3);
2228#else
2229 1 + P - bbits;
2230#endif
2231 }
2232 else {
2233 j = ilim - 1;
2234 if (m5 >= j)
2235 m5 -= j;
2236 else {
2237 s5 += j -= m5;
2238 b5 += j;
2239 m5 = 0;
2240 }
2241 if ((i = ilim) < 0) {
2242 m2 -= i;
2243 i = 0;
2244 }
2245 }
2246 b2 += i;
2247 s2 += i;
2248 mhi = i2b(1);
2249 }
2250 if (m2 > 0 && s2 > 0) {
2251 i = m2 < s2 ? m2 : s2;
2252 b2 -= i;
2253 m2 -= i;
2254 s2 -= i;
2255 }
2256 if (b5 > 0) {
2257 if (leftright) {
2258 if (m5 > 0) {
2259 mhi = pow5mult(mhi, m5);
2260 b1 = mult(mhi, b);
2261 Bfree(b);
2262 b = b1;
2263 }
2264 if (j = b5 - m5)
2265 b = pow5mult(b, j);
2266 }
2267 else
2268 b = pow5mult(b, b5);
2269 }
2270 S = i2b(1);
2271 if (s5 > 0)
2272 S = pow5mult(S, s5);
2273
2274 /* Check for special case that d is a normalized power of 2. */
2275
2276 if (mode < 2) {
2277 if (!word1(d) && !(word0(d) & Bndry_mask)
2278#ifndef Sudden_Underflow
2279 && word0(d) & Exp_mask
2280#endif
2281 ) {
2282 /* The special case */
2283 b2 += Log2P;
2284 s2 += Log2P;
2285 spec_case = 1;
2286 }
2287 else
2288 spec_case = 0;
2289 }
2290
2291 /* Arrange for convenient computation of quotients:
2292 * shift left if necessary so divisor has 4 leading 0 bits.
2293 *
2294 * Perhaps we should just compute leading 28 bits of S once
2295 * and for all and pass them and a shift to quorem, so it
2296 * can do shifts and ors to compute the numerator for q.
2297 */
2298#ifdef Pack_32
2299 if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f)
2300 i = 32 - i;
2301#else
2302 if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf)
2303 i = 16 - i;
2304#endif
2305 if (i > 4) {
2306 i -= 4;
2307 b2 += i;
2308 m2 += i;
2309 s2 += i;
2310 }
2311 else if (i < 4) {
2312 i += 28;
2313 b2 += i;
2314 m2 += i;
2315 s2 += i;
2316 }
2317 if (b2 > 0)
2318 b = lshift(b, b2);
2319 if (s2 > 0)
2320 S = lshift(S, s2);
2321 if (k_check) {
2322 if (cmp(b,S) < 0) {
2323 k--;
2324 b = multadd(b, 10, 0); /* we botched the k estimate */
2325 if (leftright)
2326 mhi = multadd(mhi, 10, 0);
2327 ilim = ilim1;
2328 }
2329 }
2330 if (ilim <= 0 && mode > 2) {
2331 if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) {
2332 /* no digits, fcvt style */
2333 no_digits:
2334 k = -1 - ndigits;
2335 goto ret;
2336 }
2337 one_digit:
2338 *s++ = '1';
2339 k++;
2340 goto ret;
2341 }
2342 if (leftright) {
2343 if (m2 > 0)
2344 mhi = lshift(mhi, m2);
2345
2346 /* Compute mlo -- check for special case
2347 * that d is a normalized power of 2.
2348 */
2349
2350 mlo = mhi;
2351 if (spec_case) {
2352 mhi = Balloc(mhi->k);
2353 Bcopy(mhi, mlo);
2354 mhi = lshift(mhi, Log2P);
2355 }
2356
2357 for(i = 1;;i++) {
2358 dig = quorem(b,S) + '0';
2359 /* Do we yet have the shortest decimal string
2360 * that will round to d?
2361 */
2362 j = cmp(b, mlo);
2363 delta = diff(S, mhi);
2364 j1 = delta->sign ? 1 : cmp(b, delta);
2365 Bfree(delta);
2366#ifndef ROUND_BIASED
2367 if (j1 == 0 && !mode && !(word1(d) & 1)) {
2368 if (dig == '9')
2369 goto round_9_up;
2370 if (j > 0)
2371 dig++;
2372 *s++ = dig;
2373 goto ret;
2374 }
2375#endif
2376 if (j < 0 || j == 0 && !mode
2377#ifndef ROUND_BIASED
2378 && !(word1(d) & 1)
2379#endif
2380 ) {
2381 if (j1 > 0) {
2382 b = lshift(b, 1);
2383 j1 = cmp(b, S);
2384 if ((j1 > 0 || j1 == 0 && dig & 1)
2385 && dig++ == '9')
2386 goto round_9_up;
2387 }
2388 *s++ = dig;
2389 goto ret;
2390 }
2391 if (j1 > 0) {
2392 if (dig == '9') { /* possible if i == 1 */
2393 round_9_up:
2394 *s++ = '9';
2395 goto roundoff;
2396 }
2397 *s++ = dig + 1;
2398 goto ret;
2399 }
2400 *s++ = dig;
2401 if (i == ilim)
2402 break;
2403 b = multadd(b, 10, 0);
2404 if (mlo == mhi)
2405 mlo = mhi = multadd(mhi, 10, 0);
2406 else {
2407 mlo = multadd(mlo, 10, 0);
2408 mhi = multadd(mhi, 10, 0);
2409 }
2410 }
2411 }
2412 else
2413 for(i = 1;; i++) {
2414 *s++ = dig = quorem(b,S) + '0';
2415 if (i >= ilim)
2416 break;
2417 b = multadd(b, 10, 0);
2418 }
2419
2420 /* Round off last digit */
2421
2422 b = lshift(b, 1);
2423 j = cmp(b, S);
2424 if (j > 0 || j == 0 && dig & 1) {
2425 roundoff:
2426 while(*--s == '9')
2427 if (s == s0) {
2428 k++;
2429 *s++ = '1';
2430 goto ret;
2431 }
2432 ++*s++;
2433 }
2434 else {
2435 while(*--s == '0');
2436 s++;
2437 }
2438 ret:
2439 Bfree(S);
2440 if (mhi) {
2441 if (mlo && mlo != mhi)
2442 Bfree(mlo);
2443 Bfree(mhi);
2444 }
2445 ret1:
2446 Bfree(b);
2447 if (s == s0) { /* don't return empty string */
2448 *s++ = '0';
2449 k = 0;
2450 }
2451 *s = 0;
2452 *decpt = k + 1;
2453 if (rve)
2454 *rve = s;
2455 return s0;
2456 }
2457#ifdef __cplusplus
2458}
2459#endif
diff --git a/src/lib/libc/stdlib/strtof.c b/src/lib/libc/stdlib/strtof.c
new file mode 100644
index 0000000000..8c8db47ad8
--- /dev/null
+++ b/src/lib/libc/stdlib/strtof.c
@@ -0,0 +1,39 @@
1/* $OpenBSD: strtof.c,v 1.1 2008/06/13 21:04:24 landry Exp $ */
2
3/*
4 * Copyright (c) 2008 Landry Breuil
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#include <math.h>
24
25float
26strtof(const char *s00, char **se)
27{
28 double d;
29
30 d = strtod(s00, se);
31 if (d > FLT_MAX) {
32 errno = ERANGE;
33 return (FLT_MAX);
34 } else if (d < -FLT_MAX) {
35 errno = ERANGE;
36 return (-FLT_MAX);
37 }
38 return ((float) d);
39}
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..84d9a0c427
--- /dev/null
+++ b/src/lib/libc/stdlib/strtol.3
@@ -0,0 +1,264 @@
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.19 2007/11/13 18:30:04 tobias Exp $
33.\"
34.Dd $Mdocdate: November 13 2007 $
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 <limits.h>
45.Fd #include <stdlib.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 <limits.h>
58.Fd #include <stdlib.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 return the result of the conversion,
155unless the value would underflow or overflow.
156If no conversion could be performed, 0 is returned;
157the global variable
158.Va errno
159is also set to
160.Er EINVAL,
161though this is not portable across all platforms.
162If overflow or underflow occurs,
163.Va errno
164is set to
165.Er ERANGE
166and the function return value is as follows:
167.Bl -column -offset indent "strtoimax" "overflow" "underflow"
168.It Sy Function Ta Sy underflow Ta Sy overflow
169.It Fn strtol Ta Dv LONG_MIN Ta Dv LONG_MAX
170.It Fn strtoll Ta Dv LLONG_MIN Ta Dv LLONG_MAX
171.It Fn strtoimax Ta Dv INTMAX_MIN Ta Dv INTMAX_MAX
172.It Fn strtoq Ta Dv LLONG_MIN Ta Dv LLONG_MAX
173.El
174.Sh EXAMPLES
175Ensuring that a string is a valid number (i.e., in range and containing no
176trailing characters) requires clearing
177.Va errno
178beforehand explicitly since
179.Va errno
180is not changed on a successful call to
181.Fn strtol ,
182and the return value of
183.Fn strtol
184cannot be used unambiguously to signal an error:
185.Bd -literal -offset indent
186char *ep;
187long lval;
188
189\&...
190
191errno = 0;
192lval = strtol(buf, &ep, 10);
193if (buf[0] == '\e0' || *ep != '\e0')
194 goto not_a_number;
195if (errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN))
196 goto out_of_range;
197.Ed
198.Pp
199This example will accept
200.Dq 12
201but not
202.Dq 12foo
203or
204.Dq 12\en .
205If trailing whitespace is acceptable, further checks must be done on
206.Va *ep ;
207alternately, use
208.Xr sscanf 3 .
209.Pp
210If
211.Fn strtol
212is being used instead of
213.Xr atoi 3 ,
214error checking is further complicated because the desired return value is an
215.Li int
216rather than a
217.Li long ;
218however, on some architectures integers and long integers are the same size.
219Thus the following is necessary:
220.Bd -literal -offset indent
221char *ep;
222int ival;
223long lval;
224
225\&...
226
227errno = 0;
228lval = strtol(buf, &ep, 10);
229if (buf[0] == '\e0' || *ep != '\e0')
230 goto not_a_number;
231if ((errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN)) ||
232 (lval > INT_MAX || lval < INT_MIN))
233 goto out_of_range;
234ival = lval;
235.Ed
236.Sh ERRORS
237.Bl -tag -width Er
238.It Bq Er ERANGE
239The given string was out of range; the value converted has been clamped.
240.El
241.Sh SEE ALSO
242.Xr atof 3 ,
243.Xr atoi 3 ,
244.Xr atol 3 ,
245.Xr atoll 3 ,
246.Xr sscanf 3 ,
247.Xr strtod 3 ,
248.Xr strtonum 3 ,
249.Xr strtoul 3
250.Sh STANDARDS
251The
252.Fn strtol ,
253.Fn strtoll ,
254and
255.Fn strtoimax
256functions conform to
257.St -ansiC-99 .
258The
259.Fn strtoq
260function is a
261.Bx
262extension and is provided for backwards compatibility with legacy programs.
263.Sh BUGS
264Ignores 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..58b4112ac3
--- /dev/null
+++ b/src/lib/libc/stdlib/strtonum.3
@@ -0,0 +1,152 @@
1.\" $OpenBSD: strtonum.3,v 1.14 2007/05/31 19:19:31 jmc Exp $
2.\"
3.\" Copyright (c) 2004 Ted Unangst
4.\"
5.\" Permission to use, copy, modify, and distribute this software for any
6.\" purpose with or without fee is hereby granted, provided that the above
7.\" copyright notice and this permission notice appear in all copies.
8.\"
9.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16.\"
17.Dd $Mdocdate: May 31 2007 $
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..a7c6bbfa18
--- /dev/null
+++ b/src/lib/libc/stdlib/strtoul.3
@@ -0,0 +1,248 @@
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.19 2007/11/13 18:30:04 tobias Exp $
33.\"
34.Dd $Mdocdate: November 13 2007 $
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 <limits.h>
45.Fd #include <stdlib.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 <limits.h>
58.Fd #include <stdlib.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 .
178If no conversion could be performed, 0 is returned;
179the global variable
180.Va errno
181is also set to
182.Er EINVAL,
183though this is not portable across all platforms.
184.Pp
185There is no way to determine if
186.Fn strtoul
187has processed a negative number (and returned an unsigned value) short of
188examining the string in
189.Fa nptr
190directly.
191.Sh EXAMPLES
192Ensuring that a string is a valid number (i.e., in range and containing no
193trailing characters) requires clearing
194.Va errno
195beforehand explicitly since
196.Va errno
197is not changed on a successful call to
198.Fn strtoul ,
199and the return value of
200.Fn strtoul
201cannot be used unambiguously to signal an error:
202.Bd -literal -offset indent
203char *ep;
204unsigned long ulval;
205
206\&...
207
208errno = 0;
209ulval = strtoul(buf, &ep, 10);
210if (buf[0] == '\e0' || *ep != '\e0')
211 goto not_a_number;
212if (errno == ERANGE && ulval == ULONG_MAX)
213 goto out_of_range;
214.Ed
215.Pp
216This example will accept
217.Dq 12
218but not
219.Dq 12foo
220or
221.Dq 12\en .
222If trailing whitespace is acceptable, further checks must be done on
223.Va *ep ;
224alternately, use
225.Xr sscanf 3 .
226.Sh ERRORS
227.Bl -tag -width Er
228.It Bq Er ERANGE
229The given string was out of range; the value converted has been clamped.
230.El
231.Sh SEE ALSO
232.Xr sscanf 3 ,
233.Xr strtol 3
234.Sh STANDARDS
235The
236.Fn strtoul ,
237.Fn strtoull ,
238and
239.Fn strtoumax
240functions conform to
241.St -ansiC-99 .
242The
243.Fn strtouq
244function is a
245.Bx
246extension and is provided for backwards compatibility with legacy programs.
247.Sh BUGS
248Ignores 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..a49e595bc0
--- /dev/null
+++ b/src/lib/libc/stdlib/system.3
@@ -0,0 +1,104 @@
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.11 2008/04/04 19:30:41 kurt Exp $
33.\"
34.Dd $Mdocdate: April 4 2008 $
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.Pp
70Note that fork handlers established using
71.Xr pthread_atfork 3
72are not called when a multithreaded program calls
73.Fn system .
74.Sh RETURN VALUES
75If a child process cannot be created, or the termination status of
76the shell cannot be obtained,
77.Fn system
78returns \-1 and sets
79.Va errno
80to indicate the error.
81If execution of the shell fails,
82.Fn system
83returns the termination status for a program that terminates with a call of
84.Fn exit 127 .
85.Sh SEE ALSO
86.Xr sh 1 ,
87.Xr execve 2 ,
88.Xr waitpid 2 ,
89.Xr popen 3
90.Sh STANDARDS
91The
92.Fn system
93function conforms to
94.St -ansiC
95and
96.St -p1003.2-92 .
97.Sh CAVEATS
98Never supply the
99.Fn system
100function with a command containing any part of an unsanitized user-supplied
101string.
102Shell meta-characters present will be honored by the
103.Xr sh 1
104command 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..0a52822620
--- /dev/null
+++ b/src/lib/libc/stdlib/tsearch.3
@@ -0,0 +1,127 @@
1.\" $OpenBSD: tsearch.3,v 1.16 2007/05/31 19:19:32 jmc 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 $Mdocdate: May 31 2007 $
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}