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.inc76
-rw-r--r--src/lib/libc/stdlib/_Exit.c22
-rw-r--r--src/lib/libc/stdlib/_rand48.c1
-rw-r--r--src/lib/libc/stdlib/a64l.3133
-rw-r--r--src/lib/libc/stdlib/a64l.c30
-rw-r--r--src/lib/libc/stdlib/abort.328
-rw-r--r--src/lib/libc/stdlib/abort.c41
-rw-r--r--src/lib/libc/stdlib/abs.327
-rw-r--r--src/lib/libc/stdlib/abs.c15
-rw-r--r--src/lib/libc/stdlib/alloca.343
-rw-r--r--src/lib/libc/stdlib/atexit.327
-rw-r--r--src/lib/libc/stdlib/atexit.c233
-rw-r--r--src/lib/libc/stdlib/atexit.h67
-rw-r--r--src/lib/libc/stdlib/atof.315
-rw-r--r--src/lib/libc/stdlib/atof.c15
-rw-r--r--src/lib/libc/stdlib/atoi.337
-rw-r--r--src/lib/libc/stdlib/atoi.c15
-rw-r--r--src/lib/libc/stdlib/atol.321
-rw-r--r--src/lib/libc/stdlib/atol.c15
-rw-r--r--src/lib/libc/stdlib/atoll.3 (renamed from src/lib/libc/stdlib/calloc.3)61
-rw-r--r--src/lib/libc/stdlib/atoll.c (renamed from src/lib/libc/stdlib/putenv.c)35
-rw-r--r--src/lib/libc/stdlib/bsearch.325
-rw-r--r--src/lib/libc/stdlib/bsearch.c27
-rw-r--r--src/lib/libc/stdlib/cfree.c40
-rw-r--r--src/lib/libc/stdlib/div.326
-rw-r--r--src/lib/libc/stdlib/div.c15
-rw-r--r--src/lib/libc/stdlib/drand48.c1
-rw-r--r--src/lib/libc/stdlib/ecvt.3165
-rw-r--r--src/lib/libc/stdlib/ecvt.c107
-rw-r--r--src/lib/libc/stdlib/erand48.c1
-rw-r--r--src/lib/libc/stdlib/exit.366
-rw-r--r--src/lib/libc/stdlib/exit.c40
-rw-r--r--src/lib/libc/stdlib/gcvt.c125
-rw-r--r--src/lib/libc/stdlib/getenv.3136
-rw-r--r--src/lib/libc/stdlib/getenv.c77
-rw-r--r--src/lib/libc/stdlib/getopt.3308
-rw-r--r--src/lib/libc/stdlib/getopt.c118
-rw-r--r--src/lib/libc/stdlib/getopt_long.3445
-rw-r--r--src/lib/libc/stdlib/getopt_long.c511
-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.3239
-rw-r--r--src/lib/libc/stdlib/hcreate.c191
-rw-r--r--src/lib/libc/stdlib/heapsort.c27
-rw-r--r--src/lib/libc/stdlib/imaxabs.3 (renamed from src/lib/libc/stdlib/free.3)65
-rw-r--r--src/lib/libc/stdlib/imaxabs.c38
-rw-r--r--src/lib/libc/stdlib/imaxdiv.366
-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.c1
-rw-r--r--src/lib/libc/stdlib/l64a.c17
-rw-r--r--src/lib/libc/stdlib/labs.337
-rw-r--r--src/lib/libc/stdlib/labs.c15
-rw-r--r--src/lib/libc/stdlib/lcong48.c1
-rw-r--r--src/lib/libc/stdlib/ldiv.332
-rw-r--r--src/lib/libc/stdlib/ldiv.c15
-rw-r--r--src/lib/libc/stdlib/llabs.c (renamed from src/lib/libc/stdlib/calloc.c)27
-rw-r--r--src/lib/libc/stdlib/lldiv.3 (renamed from src/lib/libc/stdlib/memory.3)73
-rw-r--r--src/lib/libc/stdlib/lldiv.c50
-rw-r--r--src/lib/libc/stdlib/lrand48.c1
-rw-r--r--src/lib/libc/stdlib/lsearch.3108
-rw-r--r--src/lib/libc/stdlib/lsearch.c84
-rw-r--r--src/lib/libc/stdlib/malloc.3427
-rw-r--r--src/lib/libc/stdlib/malloc.c1958
-rw-r--r--src/lib/libc/stdlib/merge.c47
-rw-r--r--src/lib/libc/stdlib/mrand48.c1
-rw-r--r--src/lib/libc/stdlib/multibyte.c131
-rw-r--r--src/lib/libc/stdlib/nrand48.c1
-rw-r--r--src/lib/libc/stdlib/posix_memalign.394
-rw-r--r--src/lib/libc/stdlib/qabs.322
-rw-r--r--src/lib/libc/stdlib/qabs.c15
-rw-r--r--src/lib/libc/stdlib/qdiv.327
-rw-r--r--src/lib/libc/stdlib/qdiv.c15
-rw-r--r--src/lib/libc/stdlib/qsort.393
-rw-r--r--src/lib/libc/stdlib/qsort.c71
-rw-r--r--src/lib/libc/stdlib/radixsort.356
-rw-r--r--src/lib/libc/stdlib/radixsort.c66
-rw-r--r--src/lib/libc/stdlib/rand.337
-rw-r--r--src/lib/libc/stdlib/rand.c27
-rw-r--r--src/lib/libc/stdlib/rand48.347
-rw-r--r--src/lib/libc/stdlib/rand48.h4
-rw-r--r--src/lib/libc/stdlib/random.3114
-rw-r--r--src/lib/libc/stdlib/random.c131
-rw-r--r--src/lib/libc/stdlib/realloc.3100
-rw-r--r--src/lib/libc/stdlib/realpath.376
-rw-r--r--src/lib/libc/stdlib/realpath.c251
-rw-r--r--src/lib/libc/stdlib/remque.c44
-rw-r--r--src/lib/libc/stdlib/seed48.c1
-rw-r--r--src/lib/libc/stdlib/setenv.c164
-rw-r--r--src/lib/libc/stdlib/srand48.c1
-rw-r--r--src/lib/libc/stdlib/strtod.387
-rw-r--r--src/lib/libc/stdlib/strtod.c2499
-rw-r--r--src/lib/libc/stdlib/strtoimax.c140
-rw-r--r--src/lib/libc/stdlib/strtol.3195
-rw-r--r--src/lib/libc/stdlib/strtol.c86
-rw-r--r--src/lib/libc/stdlib/strtoll.c (renamed from src/lib/libc/stdlib/strtoq.c)97
-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.3173
-rw-r--r--src/lib/libc/stdlib/strtoul.c60
-rw-r--r--src/lib/libc/stdlib/strtoull.c (renamed from src/lib/libc/stdlib/strtouq.c)69
-rw-r--r--src/lib/libc/stdlib/strtoumax.c102
-rw-r--r--src/lib/libc/stdlib/system.357
-rw-r--r--src/lib/libc/stdlib/system.c35
-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
108 files changed, 7896 insertions, 4949 deletions
diff --git a/src/lib/libc/stdlib/Makefile.inc b/src/lib/libc/stdlib/Makefile.inc
index 782a4ab022..81d1962026 100644
--- a/src/lib/libc/stdlib/Makefile.inc
+++ b/src/lib/libc/stdlib/Makefile.inc
@@ -1,45 +1,73 @@
1# from: @(#)Makefile.inc 5.6 (Berkeley) 6/4/91 1# $OpenBSD: Makefile.inc,v 1.44 2010/05/18 22:24:55 tedu Exp $
2# $Id: Makefile.inc,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
3 2
4# stdlib sources 3# stdlib sources
5.PATH: ${.CURDIR}/arch/${MACHINE_ARCH}/stdlib ${.CURDIR}/stdlib 4.PATH: ${LIBCSRCDIR}/arch/${MACHINE_CPU}/stdlib ${LIBCSRCDIR}/stdlib
6 5
7SRCS+= a64l.c abort.c atexit.c atoi.c atof.c atol.c bsearch.c calloc.c \ 6SRCS+= a64l.c abort.c atexit.c atoi.c atof.c atol.c atoll.c bsearch.c \
8 exit.c getenv.c getopt.c heapsort.c l64a.c malloc.c merge.c \ 7 cfree.c exit.c ecvt.c gcvt.c getenv.c getopt_long.c \
9 multibyte.c putenv.c qsort.c radixsort.c rand.c random.c realpath.c \ 8 getsubopt.c hcreate.c heapsort.c imaxabs.c imaxdiv.c l64a.c llabs.c \
10 setenv.c strtod.c strtol.c strtoq.c strtoul.c strtouq.c system.c \ 9 lldiv.c lsearch.c malloc.c merge.c qsort.c radixsort.c rand.c \
11 _rand48.c drand48.c erand48.c jrand48.c lcong48.c lrand48.c \ 10 random.c realpath.c setenv.c strtoimax.c strtol.c \
12 mrand48.c nrand48.c seed48.c srand48.c qabs.c qdiv.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
13 14
14.if (${MACHINE_ARCH} == "m68k") 15.if (${MACHINE_CPU} == "m68k")
15SRCS+= abs.S div.c labs.c ldiv.c 16SRCS+= abs.S div.c labs.c ldiv.c
16.elif (${MACHINE_ARCH} == "i386") 17LSRCS+= abs.c
18.elif (${MACHINE_CPU} == "i386")
17SRCS+= abs.S div.S labs.S ldiv.S 19SRCS+= abs.S div.S labs.S ldiv.S
18.elif (${MACHINE_ARCH} == "ns32k") 20LSRCS+= abs.c div.c labs.c ldiv.c
21.elif (${MACHINE_CPU} == "ns32k")
19SRCS+= abs.S div.c labs.c ldiv.c 22SRCS+= abs.S div.c labs.c ldiv.c
20.elif (${MACHINE_ARCH} == "tahoe") 23LSRCS+= abs.c
24.elif (${MACHINE_CPU} == "tahoe")
21SRCS+= abs.S div.c labs.c ldiv.c 25SRCS+= abs.S div.c labs.c ldiv.c
22.elif (${MACHINE_ARCH} == "vax") 26LSRCS+= abs.c
27.elif (${MACHINE_CPU} == "vax")
23SRCS+= abs.c div.c labs.c ldiv.c 28SRCS+= abs.c div.c labs.c ldiv.c
24.elif (${MACHINE_ARCH} == "alpha") 29.elif (${MACHINE_CPU} == "alpha")
25# XXX should be .S's 30# XXX should be .S's
26SRCS+= abs.c div.c labs.c ldiv.c 31SRCS+= abs.c div.c labs.c ldiv.c
27.else 32.else
28SRCS+= abs.c div.c labs.c ldiv.c 33SRCS+= abs.c div.c labs.c ldiv.c
29.endif 34.endif
30 35
31MAN+= abort.3 abs.3 alloca.3 atexit.3 atof.3 atoi.3 atol.3 bsearch.3 \ 36.if (${MACHINE_CPU} == "vax") || (${MACHINE_CPU} == "m68k")
32 calloc.3 div.3 exit.3 free.3 getenv.3 getopt.3 labs.3 ldiv.3 \ 37SRCS+= insque.S remque.S
33 malloc.3 memory.3 qabs.3 qdiv.3 qsort.3 radixsort.3 rand48.3 \ 38.else
34 rand.3 random.3 realloc.3 realpath.3 strtod.3 strtol.3 strtoul.3 \ 39SRCS+= insque.c remque.c
35 system.3 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 posix_memalign.3 qabs.3 qdiv.3 qsort.3 \
46 radixsort.3 rand48.3 rand.3 random.3 realpath.3 strtod.3 strtonum.3 \
47 strtol.3 strtoul.3 system.3 tsearch.3
36 48
49MLINKS+=exit.3 _Exit.3
50MLINKS+=ecvt.3 fcvt.3 ecvt.3 gcvt.3
37MLINKS+=getenv.3 setenv.3 getenv.3 unsetenv.3 getenv.3 putenv.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
38MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3 59MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3
39MLINKS+=rand.3 srand.3 60MLINKS+=radixsort.3 sradixsort.3
40MLINKS+=strtol.3 strtoq.3 61MLINKS+=rand.3 srand.3 rand.3 rand_r.3
41MLINKS+=strtoul.3 strtouq.3 62MLINKS+=random.3 initstate.3 random.3 setstate.3
42MLINKS+=random.3 initstate.3 random.3 setstate.3 random.3 srandom.3 63MLINKS+=random.3 srandom.3 random.3 srandomdev.3
43MLINKS+=rand48.3 drand48.3 rand48.3 erand48.3 rand48.3 lrand48.3 64MLINKS+=rand48.3 drand48.3 rand48.3 erand48.3 rand48.3 lrand48.3
44MLINKS+=rand48.3 mrand48.3 rand48.3 nrand48.3 rand48.3 jrand48.3 65MLINKS+=rand48.3 mrand48.3 rand48.3 nrand48.3 rand48.3 jrand48.3
45MLINKS+=rand48.3 srand48.3 rand48.3 seed48.3 rand48.3 lcong48.3 66MLINKS+=rand48.3 srand48.3 rand48.3 seed48.3 rand48.3 lcong48.3
67MLINKS+=strtod.3 strtof.3 strtod.3 strtold.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
index 83ade4645a..7c950f7cee 100644
--- a/src/lib/libc/stdlib/_rand48.c
+++ b/src/lib/libc/stdlib/_rand48.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: _rand48.c,v 1.3 2005/08/08 08:05:36 espie Exp $ */
1/* 2/*
2 * Copyright (c) 1993 Martin Birgmeier 3 * Copyright (c) 1993 Martin Birgmeier
3 * All rights reserved. 4 * All rights reserved.
diff --git a/src/lib/libc/stdlib/a64l.3 b/src/lib/libc/stdlib/a64l.3
new file mode 100644
index 0000000000..da0aae33c9
--- /dev/null
+++ b/src/lib/libc/stdlib/a64l.3
@@ -0,0 +1,133 @@
1.\" $OpenBSD: a64l.3,v 1.11 2010/04/01 17:06:55 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: April 1 2010 $
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 STANDARDS
112The
113.Fn a64l
114and
115.Fn l64a
116functions conform to
117.St -xpg4.2 .
118.Sh CAVEATS
119The value returned by
120.Fn l64a
121is a pointer into a static buffer, the contents of which
122will be overwritten by subsequent calls.
123.Pp
124The value returned by
125.Fn a64l
126may be incorrect if the value is too large; for that reason, only strings
127that resulted from a call to
128.Fn l64a
129should be used to call
130.Fn a64l .
131.Pp
132If a long integer is larger than 32 bits, only the low-order
13332 bits are used.
diff --git a/src/lib/libc/stdlib/a64l.c b/src/lib/libc/stdlib/a64l.c
index 03fc77e034..5312929c6f 100644
--- a/src/lib/libc/stdlib/a64l.c
+++ b/src/lib/libc/stdlib/a64l.c
@@ -1,34 +1,42 @@
1/* $OpenBSD: a64l.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
1/* 2/*
2 * Written by J.T. Conklin <jtc@netbsd.org>. 3 * Written by J.T. Conklin <jtc@netbsd.org>.
3 * Public domain. 4 * Public domain.
4 */ 5 */
5 6
6#if defined(LIBC_SCCS) && !defined(lint) 7#include <errno.h>
7static char *rcsid = "$NetBSD: a64l.c,v 1.3 1995/05/11 23:04:47 jtc Exp $"; 8#include <stdlib.h>
8#endif
9 9
10long 10long
11a64l(s) 11a64l(const char *s)
12 const char *s;
13{ 12{
14 long value, digit, shift; 13 long value, digit, shift;
15 int i; 14 int i;
16 15
16 if (s == NULL) {
17 errno = EINVAL;
18 return(-1L);
19 }
20
17 value = 0; 21 value = 0;
18 shift = 0; 22 shift = 0;
19 for (i = 0; *s && i < 6; i++, s++) { 23 for (i = 0; *s && i < 6; i++, s++) {
20 if (*s <= '/') 24 if (*s >= '.' && *s <= '/')
21 digit = *s - '.'; 25 digit = *s - '.';
22 else if (*s <= '9') 26 else if (*s >= '0' && *s <= '9')
23 digit = *s - '0' + 2; 27 digit = *s - '0' + 2;
24 else if (*s <= 'Z') 28 else if (*s >= 'A' && *s <= 'Z')
25 digit = *s - 'A' + 12; 29 digit = *s - 'A' + 12;
26 else 30 else if (*s >= 'a' && *s <= 'z')
27 digit = *s - 'a' + 38; 31 digit = *s - 'a' + 38;
32 else {
33 errno = EINVAL;
34 return(-1L);
35 }
28 36
29 value |= digit << shift; 37 value |= digit << shift;
30 shift += 6; 38 shift += 6;
31 } 39 }
32 40
33 return (long) value; 41 return(value);
34} 42}
diff --git a/src/lib/libc/stdlib/abort.3 b/src/lib/libc/stdlib/abort.3
index ab57327585..4ec85882b2 100644
--- a/src/lib/libc/stdlib/abort.3
+++ b/src/lib/libc/stdlib/abort.3
@@ -13,11 +13,7 @@
13.\" 2. Redistributions in binary form must reproduce the above copyright 13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the 14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution. 15.\" documentation and/or other materials provided with the distribution.
16.\" 3. All advertising materials mentioning features or use of this software 16.\" 3. Neither the name of the University nor the names of its contributors
17.\" must display the following acknowledgement:
18.\" This product includes software developed by the University of
19.\" California, Berkeley and its contributors.
20.\" 4. Neither the name of the University nor the names of its contributors
21.\" may be used to endorse or promote products derived from this software 17.\" may be used to endorse or promote products derived from this software
22.\" without specific prior written permission. 18.\" without specific prior written permission.
23.\" 19.\"
@@ -33,10 +29,9 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
35.\" 31.\"
36.\" from: @(#)abort.3 6.7 (Berkeley) 6/29/91 32.\" $OpenBSD: abort.3,v 1.8 2007/05/31 19:19:31 jmc Exp $
37.\" $Id: abort.3,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
38.\" 33.\"
39.Dd June 29, 1991 34.Dd $Mdocdate: May 31 2007 $
40.Dt ABORT 3 35.Dt ABORT 3
41.Os 36.Os
42.Sh NAME 37.Sh NAME
@@ -49,23 +44,20 @@
49.Sh DESCRIPTION 44.Sh DESCRIPTION
50The 45The
51.Fn abort 46.Fn abort
52function causes abnormal program termination to occur, unless the 47function causes abnormal program termination to occur, unless the signal
53signal
54.Dv SIGABRT 48.Dv SIGABRT
55is being caught and the signal handler does not return. 49is being caught and the signal handler does not return.
56.Pp 50.Pp
57No open streams are closed or flushed. 51Any open streams are flushed and closed.
58.Sh RETURN VALUES 52.Sh RETURN VALUES
59The 53The
60.Nm abort 54.Fn abort
61function 55function never returns.
62never returns.
63.Sh SEE ALSO 56.Sh SEE ALSO
64.Xr sigaction 2 , 57.Xr sigaction 2 ,
65.Xr exit 2 58.Xr exit 3
66.Sh STANDARDS 59.Sh STANDARDS
67The 60The
68.Fn abort 61.Fn abort
69function 62function conforms to
70conforms to 63.St -p1003.1-90 .
71.St -ansiC .
diff --git a/src/lib/libc/stdlib/abort.c b/src/lib/libc/stdlib/abort.c
index c298e016b4..244e3b28aa 100644
--- a/src/lib/libc/stdlib/abort.c
+++ b/src/lib/libc/stdlib/abort.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: abort.c,v 1.15 2007/09/03 14:40:16 millert Exp $ */
1/* 2/*
2 * Copyright (c) 1985 Regents of the University of California. 3 * Copyright (c) 1985 Regents of the University of California.
3 * All rights reserved. 4 * All rights reserved.
@@ -10,11 +11,7 @@
10 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. 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 15 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission. 16 * without specific prior written permission.
20 * 17 *
@@ -31,27 +28,43 @@
31 * SUCH DAMAGE. 28 * SUCH DAMAGE.
32 */ 29 */
33 30
34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)abort.c 5.11 (Berkeley) 2/23/91";*/
36static char *rcsid = "$Id: abort.c,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */
38
39#include <signal.h> 31#include <signal.h>
40#include <stdlib.h> 32#include <stdlib.h>
41#include <unistd.h> 33#include <unistd.h>
34#include "thread_private.h"
35#include "atexit.h"
42 36
43void 37void
44abort() 38abort(void)
45{ 39{
40 struct atexit *p = __atexit;
41 static int cleanup_called = 0;
46 sigset_t mask; 42 sigset_t mask;
47 43
44
48 sigfillset(&mask); 45 sigfillset(&mask);
49 /* 46 /*
50 * don't block SIGABRT to give any handler a chance; we ignore 47 * don't block SIGABRT to give any handler a chance; we ignore
51 * any errors -- X311J doesn't allow abort to return anyway. 48 * any errors -- X311J doesn't allow abort to return anyway.
52 */ 49 */
53 sigdelset(&mask, SIGABRT); 50 sigdelset(&mask, SIGABRT);
54 (void)sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL); 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
55 (void)kill(getpid(), SIGABRT); 68 (void)kill(getpid(), SIGABRT);
56 69
57 /* 70 /*
@@ -59,7 +72,7 @@ abort()
59 * it again, only harder. 72 * it again, only harder.
60 */ 73 */
61 (void)signal(SIGABRT, SIG_DFL); 74 (void)signal(SIGABRT, SIG_DFL);
62 (void)sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL); 75 (void)_thread_sys_sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
63 (void)kill(getpid(), SIGABRT); 76 (void)kill(getpid(), SIGABRT);
64 exit(1); 77 _exit(1);
65} 78}
diff --git a/src/lib/libc/stdlib/abs.3 b/src/lib/libc/stdlib/abs.3
index 4748d89e77..473aea1cd6 100644
--- a/src/lib/libc/stdlib/abs.3
+++ b/src/lib/libc/stdlib/abs.3
@@ -13,11 +13,7 @@
13.\" 2. Redistributions in binary form must reproduce the above copyright 13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the 14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution. 15.\" documentation and/or other materials provided with the distribution.
16.\" 3. All advertising materials mentioning features or use of this software 16.\" 3. Neither the name of the University nor the names of its contributors
17.\" must display the following acknowledgement:
18.\" This product includes software developed by the University of
19.\" California, Berkeley and its contributors.
20.\" 4. Neither the name of the University nor the names of its contributors
21.\" may be used to endorse or promote products derived from this software 17.\" may be used to endorse or promote products derived from this software
22.\" without specific prior written permission. 18.\" without specific prior written permission.
23.\" 19.\"
@@ -33,10 +29,9 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
35.\" 31.\"
36.\" from: @(#)abs.3 6.4 (Berkeley) 6/29/91 32.\" $OpenBSD: abs.3,v 1.9 2011/07/07 13:30:28 jmc Exp $
37.\" $Id: abs.3,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
38.\" 33.\"
39.Dd June 29, 1991 34.Dd $Mdocdate: July 7 2011 $
40.Dt ABS 3 35.Dt ABS 3
41.Os 36.Os
42.Sh NAME 37.Sh NAME
@@ -49,22 +44,18 @@
49.Sh DESCRIPTION 44.Sh DESCRIPTION
50The 45The
51.Fn abs 46.Fn abs
52function 47function computes the absolute value of the integer
53computes 48.Fa j .
54the absolute value of the integer
55.Ar j .
56.Sh RETURN VALUES 49.Sh RETURN VALUES
57The 50The
58.Fn abs 51.Fn abs
59function 52function returns the absolute value.
60returns
61the absolute value.
62.Sh SEE ALSO 53.Sh SEE ALSO
63.Xr floor 3 ,
64.Xr labs 3 ,
65.Xr cabs 3 , 54.Xr cabs 3 ,
55.Xr floor 3 ,
66.Xr hypot 3 , 56.Xr hypot 3 ,
67.Xr math 3 57.Xr imaxabs 3 ,
58.Xr labs 3
68.Sh STANDARDS 59.Sh STANDARDS
69The 60The
70.Fn abs 61.Fn abs
diff --git a/src/lib/libc/stdlib/abs.c b/src/lib/libc/stdlib/abs.c
index 64468e0224..5d2fbae69f 100644
--- a/src/lib/libc/stdlib/abs.c
+++ b/src/lib/libc/stdlib/abs.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: abs.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
1/*- 2/*-
2 * Copyright (c) 1990 The Regents of the University of California. 3 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved. 4 * All rights reserved.
@@ -10,11 +11,7 @@
10 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. 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 15 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission. 16 * without specific prior written permission.
20 * 17 *
@@ -31,16 +28,10 @@
31 * SUCH DAMAGE. 28 * SUCH DAMAGE.
32 */ 29 */
33 30
34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)abs.c 5.2 (Berkeley) 5/17/90";*/
36static char *rcsid = "$Id: abs.c,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */
38
39#include <stdlib.h> 31#include <stdlib.h>
40 32
41int 33int
42abs(j) 34abs(int j)
43 int j;
44{ 35{
45 return(j < 0 ? -j : j); 36 return(j < 0 ? -j : j);
46} 37}
diff --git a/src/lib/libc/stdlib/alloca.3 b/src/lib/libc/stdlib/alloca.3
index dcb97ab11c..d7fddb04c2 100644
--- a/src/lib/libc/stdlib/alloca.3
+++ b/src/lib/libc/stdlib/alloca.3
@@ -9,11 +9,7 @@
9.\" 2. Redistributions in binary form must reproduce the above copyright 9.\" 2. Redistributions in binary form must reproduce the above copyright
10.\" notice, this list of conditions and the following disclaimer in the 10.\" notice, this list of conditions and the following disclaimer in the
11.\" documentation and/or other materials provided with the distribution. 11.\" documentation and/or other materials provided with the distribution.
12.\" 3. All advertising materials mentioning features or use of this software 12.\" 3. Neither the name of the University nor the names of its contributors
13.\" must display the following acknowledgement:
14.\" This product includes software developed by the University of
15.\" California, Berkeley and its contributors.
16.\" 4. 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 13.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission. 14.\" without specific prior written permission.
19.\" 15.\"
@@ -29,12 +25,11 @@
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE. 26.\" SUCH DAMAGE.
31.\" 27.\"
32.\" from: @(#)alloca.3 5.1 (Berkeley) 5/2/91 28.\" $OpenBSD: alloca.3,v 1.11 2007/05/31 19:19:31 jmc Exp $
33.\" $Id: alloca.3,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
34.\" 29.\"
35.Dd May 2, 1991 30.Dd $Mdocdate: May 31 2007 $
36.Dt ALLOCA 3 31.Dt ALLOCA 3
37.Os BSD 4 32.Os
38.Sh NAME 33.Sh NAME
39.Nm alloca 34.Nm alloca
40.Nd memory allocator 35.Nd memory allocator
@@ -45,35 +40,41 @@
45.Sh DESCRIPTION 40.Sh DESCRIPTION
46The 41The
47.Fn alloca 42.Fn alloca
48function 43function allocates
49allocates
50.Fa size 44.Fa size
51bytes of space in the stack frame of the caller. 45bytes of space in the stack frame of the caller.
52This temporary space is automatically freed on 46This temporary space is automatically freed on return.
53return.
54.Sh RETURN VALUES 47.Sh RETURN VALUES
55The 48The
56.Fn alloca 49.Fn alloca
57function returns a pointer to the beginning of the allocated space. 50function returns a pointer to the beginning of the allocated space.
58If the allocation failed, a
59.Dv NULL
60pointer is returned.
61.Sh SEE ALSO 51.Sh SEE ALSO
52.Xr pagesize 1 ,
62.Xr brk 2 , 53.Xr brk 2 ,
63.Xr pagesize 2
64.Xr calloc 3 , 54.Xr calloc 3 ,
65.Xr malloc 3 , 55.Xr malloc 3 ,
66.Xr realloc 3 , 56.Xr realloc 3
67.Sh BUGS 57.Sh BUGS
68The 58The
69.Fn alloca 59.Fn alloca
70function 60function is machine dependent; its use is discouraged.
71is machine dependent; its use is discouraged.
72.\" .Sh HISTORY 61.\" .Sh HISTORY
73.\" The 62.\" The
74.\" .Fn alloca 63.\" .Fn alloca
75.\" function appeared in 64.\" function appeared in
76.\" .Bx ?? . 65.\" .Bx ?? .
77.\" The function appeared in 32v, pwb and pwb.2 and in 3bsd 4bsd 66.\" The function appeared in 32v, pwb and pwb.2 and in 3bsd 4bsd
78.\" The first man page (or link to a man page that I can find at the 67.\" The first man page (or link to a man page that I can find at the
79.\" moment is 4.3... 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
index 07de054d3c..0615feabb1 100644
--- a/src/lib/libc/stdlib/atexit.3
+++ b/src/lib/libc/stdlib/atexit.3
@@ -13,11 +13,7 @@
13.\" 2. Redistributions in binary form must reproduce the above copyright 13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the 14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution. 15.\" documentation and/or other materials provided with the distribution.
16.\" 3. All advertising materials mentioning features or use of this software 16.\" 3. Neither the name of the University nor the names of its contributors
17.\" must display the following acknowledgement:
18.\" This product includes software developed by the University of
19.\" California, Berkeley and its contributors.
20.\" 4. Neither the name of the University nor the names of its contributors
21.\" may be used to endorse or promote products derived from this software 17.\" may be used to endorse or promote products derived from this software
22.\" without specific prior written permission. 18.\" without specific prior written permission.
23.\" 19.\"
@@ -33,10 +29,9 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
35.\" 31.\"
36.\" from: @(#)atexit.3 5.3 (Berkeley) 6/29/91 32.\" $OpenBSD: atexit.3,v 1.8 2007/05/31 19:19:31 jmc Exp $
37.\" $Id: atexit.3,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
38.\" 33.\"
39.Dd June 29, 1991 34.Dd $Mdocdate: May 31 2007 $
40.Dt ATEXIT 3 35.Dt ATEXIT 3
41.Os 36.Os
42.Sh NAME 37.Sh NAME
@@ -49,17 +44,22 @@
49.Sh DESCRIPTION 44.Sh DESCRIPTION
50The 45The
51.Fn atexit 46.Fn atexit
52function 47function registers the given
53registers the given 48.Fa function
54.Ar function
55to be called at program exit, whether via 49to be called at program exit, whether via
56.Xr exit 3 50.Xr exit 3
57or via return from the program's 51or via return from the program's
58.Em main . 52.Fn main .
59Functions so registered are called in reverse order; 53Functions so registered are called in reverse order;
60no arguments are passed. 54no arguments are passed.
61At least 32 functions can always be registered, 55At least 32 functions can always be registered,
62and more are allowed as long as sufficient memory can be allocated. 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 63.Sh RETURN VALUES
64.Rv -std atexit 64.Rv -std atexit
65.Sh ERRORS 65.Sh ERRORS
@@ -73,6 +73,5 @@ The existing list of functions is unmodified.
73.Sh STANDARDS 73.Sh STANDARDS
74The 74The
75.Fn atexit 75.Fn atexit
76function 76function conforms to
77conforms to
78.St -ansiC . 77.St -ansiC .
diff --git a/src/lib/libc/stdlib/atexit.c b/src/lib/libc/stdlib/atexit.c
index 4da1eb0d9c..e28ccf29d0 100644
--- a/src/lib/libc/stdlib/atexit.c
+++ b/src/lib/libc/stdlib/atexit.c
@@ -1,68 +1,209 @@
1/*- 1/* $OpenBSD: atexit.c,v 1.15 2011/03/02 18:34:05 matthew Exp $ */
2 * Copyright (c) 1990 The Regents of the University of California. 2/*
3 * Copyright (c) 2002 Daniel Hartmeier
3 * All rights reserved. 4 * All rights reserved.
4 * 5 *
5 * This code is derived from software contributed to Berkeley by
6 * Chris Torek.
7 *
8 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
10 * are met: 8 * 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 by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 * 9 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 10 * - Redistributions of source code must retain the above copyright
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 11 * notice, this list of conditions and the following disclaimer.
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 12 * - Redistributions in binary form must reproduce the above
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 13 * copyright notice, this list of conditions and the following
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 14 * disclaimer in the documentation and/or other materials provided
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 15 * with the distribution.
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 16 *
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
34 * SUCH DAMAGE. 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 *
35 */ 30 */
36 31
37#if defined(LIBC_SCCS) && !defined(lint) 32#include <sys/types.h>
38/*static char *sccsid = "from: @(#)atexit.c 5.2 (Berkeley) 11/14/90";*/ 33#include <sys/mman.h>
39static char *rcsid = "$Id: atexit.c,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */
41
42#include <stdlib.h> 34#include <stdlib.h>
35#include <string.h>
36#include <unistd.h>
43#include "atexit.h" 37#include "atexit.h"
38#include "thread_private.h"
44 39
40int __atexit_invalid = 1;
45struct atexit *__atexit; 41struct atexit *__atexit;
46 42
47/* 43/*
48 * Register a function to be performed at exit. 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
49 */ 59 */
50int 60int
51atexit(fn) 61__cxa_atexit(void (*func)(void *), void *arg, void *dso)
52 void (*fn)();
53{ 62{
54 static struct atexit __atexit0; /* one guaranteed table */ 63 struct atexit *p = __atexit;
55 register struct atexit *p; 64 struct atexit_fn *fnp;
65 int pgsize = getpagesize();
66 int ret = -1;
56 67
57 if ((p = __atexit) == NULL) 68 if (pgsize < sizeof(*p))
58 __atexit = p = &__atexit0; 69 return (-1);
59 else if (p->ind >= ATEXIT_SIZE) { 70 _ATEXIT_LOCK();
60 if ((p = malloc(sizeof(*p))) == NULL) 71 p = __atexit;
61 return (-1); 72 if (p != NULL) {
62 p->ind = 0; 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]);
63 p->next = __atexit; 90 p->next = __atexit;
64 __atexit = p; 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 (fn.fn_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;
65 } 202 }
66 p->fns[p->ind++] = fn; 203 p->fns[0].fn_ptr.std_func = func;
67 return (0); 204 p->fns[0].fn_arg = NULL;
205 p->fns[0].fn_dso = NULL;
206 mprotect(p, pgsize, PROT_READ);
207unlock:
208 _ATEXIT_UNLOCK();
68} 209}
diff --git a/src/lib/libc/stdlib/atexit.h b/src/lib/libc/stdlib/atexit.h
index 8b756e8fe2..1b23565dd0 100644
--- a/src/lib/libc/stdlib/atexit.h
+++ b/src/lib/libc/stdlib/atexit.h
@@ -1,46 +1,51 @@
1/*- 1/* $OpenBSD: atexit.h,v 1.7 2007/09/03 14:40:16 millert Exp $ */
2 * Copyright (c) 1990 The Regents of the University of California. 2
3/*
4 * Copyright (c) 2002 Daniel Hartmeier
3 * All rights reserved. 5 * All rights reserved.
4 * 6 *
5 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
7 * are met: 9 * 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. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. 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 * 10 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 11 * - Redistributions of source code must retain the above copyright
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 12 * notice, this list of conditions and the following disclaimer.
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 13 * - Redistributions in binary form must reproduce the above
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 14 * copyright notice, this list of conditions and the following
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 15 * disclaimer in the documentation and/or other materials provided
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 16 * with the distribution.
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 17 *
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31 * SUCH DAMAGE. 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.
32 * 30 *
33 * from: @(#)atexit.h 5.1 (Berkeley) 5/15/90
34 * $Id: atexit.h,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
35 */ 31 */
36 32
37/* must be at least 32 to guarantee ANSI conformance */
38#define ATEXIT_SIZE 32
39
40struct atexit { 33struct atexit {
41 struct atexit *next; /* next in list */ 34 struct atexit *next; /* next in list */
42 int ind; /* next index in this table */ 35 int ind; /* next index in this table */
43 void (*fns[ATEXIT_SIZE])(); /* the table itself */ 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 */
44}; 45};
45 46
47extern int __atexit_invalid;
46extern struct atexit *__atexit; /* points to head of LIFO stack */ 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
index 53e04f71c5..2538d0c879 100644
--- a/src/lib/libc/stdlib/atof.3
+++ b/src/lib/libc/stdlib/atof.3
@@ -13,11 +13,7 @@
13.\" 2. Redistributions in binary form must reproduce the above copyright 13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the 14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution. 15.\" documentation and/or other materials provided with the distribution.
16.\" 3. All advertising materials mentioning features or use of this software 16.\" 3. Neither the name of the University nor the names of its contributors
17.\" must display the following acknowledgement:
18.\" This product includes software developed by the University of
19.\" California, Berkeley and its contributors.
20.\" 4. Neither the name of the University nor the names of its contributors
21.\" may be used to endorse or promote products derived from this software 17.\" may be used to endorse or promote products derived from this software
22.\" without specific prior written permission. 18.\" without specific prior written permission.
23.\" 19.\"
@@ -33,10 +29,9 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
35.\" 31.\"
36.\" from: @(#)atof.3 6.4 (Berkeley) 6/29/91 32.\" $OpenBSD: atof.3,v 1.5 2007/05/31 19:19:31 jmc Exp $
37.\" $Id: atof.3,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
38.\" 33.\"
39.Dd June 29, 1991 34.Dd $Mdocdate: May 31 2007 $
40.Dt ATOF 3 35.Dt ATOF 3
41.Os 36.Os
42.Sh NAME 37.Sh NAME
@@ -52,9 +47,9 @@ string to double
52The 47The
53.Fn atof 48.Fn atof
54function converts the initial portion of the string pointed to by 49function converts the initial portion of the string pointed to by
55.Ar nptr 50.Fa nptr
56to 51to
57.Ar double 52.Li double
58representation. 53representation.
59.Pp 54.Pp
60It is equivalent to: 55It is equivalent to:
diff --git a/src/lib/libc/stdlib/atof.c b/src/lib/libc/stdlib/atof.c
index 9202de50bb..d14b58b070 100644
--- a/src/lib/libc/stdlib/atof.c
+++ b/src/lib/libc/stdlib/atof.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: atof.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
1/* 2/*
2 * Copyright (c) 1988 The Regents of the University of California. 3 * Copyright (c) 1988 The Regents of the University of California.
3 * All rights reserved. 4 * All rights reserved.
@@ -10,11 +11,7 @@
10 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. 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 15 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission. 16 * without specific prior written permission.
20 * 17 *
@@ -31,16 +28,10 @@
31 * SUCH DAMAGE. 28 * SUCH DAMAGE.
32 */ 29 */
33 30
34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)atof.c 5.3 (Berkeley) 1/8/93";*/
36static char *rcsid = "$Id: atof.c,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */
38
39#include <stdlib.h> 31#include <stdlib.h>
40 32
41double 33double
42atof(ascii) 34atof(const char *ascii)
43 const char *ascii;
44{ 35{
45 return(strtod(ascii, (char **)NULL)); 36 return(strtod(ascii, (char **)NULL));
46} 37}
diff --git a/src/lib/libc/stdlib/atoi.3 b/src/lib/libc/stdlib/atoi.3
index 219ba73c00..0c6b62b25f 100644
--- a/src/lib/libc/stdlib/atoi.3
+++ b/src/lib/libc/stdlib/atoi.3
@@ -1,5 +1,5 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California. 1.\" Copyright (c) 1990, 1991, 1993
2.\" All rights reserved. 2.\" The Regents of the University of California. All rights reserved.
3.\" 3.\"
4.\" This code is derived from software contributed to Berkeley by 4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information 5.\" the American National Standards Committee X3, on Information
@@ -13,11 +13,7 @@
13.\" 2. Redistributions in binary form must reproduce the above copyright 13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the 14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution. 15.\" documentation and/or other materials provided with the distribution.
16.\" 3. All advertising materials mentioning features or use of this software 16.\" 3. Neither the name of the University nor the names of its contributors
17.\" must display the following acknowledgement:
18.\" This product includes software developed by the University of
19.\" California, Berkeley and its contributors.
20.\" 4. Neither the name of the University nor the names of its contributors
21.\" may be used to endorse or promote products derived from this software 17.\" may be used to endorse or promote products derived from this software
22.\" without specific prior written permission. 18.\" without specific prior written permission.
23.\" 19.\"
@@ -33,10 +29,9 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
35.\" 31.\"
36.\" from: @(#)atoi.3 5.3 (Berkeley) 6/29/91 32.\" $OpenBSD: atoi.3,v 1.9 2007/05/31 19:19:31 jmc Exp $
37.\" $Id: atoi.3,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
38.\" 33.\"
39.Dd June 29, 1991 34.Dd $Mdocdate: May 31 2007 $
40.Dt ATOI 3 35.Dt ATOI 3
41.Os 36.Os
42.Sh NAME 37.Sh NAME
@@ -52,13 +47,12 @@ string to integer
52The 47The
53.Fn atoi 48.Fn atoi
54function converts the initial portion of the string pointed to by 49function converts the initial portion of the string pointed to by
55.Em nptr 50.Fa nptr
56to 51to
57.Em integer 52.Li integer
58representation. 53representation.
59.Pp 54.Pp
60It is equivalent to: 55It is equivalent to:
61.Pp
62.Bd -literal -offset indent 56.Bd -literal -offset indent
63(int)strtol(nptr, (char **)NULL, 10); 57(int)strtol(nptr, (char **)NULL, 10);
64.Ed 58.Ed
@@ -67,9 +61,26 @@ It is equivalent to:
67.Xr atol 3 , 61.Xr atol 3 ,
68.Xr strtod 3 , 62.Xr strtod 3 ,
69.Xr strtol 3 , 63.Xr strtol 3 ,
64.Xr strtonum 3 ,
70.Xr strtoul 3 65.Xr strtoul 3
71.Sh STANDARDS 66.Sh STANDARDS
72The 67The
73.Fn atoi 68.Fn atoi
74function conforms to 69function conforms to
75.St -ansiC . 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
index df7845f90c..b0842678e2 100644
--- a/src/lib/libc/stdlib/atoi.c
+++ b/src/lib/libc/stdlib/atoi.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: atoi.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
1/* 2/*
2 * Copyright (c) 1988 Regents of the University of California. 3 * Copyright (c) 1988 Regents of the University of California.
3 * All rights reserved. 4 * All rights reserved.
@@ -10,11 +11,7 @@
10 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. 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 15 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission. 16 * without specific prior written permission.
20 * 17 *
@@ -31,16 +28,10 @@
31 * SUCH DAMAGE. 28 * SUCH DAMAGE.
32 */ 29 */
33 30
34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)atoi.c 5.7 (Berkeley) 2/23/91";*/
36static char *rcsid = "$Id: atoi.c,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */
38
39#include <stdlib.h> 31#include <stdlib.h>
40 32
41int 33int
42atoi(str) 34atoi(const char *str)
43 const char *str;
44{ 35{
45 return((int)strtol(str, (char **)NULL, 10)); 36 return((int)strtol(str, (char **)NULL, 10));
46} 37}
diff --git a/src/lib/libc/stdlib/atol.3 b/src/lib/libc/stdlib/atol.3
index 86e3d324a3..3c5551182d 100644
--- a/src/lib/libc/stdlib/atol.3
+++ b/src/lib/libc/stdlib/atol.3
@@ -13,11 +13,7 @@
13.\" 2. Redistributions in binary form must reproduce the above copyright 13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the 14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution. 15.\" documentation and/or other materials provided with the distribution.
16.\" 3. All advertising materials mentioning features or use of this software 16.\" 3. Neither the name of the University nor the names of its contributors
17.\" must display the following acknowledgement:
18.\" This product includes software developed by the University of
19.\" California, Berkeley and its contributors.
20.\" 4. Neither the name of the University nor the names of its contributors
21.\" may be used to endorse or promote products derived from this software 17.\" may be used to endorse or promote products derived from this software
22.\" without specific prior written permission. 18.\" without specific prior written permission.
23.\" 19.\"
@@ -33,10 +29,9 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
35.\" 31.\"
36.\" from: @(#)atol.3 5.3 (Berkeley) 6/29/91 32.\" $OpenBSD: atol.3,v 1.7 2007/05/31 19:19:31 jmc Exp $
37.\" $Id: atol.3,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
38.\" 33.\"
39.Dd June 29, 1991 34.Dd $Mdocdate: May 31 2007 $
40.Dt ATOL 3 35.Dt ATOL 3
41.Os 36.Os
42.Sh NAME 37.Sh NAME
@@ -52,9 +47,9 @@ string to long integer
52The 47The
53.Fn atol 48.Fn atol
54function converts the initial portion of the string pointed to by 49function converts the initial portion of the string pointed to by
55.Ar nptr 50.Fa nptr
56to 51to
57.Em long integer 52.Li long integer
58representation. 53representation.
59.Pp 54.Pp
60It is equivalent to: 55It is equivalent to:
@@ -64,12 +59,12 @@ strtol(nptr, (char **)NULL, 10);
64.Sh SEE ALSO 59.Sh SEE ALSO
65.Xr atof 3 , 60.Xr atof 3 ,
66.Xr atoi 3 , 61.Xr atoi 3 ,
62.Xr atoll 3 ,
67.Xr strtod 3 , 63.Xr strtod 3 ,
68.Xr strtol 3 , 64.Xr strtol 3 ,
69.Xr strtoul 3 65.Xr strtoul 3
70.Sh STANDARDS 66.Sh STANDARDS
71The 67The
72.Fn atol 68.Fn atol
73function 69function conforms to
74conforms to 70.St -ansiC-99 .
75.St -ansiC .
diff --git a/src/lib/libc/stdlib/atol.c b/src/lib/libc/stdlib/atol.c
index 31ed06298b..1970804401 100644
--- a/src/lib/libc/stdlib/atol.c
+++ b/src/lib/libc/stdlib/atol.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: atol.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
1/* 2/*
2 * Copyright (c) 1988 Regents of the University of California. 3 * Copyright (c) 1988 Regents of the University of California.
3 * All rights reserved. 4 * All rights reserved.
@@ -10,11 +11,7 @@
10 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. 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 15 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission. 16 * without specific prior written permission.
20 * 17 *
@@ -31,16 +28,10 @@
31 * SUCH DAMAGE. 28 * SUCH DAMAGE.
32 */ 29 */
33 30
34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)atol.c 5.7 (Berkeley) 2/23/91";*/
36static char *rcsid = "$Id: atol.c,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */
38
39#include <stdlib.h> 31#include <stdlib.h>
40 32
41long 33long
42atol(str) 34atol(const char *str)
43 const char *str;
44{ 35{
45 return(strtol(str, (char **)NULL, 10)); 36 return(strtol(str, (char **)NULL, 10));
46} 37}
diff --git a/src/lib/libc/stdlib/calloc.3 b/src/lib/libc/stdlib/atoll.3
index d0754b46a0..608a61f4ce 100644
--- a/src/lib/libc/stdlib/calloc.3
+++ b/src/lib/libc/stdlib/atoll.3
@@ -1,4 +1,4 @@
1.\" Copyright (c) 1991 The Regents of the University of California. 1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved. 2.\" All rights reserved.
3.\" 3.\"
4.\" This code is derived from software contributed to Berkeley by 4.\" This code is derived from software contributed to Berkeley by
@@ -13,11 +13,7 @@
13.\" 2. Redistributions in binary form must reproduce the above copyright 13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the 14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution. 15.\" documentation and/or other materials provided with the distribution.
16.\" 3. All advertising materials mentioning features or use of this software 16.\" 3. Neither the name of the University nor the names of its contributors
17.\" must display the following acknowledgement:
18.\" This product includes software developed by the University of
19.\" California, Berkeley and its contributors.
20.\" 4. Neither the name of the University nor the names of its contributors
21.\" may be used to endorse or promote products derived from this software 17.\" may be used to endorse or promote products derived from this software
22.\" without specific prior written permission. 18.\" without specific prior written permission.
23.\" 19.\"
@@ -33,39 +29,42 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
35.\" 31.\"
36.\" from: @(#)calloc.3 5.2 (Berkeley) 6/29/91 32.\" $OpenBSD: atoll.3,v 1.5 2007/05/31 19:19:31 jmc Exp $
37.\" $Id: calloc.3,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $
38.\" 33.\"
39.Dd June 29, 1991 34.Dd $Mdocdate: May 31 2007 $
40.Dt CALLOC 3 35.Dt ATOLL 3
41.Os 36.Os
42.Sh NAME 37.Sh NAME
43.Nm calloc 38.Nm atoll
44.Nd allocate clean memory (zero initialized space) 39.Nd convert
40.Tn ASCII
41string to long long integer
45.Sh SYNOPSIS 42.Sh SYNOPSIS
46.Fd #include <stdlib.h> 43.Fd #include <stdlib.h>
47.Ft void * 44.Ft long long
48.Fn calloc "size_t nmemb" "size_t size" 45.Fn atoll "const char *nptr"
49.Sh DESCRIPTION 46.Sh DESCRIPTION
50The 47The
51.Fn calloc 48.Fn atoll
52function allocates space for an array of 49function converts the initial portion of the string pointed to by
53.Fa nmemb 50.Fa nptr
54objects, each of whose size is 51to
55.Fa size . 52.Li long long integer
56The space is initialized to all bits zero. 53representation.
57.Sh RETURN VALUES 54.Pp
58The 55It is equivalent to:
59.Fn calloc 56.Bd -literal -offset indent
60function returns 57strtoll(nptr, (char **)NULL, 10);
61a pointer to the 58.Ed
62the allocated space if successful; otherwise a null pointer is returned.
63.Sh SEE ALSO 59.Sh SEE ALSO
64.Xr malloc 3 , 60.Xr atof 3 ,
65.Xr realloc 3 , 61.Xr atoi 3 ,
66.Xr free 3 62.Xr atol 3 ,
63.Xr strtod 3 ,
64.Xr strtol 3 ,
65.Xr strtoul 3
67.Sh STANDARDS 66.Sh STANDARDS
68The 67The
69.Fn calloc 68.Fn atoll
70function conforms to 69function conforms to
71.St -ansiC . 70.St -ansiC-99 .
diff --git a/src/lib/libc/stdlib/putenv.c b/src/lib/libc/stdlib/atoll.c
index 2194c2c608..a65e682cfb 100644
--- a/src/lib/libc/stdlib/putenv.c
+++ b/src/lib/libc/stdlib/atoll.c
@@ -1,5 +1,6 @@
1/*- 1/* $OpenBSD: atoll.c,v 1.3 2005/08/08 08:05:36 espie Exp $ */
2 * Copyright (c) 1988 The Regents of the University of California. 2/*
3 * Copyright (c) 1988 Regents of the University of California.
3 * All rights reserved. 4 * All rights reserved.
4 * 5 *
5 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
@@ -10,11 +11,7 @@
10 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. 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 15 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission. 16 * without specific prior written permission.
20 * 17 *
@@ -31,29 +28,11 @@
31 * SUCH DAMAGE. 28 * SUCH DAMAGE.
32 */ 29 */
33 30
34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)putenv.c 5.4 (Berkeley) 2/23/91";*/
36static char *rcsid = "$Id: putenv.c,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */
38
39#include <stdlib.h> 31#include <stdlib.h>
40#include <string.h>
41 32
42int 33long long
43putenv(str) 34atoll(str)
44 const char *str; 35 const char *str;
45{ 36{
46 register char *p, *equal; 37 return(strtoll(str, (char **)NULL, 10));
47 int rval;
48
49 if (!(p = strdup(str)))
50 return(1);
51 if (!(equal = strchr(p, '='))) {
52 (void)free(p);
53 return(1);
54 }
55 *equal = '\0';
56 rval = setenv(p, equal + 1, 1);
57 (void)free(p);
58 return(rval);
59} 38}
diff --git a/src/lib/libc/stdlib/bsearch.3 b/src/lib/libc/stdlib/bsearch.3
index 1622c96c6b..4877a1023e 100644
--- a/src/lib/libc/stdlib/bsearch.3
+++ b/src/lib/libc/stdlib/bsearch.3
@@ -1,5 +1,5 @@
1.\" Copyright (c) 1990, 1991 The Regents of the University of California. 1.\" Copyright (c) 1990, 1991, 1993, 1994
2.\" All rights reserved. 2.\" The Regents of the University of California. All rights reserved.
3.\" 3.\"
4.\" This code is derived from software contributed to Berkeley by 4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information 5.\" the American National Standards Committee X3, on Information
@@ -13,11 +13,7 @@
13.\" 2. Redistributions in binary form must reproduce the above copyright 13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the 14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution. 15.\" documentation and/or other materials provided with the distribution.
16.\" 3. All advertising materials mentioning features or use of this software 16.\" 3. Neither the name of the University nor the names of its contributors
17.\" must display the following acknowledgement:
18.\" This product includes software developed by the University of
19.\" California, Berkeley and its contributors.
20.\" 4. Neither the name of the University nor the names of its contributors
21.\" may be used to endorse or promote products derived from this software 17.\" may be used to endorse or promote products derived from this software
22.\" without specific prior written permission. 18.\" without specific prior written permission.
23.\" 19.\"
@@ -33,10 +29,9 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
35.\" 31.\"
36.\" from: @(#)bsearch.3 5.6 (Berkeley) 6/29/91 32.\" $OpenBSD: bsearch.3,v 1.7 2007/05/31 19:19:31 jmc Exp $
37.\" $Id: bsearch.3,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
38.\" 33.\"
39.Dd June 29, 1991 34.Dd $Mdocdate: May 31 2007 $
40.Dt BSEARCH 3 35.Dt BSEARCH 3
41.Os 36.Os
42.Sh NAME 37.Sh NAME
@@ -51,12 +46,12 @@ The
51.Fn bsearch 46.Fn bsearch
52function searches an array of 47function searches an array of
53.Fa nmemb 48.Fa nmemb
54objects, the initial member of which is 49objects, the initial member of which is
55pointed to by 50pointed to by
56.Fa base , 51.Fa base ,
57for a member that matches the object pointed to by 52for a member that matches the object pointed to by
58.Fa key . 53.Fa key .
59The size of each member of the array is specified by 54The size of each member of the array is specified by
60.Fa size . 55.Fa size .
61.Pp 56.Pp
62The contents of the array should be in ascending sorted order according 57The contents of the array should be in ascending sorted order according
@@ -64,9 +59,7 @@ to the comparison function referenced by
64.Fa compar . 59.Fa compar .
65The 60The
66.Fa compar 61.Fa compar
67routine 62routine is expected to have two arguments which point to the
68is expected to have two
69two arguments which point to the
70.Fa key 63.Fa key
71object and to an array member, in that order, and should return an integer 64object and to an array member, in that order, and should return an integer
72less than, equal to, or greater than zero if the 65less than, equal to, or greater than zero if the
@@ -83,7 +76,7 @@ If two members compare as equal, which member is matched is unspecified.
83.Xr db 3 , 76.Xr db 3 ,
84.Xr lsearch 3 , 77.Xr lsearch 3 ,
85.Xr qsort 3 , 78.Xr qsort 3 ,
86.\" .Xr tsearch 3 79.Xr tsearch 3
87.Sh STANDARDS 80.Sh STANDARDS
88The 81The
89.Fn bsearch 82.Fn bsearch
diff --git a/src/lib/libc/stdlib/bsearch.c b/src/lib/libc/stdlib/bsearch.c
index fac03f694f..b48747236e 100644
--- a/src/lib/libc/stdlib/bsearch.c
+++ b/src/lib/libc/stdlib/bsearch.c
@@ -10,11 +10,7 @@
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the 11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution. 12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software 13 * 3. Neither the name of the University nor the names of its contributors
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. 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 14 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission. 15 * without specific prior written permission.
20 * 16 *
@@ -31,11 +27,6 @@
31 * SUCH DAMAGE. 27 * SUCH DAMAGE.
32 */ 28 */
33 29
34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)bsearch.c 5.4 (Berkeley) 2/23/91";*/
36static char *rcsid = "$Id: bsearch.c,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */
38
39#include <stdlib.h> 30#include <stdlib.h>
40 31
41/* 32/*
@@ -46,7 +37,7 @@ static char *rcsid = "$Id: bsearch.c,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
46 * is odd, moving left simply involves halving lim: e.g., when lim 37 * is odd, moving left simply involves halving lim: e.g., when lim
47 * is 5 we look at item 2, so we change lim to 2 so that we will 38 * is 5 we look at item 2, so we change lim to 2 so that we will
48 * look at items 0 & 1. If lim is even, the same applies. If lim 39 * look at items 0 & 1. If lim is even, the same applies. If lim
49 * is odd, moving right again involes halving lim, this time moving 40 * is odd, moving right again involves halving lim, this time moving
50 * the base up one item past p: e.g., when lim is 5 we change base 41 * the base up one item past p: e.g., when lim is 5 we change base
51 * to item 3 and make lim 2 so that we will look at items 3 and 4. 42 * to item 3 and make lim 2 so that we will look at items 3 and 4.
52 * If lim is even, however, we have to shrink it by one before 43 * If lim is even, however, we have to shrink it by one before
@@ -55,16 +46,12 @@ static char *rcsid = "$Id: bsearch.c,v 1.1.1.1 1995/10/18 08:42:16 deraadt Exp $
55 * look at item 3. 46 * look at item 3.
56 */ 47 */
57void * 48void *
58bsearch(key, base0, nmemb, size, compar) 49bsearch(const void *key, const void *base0, size_t nmemb, size_t size,
59 register const void *key; 50 int (*compar)(const void *, const void *))
60 const void *base0;
61 size_t nmemb;
62 register size_t size;
63 register int (*compar) __P((const void *, const void *));
64{ 51{
65 register const char *base = base0; 52 const char *base = base0;
66 register int lim, cmp; 53 int lim, cmp;
67 register const void *p; 54 const void *p;
68 55
69 for (lim = nmemb; lim != 0; lim >>= 1) { 56 for (lim = nmemb; lim != 0; lim >>= 1) {
70 p = base + (lim >> 1) * size; 57 p = base + (lim >> 1) * size;
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
index a4730694a5..2403fcb0e8 100644
--- a/src/lib/libc/stdlib/div.3
+++ b/src/lib/libc/stdlib/div.3
@@ -11,11 +11,7 @@
11.\" 2. Redistributions in binary form must reproduce the above copyright 11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the 12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution. 13.\" documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software 14.\" 3. Neither the name of the University nor the names of its contributors
15.\" must display the following acknowledgement:
16.\" This product includes software developed by the University of
17.\" California, Berkeley and its contributors.
18.\" 4. 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 15.\" may be used to endorse or promote products derived from this software
20.\" without specific prior written permission. 16.\" without specific prior written permission.
21.\" 17.\"
@@ -31,10 +27,9 @@
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE. 28.\" SUCH DAMAGE.
33.\" 29.\"
34.\" from: @(#)div.3 5.2 (Berkeley) 4/19/91 30.\" $OpenBSD: div.3,v 1.10 2011/07/07 13:30:28 jmc Exp $
35.\" $Id: div.3,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $
36.\" 31.\"
37.Dd April 19, 1991 32.Dd $Mdocdate: July 7 2011 $
38.Dt DIV 3 33.Dt DIV 3
39.Os 34.Os
40.Sh NAME 35.Sh NAME
@@ -47,24 +42,23 @@
47.Sh DESCRIPTION 42.Sh DESCRIPTION
48The 43The
49.Fn div 44.Fn div
50function 45function computes the value
51computes the value 46.Fa num Ns / Ns Fa denom
52.Fa num/denom
53and returns the quotient and remainder in a structure named 47and returns the quotient and remainder in a structure named
54.Fa div_t 48.Fa div_t
55that contains two 49that contains two
56.Em int 50.Li int
57members named 51members named
58.Fa quot 52.Fa quot
59and 53and
60.Fa rem . 54.Fa rem .
61.Sh SEE ALSO 55.Sh SEE ALSO
56.Xr imaxdiv 3 ,
62.Xr ldiv 3 , 57.Xr ldiv 3 ,
63.Xr qdiv 3 , 58.Xr lldiv 3 ,
64.Xr math 3 59.Xr qdiv 3
65.Sh STANDARDS 60.Sh STANDARDS
66The 61The
67.Fn div 62.Fn div
68function 63function conforms to
69conforms to
70.St -ansiC . 64.St -ansiC .
diff --git a/src/lib/libc/stdlib/div.c b/src/lib/libc/stdlib/div.c
index 122ac0deec..f7ac2db4b0 100644
--- a/src/lib/libc/stdlib/div.c
+++ b/src/lib/libc/stdlib/div.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: div.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
1/* 2/*
2 * Copyright (c) 1990 Regents of the University of California. 3 * Copyright (c) 1990 Regents of the University of California.
3 * All rights reserved. 4 * All rights reserved.
@@ -13,11 +14,7 @@
13 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software 17 * 3. Neither the name of the University nor the names of its contributors
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software 18 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission. 19 * without specific prior written permission.
23 * 20 *
@@ -34,16 +31,10 @@
34 * SUCH DAMAGE. 31 * SUCH DAMAGE.
35 */ 32 */
36 33
37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char *sccsid = "from: @(#)div.c 5.2 (Berkeley) 4/16/91";*/
39static char *rcsid = "$Id: div.c,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */
41
42#include <stdlib.h> /* div_t */ 34#include <stdlib.h> /* div_t */
43 35
44div_t 36div_t
45div(num, denom) 37div(int num, int denom)
46 int num, denom;
47{ 38{
48 div_t r; 39 div_t r;
49 40
diff --git a/src/lib/libc/stdlib/drand48.c b/src/lib/libc/stdlib/drand48.c
index ae1a8634dc..b6c046c831 100644
--- a/src/lib/libc/stdlib/drand48.c
+++ b/src/lib/libc/stdlib/drand48.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: drand48.c,v 1.3 2005/08/08 08:05:36 espie Exp $ */
1/* 2/*
2 * Copyright (c) 1993 Martin Birgmeier 3 * Copyright (c) 1993 Martin Birgmeier
3 * All rights reserved. 4 * All rights reserved.
diff --git a/src/lib/libc/stdlib/ecvt.3 b/src/lib/libc/stdlib/ecvt.3
new file mode 100644
index 0000000000..2f107e11fd
--- /dev/null
+++ b/src/lib/libc/stdlib/ecvt.3
@@ -0,0 +1,165 @@
1.\" $OpenBSD: ecvt.3,v 1.9 2010/04/01 17:06:55 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: April 1 2010 $
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 SEE ALSO
142.Xr printf 3 ,
143.Xr strtod 3
144.Sh STANDARDS
145The
146.Fn ecvt ,
147.Fn fcvt
148and
149.Fn gcvt
150functions conform to
151.St -p1003.1-2001 .
152.Sh CAVEATS
153The
154.Fn ecvt
155and
156.Fn fcvt
157functions return a pointer to internal storage space that will be
158overwritten by subsequent calls to either function.
159.Pp
160The maximum possible precision of the return value is limited by the
161precision of a double and may not be the same on all architectures.
162.Pp
163The
164.Xr snprintf 3
165function is preferred over these functions for new code.
diff --git a/src/lib/libc/stdlib/ecvt.c b/src/lib/libc/stdlib/ecvt.c
new file mode 100644
index 0000000000..03ff918967
--- /dev/null
+++ b/src/lib/libc/stdlib/ecvt.c
@@ -0,0 +1,107 @@
1/* $OpenBSD: ecvt.c,v 1.7 2009/10/16 12:15:03 martynas 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 (p == NULL)
66 return (NULL);
67 if (*decpt == 9999) {
68 /* Infinity or Nan, convert to inf or nan like printf */
69 *decpt = 0;
70 c = *p;
71 __freedtoa(p);
72 return(c == 'I' ? "inf" : "nan");
73 }
74 /* Make a local copy and adjust rve to be in terms of s */
75 if (pad && fmode)
76 siz += *decpt;
77 if ((s = (char *)malloc(siz)) == NULL) {
78 __freedtoa(p);
79 return(NULL);
80 }
81 (void) strlcpy(s, p, siz);
82 rve = s + (rve - p);
83 __freedtoa(p);
84 }
85
86 /* Add trailing zeros */
87 if (pad) {
88 siz -= rve - s;
89 while (--siz)
90 *rve++ = '0';
91 *rve = '\0';
92 }
93
94 return(s);
95}
96
97char *
98ecvt(double value, int ndigit, int *decpt, int *sign)
99{
100 return(__cvt(value, ndigit, decpt, sign, 0, 1));
101}
102
103char *
104fcvt(double value, int ndigit, int *decpt, int *sign)
105{
106 return(__cvt(value, ndigit, decpt, sign, 1, 1));
107}
diff --git a/src/lib/libc/stdlib/erand48.c b/src/lib/libc/stdlib/erand48.c
index cc9fbf770c..2ffeaa6e71 100644
--- a/src/lib/libc/stdlib/erand48.c
+++ b/src/lib/libc/stdlib/erand48.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: erand48.c,v 1.3 2005/08/08 08:05:36 espie Exp $ */
1/* 2/*
2 * Copyright (c) 1993 Martin Birgmeier 3 * Copyright (c) 1993 Martin Birgmeier
3 * All rights reserved. 4 * All rights reserved.
diff --git a/src/lib/libc/stdlib/exit.3 b/src/lib/libc/stdlib/exit.3
index adb81ffcb4..45eae80a08 100644
--- a/src/lib/libc/stdlib/exit.3
+++ b/src/lib/libc/stdlib/exit.3
@@ -13,11 +13,7 @@
13.\" 2. Redistributions in binary form must reproduce the above copyright 13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the 14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution. 15.\" documentation and/or other materials provided with the distribution.
16.\" 3. All advertising materials mentioning features or use of this software 16.\" 3. Neither the name of the University nor the names of its contributors
17.\" must display the following acknowledgement:
18.\" This product includes software developed by the University of
19.\" California, Berkeley and its contributors.
20.\" 4. Neither the name of the University nor the names of its contributors
21.\" may be used to endorse or promote products derived from this software 17.\" may be used to endorse or promote products derived from this software
22.\" without specific prior written permission. 18.\" without specific prior written permission.
23.\" 19.\"
@@ -33,25 +29,30 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
35.\" 31.\"
36.\" from: @(#)exit.3 6.6 (Berkeley) 6/29/91 32.\" $OpenBSD: exit.3,v 1.11 2007/05/31 19:19:31 jmc Exp $
37.\" $Id: exit.3,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $
38.\" 33.\"
39.Dd June 29, 1991 34.Dd $Mdocdate: May 31 2007 $
40.Dt EXIT 3 35.Dt EXIT 3
41.Os 36.Os
42.Sh NAME 37.Sh NAME
43.Nm exit 38.Nm exit, _Exit
44.Nd perform normal program termination 39.Nd perform normal program termination
45.Sh SYNOPSIS 40.Sh SYNOPSIS
46.Fd #include <stdlib.h> 41.Fd #include <stdlib.h>
47.Ft void 42.Ft void
48.Fn exit "int status" 43.Fn exit "int status"
44.Ft void
45.Fn _Exit "int status"
49.Sh DESCRIPTION 46.Sh DESCRIPTION
50.Fn Exit 47The
51terminates a process. 48.Fn exit
49and
50.Fn _Exit
51functions terminate a process.
52.Pp 52.Pp
53Before termination it performs the following functions in the 53Before termination,
54order listed: 54.Fn exit
55performs the following operations in the order listed:
55.Bl -enum -offset indent 56.Bl -enum -offset indent
56.It 57.It
57Call the functions registered with the 58Call the functions registered with the
@@ -66,19 +67,48 @@ Unlink all files created with the
66.Xr tmpfile 3 67.Xr tmpfile 3
67function. 68function.
68.El 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.
69.Sh RETURN VALUES 96.Sh RETURN VALUES
70The 97The
71.Fn exit 98.Fn exit
72function 99and
73never returns. 100.Fn _Exit
101functions never return.
74.Sh SEE ALSO 102.Sh SEE ALSO
75.Xr _exit 2 , 103.Xr _exit 2 ,
76.Xr atexit 3 , 104.Xr atexit 3 ,
77.Xr intro 3 , 105.Xr intro 3 ,
106.Xr sysexits 3 ,
78.Xr tmpfile 3 107.Xr tmpfile 3
79.Sh STANDARDS 108.Sh STANDARDS
80The 109The
81.Fn exit 110.Fn exit
82function 111and
83conforms to 112.Fn _Exit
84.St -ansiC . 113functions conform to
114.St -ansiC-99 .
diff --git a/src/lib/libc/stdlib/exit.c b/src/lib/libc/stdlib/exit.c
index b1412f42bb..83fe3d2de5 100644
--- a/src/lib/libc/stdlib/exit.c
+++ b/src/lib/libc/stdlib/exit.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: exit.c,v 1.12 2007/09/03 14:40:16 millert Exp $ */
1/*- 2/*-
2 * Copyright (c) 1990 The Regents of the University of California. 3 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved. 4 * All rights reserved.
@@ -10,11 +11,7 @@
10 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. 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 15 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission. 16 * without specific prior written permission.
20 * 17 *
@@ -31,31 +28,32 @@
31 * SUCH DAMAGE. 28 * SUCH DAMAGE.
32 */ 29 */
33 30
34#if defined(LIBC_SCCS) && !defined(lint) 31#include <sys/types.h>
35/*static char *sccsid = "from: @(#)exit.c 5.4 (Berkeley) 2/23/91";*/ 32#include <sys/mman.h>
36static char *rcsid = "$Id: exit.c,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */
38
39#include <stdlib.h> 33#include <stdlib.h>
40#include <unistd.h> 34#include <unistd.h>
41#include "atexit.h" 35#include "atexit.h"
36#include "thread_private.h"
42 37
43void (*__cleanup)(); 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;
44 46
45/* 47/*
46 * Exit, flushing stdio buffers if necessary. 48 * Exit, flushing stdio buffers if necessary.
47 */ 49 */
48void 50void
49exit(status) 51exit(int status)
50 int status;
51{ 52{
52 register struct atexit *p; 53 /*
53 register int n; 54 * Call functions registered by atexit() or _cxa_atexit()
54 55 * (including the stdio cleanup routine) and then _exit().
55 for (p = __atexit; p; p = p->next) 56 */
56 for (n = p->ind; --n >= 0;) 57 __cxa_finalize(NULL);
57 (*p->fns[n])();
58 if (__cleanup)
59 (*__cleanup)();
60 _exit(status); 58 _exit(status);
61} 59}
diff --git a/src/lib/libc/stdlib/gcvt.c b/src/lib/libc/stdlib/gcvt.c
new file mode 100644
index 0000000000..d9081a7d39
--- /dev/null
+++ b/src/lib/libc/stdlib/gcvt.c
@@ -0,0 +1,125 @@
1/* $OpenBSD: gcvt.c,v 1.12 2010/09/25 13:19:19 millert Exp $ */
2
3/*
4 * Copyright (c) 2002, 2003, 2006, 2010
5 * 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#include <locale.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28
29extern char *__dtoa(double, int, int, int *, int *, char **);
30extern void __freedtoa(char *);
31
32#define DEFPREC 6
33
34char *
35gcvt(double value, int ndigit, char *buf)
36{
37 char *digits, *dst, *src;
38 int i, decpt, sign;
39 struct lconv *lconv;
40
41 lconv = localeconv();
42 if (ndigit <= 0) {
43 /* Match printf(3) behavior. */
44 ndigit = ndigit ? DEFPREC : 1;
45 }
46
47 digits = __dtoa(value, 2, ndigit, &decpt, &sign, NULL);
48 if (digits == NULL)
49 return (NULL);
50 if (decpt == 9999) {
51 /*
52 * Infinity or NaN, convert to inf or nan with sign.
53 * We can't infer buffer size based on ndigit.
54 * We have to assume it is at least 5 chars.
55 */
56 snprintf(buf, 5, "%s%s", sign ? "-" : "",
57 *digits == 'I' ? "inf" : "nan");
58 __freedtoa(digits);
59 return (buf);
60 }
61
62 dst = buf;
63 if (sign)
64 *dst++ = '-';
65
66 /* Match printf(3) behavior for exponential vs. regular fomatting. */
67 if (decpt <= -4 || decpt > ndigit) {
68 /* exponential format (e.g. 1.2345e+13) */
69 if (--decpt < 0) {
70 sign = 1;
71 decpt = -decpt;
72 } else
73 sign = 0;
74 src = digits;
75 *dst++ = *src++;
76 if (*src != '\0') {
77 *dst++ = *lconv->decimal_point;
78 do {
79 *dst++ = *src++;
80 } while (*src != '\0');
81 }
82 *dst++ = 'e';
83 if (sign)
84 *dst++ = '-';
85 else
86 *dst++ = '+';
87 if (decpt < 10) {
88 *dst++ = '0';
89 *dst++ = '0' + decpt;
90 *dst = '\0';
91 } else {
92 /* XXX - optimize */
93 for (sign = decpt, i = 0; (sign /= 10) != 0; i++)
94 continue;
95 dst[i + 1] = '\0';
96 while (decpt != 0) {
97 dst[i--] = '0' + decpt % 10;
98 decpt /= 10;
99 }
100 }
101 } else {
102 /* standard format */
103 for (i = 0, src = digits; i < decpt; i++) {
104 if (*src != '\0')
105 *dst++ = *src++;
106 else
107 *dst++ = '0';
108 }
109 if (*src != '\0') {
110 if (src == digits)
111 *dst++ = '0'; /* zero before decimal point */
112 *dst++ = *lconv->decimal_point;
113 while (decpt < 0) {
114 *dst++ = '0';
115 decpt++;
116 }
117 for (i = decpt; digits[i] != '\0'; i++) {
118 *dst++ = digits[i];
119 }
120 }
121 *dst = '\0';
122 }
123 __freedtoa(digits);
124 return (buf);
125}
diff --git a/src/lib/libc/stdlib/getenv.3 b/src/lib/libc/stdlib/getenv.3
index 411eb35da4..9da27ec11c 100644
--- a/src/lib/libc/stdlib/getenv.3
+++ b/src/lib/libc/stdlib/getenv.3
@@ -1,5 +1,5 @@
1.\" Copyright (c) 1988, 1991 The Regents of the University of California. 1.\" Copyright (c) 1988, 1991, 1993
2.\" All rights reserved. 2.\" The Regents of the University of California. All rights reserved.
3.\" 3.\"
4.\" This code is derived from software contributed to Berkeley by 4.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information 5.\" the American National Standards Committee X3, on Information
@@ -13,11 +13,7 @@
13.\" 2. Redistributions in binary form must reproduce the above copyright 13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the 14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution. 15.\" documentation and/or other materials provided with the distribution.
16.\" 3. All advertising materials mentioning features or use of this software 16.\" 3. Neither the name of the University nor the names of its contributors
17.\" must display the following acknowledgement:
18.\" This product includes software developed by the University of
19.\" California, Berkeley and its contributors.
20.\" 4. Neither the name of the University nor the names of its contributors
21.\" may be used to endorse or promote products derived from this software 17.\" may be used to endorse or promote products derived from this software
22.\" without specific prior written permission. 18.\" without specific prior written permission.
23.\" 19.\"
@@ -33,10 +29,9 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
35.\" 31.\"
36.\" from: @(#)getenv.3 6.11 (Berkeley) 6/29/91 32.\" $OpenBSD: getenv.3,v 1.16 2011/04/27 13:40:15 otto Exp $
37.\" $Id: getenv.3,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $
38.\" 33.\"
39.Dd June 29, 1991 34.Dd $Mdocdate: April 27 2011 $
40.Dt GETENV 3 35.Dt GETENV 3
41.Os 36.Os
42.Sh NAME 37.Sh NAME
@@ -52,82 +47,109 @@
52.Ft int 47.Ft int
53.Fn setenv "const char *name" "const char *value" "int overwrite" 48.Fn setenv "const char *name" "const char *value" "int overwrite"
54.Ft int 49.Ft int
55.Fn putenv "const char *string" 50.Fn putenv "char *string"
56.Ft void 51.Ft int
57.Fn unsetenv "const char *name" 52.Fn unsetenv "const char *name"
58.Sh DESCRIPTION 53.Sh DESCRIPTION
59These functions set, unset and fetch environment variables from the 54These functions set, unset, and fetch environment variables from the host
60host
61.Em environment list . 55.Em environment list .
62For compatibility with differing environment conventions, 56For compatibility with differing environment conventions, the given argument
63the given arguments 57.Fa name
64.Ar name 58may be appended with an equal sign
59.Dq Li \&=
60followed by zero or more characters,
65and 61and
66.Ar value 62.Fa value
67may be appended and prepended, 63may be prepended with an equal sign.
68respectively,
69with an equal sign
70.Dq Li \&= .
71.Pp 64.Pp
72The 65The
73.Fn getenv 66.Fn getenv
74function obtains the current value of the environment variable, 67function obtains the current value of the environment variable
75.Ar name . 68.Fa name .
76If the variable 69If the variable
77.Ar name 70.Fa name
78is not in the current environment , 71is not in the current environment, a null pointer is returned.
79a null pointer is returned.
80.Pp 72.Pp
81The 73The
82.Fn setenv 74.Fn setenv
83function inserts or resets the environment variable 75function inserts or resets the environment variable
84.Ar name 76.Fa name
85in the current environment list. 77in the current environment list.
86If the variable 78If the variable
87.Ar name 79.Fa name
88does not exist in the list, 80does not exist in the list, it is inserted with the given
89it is inserted with the given 81.Fa value .
90.Ar value.
91If the variable does exist, the argument 82If the variable does exist, the argument
92.Ar overwrite 83.Fa overwrite
93is tested; if 84is tested; if
94.Ar overwrite is 85.Fa overwrite
95zero, the 86is zero, the variable is not reset, otherwise it is reset to the given
96variable is not reset, otherwise it is reset 87.Fa value .
97to the given
98.Ar value .
99.Pp 88.Pp
100The 89The
101.Fn putenv 90.Fn putenv
102function takes an argument of the form ``name=value'' and is 91function takes an argument of the form
103equivalent to: 92.Ar name Ns = Ns Ar value .
104.Bd -literal -offset indent 93The memory pointed to by
105setenv(name, value, 1); 94.Ar string
106.Ed 95becomes part of the environment and must not be deallocated by the caller.
96If the variable already exists, it will be overwritten.
97A common source of bugs is to pass a
98.Ar string
99argument that is a locally scoped string buffer.
100This will result in corruption of the environment after leaving
101the scope in which the variable is defined.
102For this reason, the
103.Fn setenv
104function is preferred over
105.Fn putenv .
107.Pp 106.Pp
108The 107The
109.Fn unsetenv 108.Fn unsetenv
110function 109function deletes all instances of the variable name pointed to by
111deletes all instances of the variable name pointed to by
112.Fa name 110.Fa name
113from the list. 111from the list.
114.Sh RETURN VALUES 112.Sh RETURN VALUES
115The functions 113These functions
116.Fn setenv
117and
118.Fn putenv
119return zero if successful; otherwise the global variable 114return zero if successful; otherwise the global variable
120.Va errno 115.Va errno
121is set to indicate the error and a 116is set to indicate the error and \-1 is returned.
122\-1 is returned. 117.Pp
118If
119.Fn getenv
120is successful, the string returned should be considered read-only.
123.Sh ERRORS 121.Sh ERRORS
124.Bl -tag -width Er 122.Bl -tag -width Er
123.It Bq Er EINVAL
124The
125.Fn setenv
126or
127.Fn unsetenv
128function was passed a
129.Ar name
130containing an
131.Sq =
132character.
133.Pp
134The
135.Fn unsetenv
136function was passed an empty
137.Ar name
138or a NULL pointer.
139.Pp
140The
141.Fn putenv
142function was passed a
143.Ar string
144that did not contain an
145.Sq =
146character.
125.It Bq Er ENOMEM 147.It Bq Er ENOMEM
126The function 148The
127.Fn setenv 149.Fn setenv
128or 150or
129.Fn putenv 151.Fn putenv
130failed because they were unable to allocate memory for the environment. 152function failed because it was unable to allocate memory for the environment.
131.El 153.El
132.Sh SEE ALSO 154.Sh SEE ALSO
133.Xr csh 1 , 155.Xr csh 1 ,
@@ -140,12 +162,18 @@ The
140function conforms to 162function conforms to
141.St -ansiC . 163.St -ansiC .
142.Sh HISTORY 164.Sh HISTORY
165The function
166.Fn getenv
167appeared in
168.At v7
169and
170.Bx 3 .
143The functions 171The functions
144.Fn setenv 172.Fn setenv
145and 173and
146.Fn unsetenv 174.Fn unsetenv
147appeared in 175appeared in
148.At v7 . 176.Bx 4.3 Tahoe .
149The 177The
150.Fn putenv 178.Fn putenv
151function appeared in 179function appeared in
diff --git a/src/lib/libc/stdlib/getenv.c b/src/lib/libc/stdlib/getenv.c
index 09d47f2149..fd8482e9e3 100644
--- a/src/lib/libc/stdlib/getenv.c
+++ b/src/lib/libc/stdlib/getenv.c
@@ -1,6 +1,7 @@
1/* $OpenBSD: getenv.c,v 1.10 2010/08/23 22:31:50 millert Exp $ */
1/* 2/*
2 * Copyright (c) 1987 Regents of the University of California. 3 * Copyright (c) 1987, 1993
3 * All rights reserved. 4 * The Regents of the University of California. All rights reserved.
4 * 5 *
5 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
@@ -10,11 +11,7 @@
10 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. 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 15 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission. 16 * without specific prior written permission.
20 * 17 *
@@ -31,52 +28,54 @@
31 * SUCH DAMAGE. 28 * SUCH DAMAGE.
32 */ 29 */
33 30
34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)getenv.c 5.8 (Berkeley) 2/23/91";*/
36static char *rcsid = "$Id: getenv.c,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */
38
39#include <stdlib.h> 31#include <stdlib.h>
40#include <string.h> 32#include <string.h>
41 33
42/* 34char *__findenv(const char *name, int len, int *offset);
43 * getenv --
44 * Returns ptr to value associated with name, if any, else NULL.
45 */
46char *
47getenv(name)
48 const char *name;
49{
50 int offset;
51 char *__findenv();
52
53 return(__findenv(name, &offset));
54}
55 35
56/* 36/*
57 * __findenv -- 37 * __findenv --
58 * Returns pointer to value associated with name, if any, else NULL. 38 * Returns pointer to value associated with name, if any, else NULL.
39 * Starts searching within the environmental array at offset.
59 * Sets offset to be the offset of the name/value combination in the 40 * Sets offset to be the offset of the name/value combination in the
60 * environmental array, for use by setenv(3) and unsetenv(3). 41 * environmental array, for use by putenv(3), setenv(3) and unsetenv(3).
61 * Explicitly removes '=' in argument name. 42 * Explicitly removes '=' in argument name.
62 * 43 *
63 * This routine *should* be a static; don't use it. 44 * This routine *should* be a static; don't use it.
64 */ 45 */
65char * 46char *
66__findenv(name, offset) 47__findenv(const char *name, int len, int *offset)
67 register char *name;
68 int *offset;
69{ 48{
70 extern char **environ; 49 extern char **environ;
71 register int len; 50 int i;
72 register char **P, *C; 51 const char *np;
52 char **p, *cp;
53
54 if (name == NULL || environ == NULL)
55 return (NULL);
56 for (p = environ + *offset; (cp = *p) != NULL; ++p) {
57 for (np = name, i = len; i && *cp; i--)
58 if (*cp++ != *np++)
59 break;
60 if (i == 0 && *cp++ == '=') {
61 *offset = p - environ;
62 return (cp);
63 }
64 }
65 return (NULL);
66}
67
68/*
69 * getenv --
70 * Returns ptr to value associated with name, if any, else NULL.
71 */
72char *
73getenv(const char *name)
74{
75 int offset = 0;
76 const char *np;
73 77
74 for (C = name, len = 0; *C && *C != '='; ++C, ++len); 78 for (np = name; *np && *np != '='; ++np)
75 for (P = environ; *P; ++P) 79 ;
76 if (!strncmp(*P, name, len)) 80 return (__findenv(name, (int)(np - name), &offset));
77 if (*(C = *P + len) == '=') {
78 *offset = P - environ;
79 return(++C);
80 }
81 return(NULL);
82} 81}
diff --git a/src/lib/libc/stdlib/getopt.3 b/src/lib/libc/stdlib/getopt.3
index f843881afd..ecdf42ab76 100644
--- a/src/lib/libc/stdlib/getopt.3
+++ b/src/lib/libc/stdlib/getopt.3
@@ -9,11 +9,7 @@
9.\" 2. Redistributions in binary form must reproduce the above copyright 9.\" 2. Redistributions in binary form must reproduce the above copyright
10.\" notice, this list of conditions and the following disclaimer in the 10.\" notice, this list of conditions and the following disclaimer in the
11.\" documentation and/or other materials provided with the distribution. 11.\" documentation and/or other materials provided with the distribution.
12.\" 3. All advertising materials mentioning features or use of this software 12.\" 3. Neither the name of the University nor the names of its contributors
13.\" must display the following acknowledgement:
14.\" This product includes software developed by the University of
15.\" California, Berkeley and its contributors.
16.\" 4. 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 13.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission. 14.\" without specific prior written permission.
19.\" 15.\"
@@ -29,20 +25,20 @@
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE. 26.\" SUCH DAMAGE.
31.\" 27.\"
32.\" @(#)getopt.3 8.4 (Berkeley) 4/19/94 28.\" $OpenBSD: getopt.3,v 1.42 2011/03/05 22:10:11 guenther Exp $
33.\" 29.\"
34.Dd April 19, 1994 30.Dd $Mdocdate: March 5 2011 $
35.Dt GETOPT 3 31.Dt GETOPT 3
36.Os BSD 4.3 32.Os
37.Sh NAME 33.Sh NAME
38.Nm getopt 34.Nm getopt
39.Nd get option character from command line argument list 35.Nd get option character from command line argument list
40.Sh SYNOPSIS 36.Sh SYNOPSIS
41.Fd #include <unistd.h> 37.Fd #include <unistd.h>
42.Vt extern char *optarg; 38.Vt extern char *optarg;
39.Vt extern int opterr;
43.Vt extern int optind; 40.Vt extern int optind;
44.Vt extern int optopt; 41.Vt extern int optopt;
45.Vt extern int opterr;
46.Vt extern int optreset; 42.Vt extern int optreset;
47.Ft int 43.Ft int
48.Fn getopt "int argc" "char * const *argv" "const char *optstring" 44.Fn getopt "int argc" "char * const *argv" "const char *optstring"
@@ -61,20 +57,25 @@ if it has been specified in the string of accepted option characters,
61.Pp 57.Pp
62The option string 58The option string
63.Fa optstring 59.Fa optstring
64may contain the following elements: individual characters, and 60may contain the following elements: individual characters,
65characters followed by a colon to indicate an option argument 61characters followed by a colon, and characters followed by two colons.
66is to follow. 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.
67For example, an option string 66For example, an option string
68.Li "\&""x"" 67.Qq x
69recognizes an option 68recognizes an option
70.Dq Fl x , 69.Fl x ,
71and an option string 70and an option string
72.Li "\&""x:"" 71.Qq Li x:
73recognizes an option and argument 72recognizes an option and argument
74.Dq Fl x Ar argument . 73.Fl x Ar argument .
75It does not matter to 74It does not matter to
76.Fn getopt 75.Fn getopt
77if a following argument has leading white space. 76if a following argument has leading whitespace; except in the case where
77the argument is optional, denoted with two colons, no leading whitespace
78is permitted.
78.Pp 79.Pp
79On return from 80On return from
80.Fn getopt , 81.Fn getopt ,
@@ -87,23 +88,23 @@ contains the index to the next
87argument for a subsequent call 88argument for a subsequent call
88to 89to
89.Fn getopt . 90.Fn getopt .
90The variable
91.Va optopt
92saves the last
93.Em known
94option character returned by
95.Fn getopt .
96.Pp 91.Pp
97The variable 92The variables
98.Va opterr 93.Va opterr
99and 94and
100.Va optind 95.Va optind
101are both initialized to 1. 96are both initialized to 1.
102The 97The
103.Va optind 98.Va optind
104variable may be set to another value before a set of calls to 99variable may be set to another value larger than 0 before a set of calls to
105.Fn getopt 100.Fn getopt
106in order to skip over more or less argv entries. 101in order to skip over more or less
102.Fa argv
103entries.
104An
105.Va optind
106value of 0 is reserved for compatibility with GNU
107.Fn getopt .
107.Pp 108.Pp
108In order to use 109In order to use
109.Fn getopt 110.Fn getopt
@@ -119,101 +120,154 @@ must be reinitialized.
119.Pp 120.Pp
120The 121The
121.Fn getopt 122.Fn getopt
122function 123function returns \-1 when the argument list is exhausted.
123returns \-1
124when the argument list is exhausted, or a non-recognized
125option is encountered.
126The interpretation of options in the argument list may be cancelled 124The interpretation of options in the argument list may be cancelled
127by the option 125by the option
128.Ql -- 126.Ql --
129(double dash) which causes 127(double dash) which causes
130.Fn getopt 128.Fn getopt
131to signal the end of argument processing and returns \-1. 129to signal the end of argument processing and return \-1.
132When all options have been processed (i.e., up to the first non-option 130When all options have been processed (i.e., up to the first non-option
133argument), 131argument),
134.Fn getopt 132.Fn getopt
135returns \-1. 133returns \-1.
136.Sh DIAGNOSTICS 134.Sh RETURN VALUES
137If the 135The
138.Fn getopt 136.Fn getopt
139function encounters a character not found in the string 137function returns the next known option character in
140.Va optarg 138.Fa optstring .
141or detects
142a missing option argument it writes an error message and returns
143.Ql ?
144to the
145.Em stderr .
146Setting
147.Va opterr
148to a zero will disable these error messages.
149If 139If
150.Va optstring 140.Fn getopt
151has a leading 141encounters a character not found in
152.Ql \&: 142.Fa optstring
153then a missing option argument causes a 143or if it detects a missing option argument,
154.Ql \&: 144it returns
155to be returned in addition to suppressing any error messages. 145.Sq \&?
156.Pp 146(question mark).
157Option arguments are allowed to begin with 147If
158.Dq Li \- ; 148.Fa optstring
159this is reasonable but 149has a leading
160reduces the amount of error checking possible. 150.Sq \&:
161.Sh EXTENSIONS 151then a missing option argument causes
152.Sq \&:
153to be returned instead of
154.Sq \&? .
155In either case, the variable
156.Va optopt
157is set to the character that caused the error.
162The 158The
163.Va optreset
164variable was added to make it possible to call the
165.Fn getopt 159.Fn getopt
166function multiple times. 160function returns \-1 when the argument list is exhausted.
167This is an extension to the 161.Sh EXAMPLES
168.St -p1003.2 162The following code accepts the options
169specification. 163.Fl b
170.Sh EXAMPLE 164and
171.Bd -literal -compact 165.Fl f Ar argument
172extern char *optarg; 166and adjusts
173extern int optind; 167.Va argc
168and
169.Va argv
170after option argument processing has completed.
171.Bd -literal -offset indent
174int bflag, ch, fd; 172int bflag, ch, fd;
175 173
176bflag = 0; 174bflag = 0;
177while ((ch = getopt(argc, argv, "bf:")) != -1) 175while ((ch = getopt(argc, argv, "bf:")) != -1) {
178 switch(ch) { 176 switch (ch) {
179 case 'b': 177 case 'b':
180 bflag = 1; 178 bflag = 1;
181 break; 179 break;
182 case 'f': 180 case 'f':
183 if ((fd = open(optarg, O_RDONLY, 0)) < 0) { 181 if ((fd = open(optarg, O_RDONLY, 0)) == -1)
184 (void)fprintf(stderr, 182 err(1, "%s", optarg);
185 "myname: %s: %s\en", optarg, strerror(errno));
186 exit(1);
187 }
188 break; 183 break;
189 case '?':
190 default: 184 default:
191 usage(); 185 usage();
186 /* NOTREACHED */
187 }
192} 188}
193argc -= optind; 189argc -= optind;
194argv += optind; 190argv += optind;
195.Ed 191.Ed
196.Sh HISTORY 192.Sh DIAGNOSTICS
193If the
194.Fn getopt
195function encounters a character not found in the string
196.Fa optstring
197or detects
198a missing option argument, it writes an error message to
199.Em stderr
200and returns
201.Ql \&? .
202Setting
203.Va opterr
204to a zero will disable these error messages.
205If
206.Fa optstring
207has a leading
208.Ql \&:
209then a missing option argument causes a
210.Ql \&:
211to be returned in addition to suppressing any error messages.
212.Pp
213Option arguments are allowed to begin with
214.Ql - ;
215this is reasonable but reduces the amount of error checking possible.
216.Sh SEE ALSO
217.Xr getopt 1 ,
218.Xr getopt_long 3 ,
219.Xr getsubopt 3
220.Sh STANDARDS
197The 221The
198.Fn getopt 222.Fn getopt
199function appeared 223function implements a superset of the functionality specified by
200.Bx 4.3 . 224.St -p1003.1 .
201.Sh BUGS 225.Pp
226The following extensions are supported:
227.Bl -tag -width "xxx"
228.It Li o
202The 229The
230.Va optreset
231variable was added to make it possible to call the
203.Fn getopt 232.Fn getopt
204function was once specified to return 233function multiple times.
205.Dv EOF 234.It Li o
206instead of \-1. 235If the
207This was changed by 236.Va optind
208.St -p1003.2-92 237variable is set to 0,
209to decouple
210.Fn getopt 238.Fn getopt
211from 239will behave as if the
212.Pa <stdio.h> . 240.Va optreset
213.Pp 241variable has been set.
242This is for compatibility with
243.Tn GNU
244.Fn getopt .
245New code should use
246.Va optreset
247instead.
248.It Li o
249If the first character of
250.Fa optstring
251is a plus sign
252.Pq Ql + ,
253it will be ignored.
254This is for compatibility with
255.Tn GNU
256.Fn getopt .
257.It Li o
258If the first character of
259.Fa optstring
260is a dash
261.Pq Ql - ,
262non-options will be returned as arguments to the option character
263.Ql \e1 .
264This is for compatibility with
265.Tn GNU
266.Fn getopt .
267.It Li o
214A single dash 268A single dash
215.Dq Li - 269.Pq Ql -
216may be specified as an character in 270may be specified as a character in
217.Fa optstring , 271.Fa optstring ,
218however it should 272however it should
219.Em never 273.Em never
@@ -221,40 +275,90 @@ have an argument associated with it.
221This allows 275This allows
222.Fn getopt 276.Fn getopt
223to be used with programs that expect 277to be used with programs that expect
224.Dq Li - 278.Ql -
225as an option flag. 279as an option flag.
226This practice is wrong, and should not be used in any current development. 280This practice is wrong, and should not be used in any current development.
227It is provided for backward compatibility 281It is provided for backward compatibility
228.Em only . 282.Em only .
283Care should be taken not to use
284.Ql -
285as the first character in
286.Fa optstring
287to avoid a semantic conflict with
288.Tn GNU
289.Fn getopt
290semantics (see above).
229By default, a single dash causes 291By default, a single dash causes
230.Fn getopt 292.Fn getopt
231to return \-1. 293to return \-1.
232This is, we believe, compatible with System V. 294.El
295.Pp
296Historic
297.Bx
298versions of
299.Fn getopt
300set
301.Fa optopt
302to the last option character processed.
303However, this conflicts with
304.St -p1003.1
305which stipulates that
306.Fa optopt
307be set to the last character that caused an error.
308.Sh HISTORY
309The
310.Fn getopt
311function appeared in
312.Bx 4.3 .
313.Sh BUGS
314The
315.Fn getopt
316function was once specified to return
317.Dv EOF
318instead of \-1.
319This was changed by
320.St -p1003.2-92
321to decouple
322.Fn getopt
323from
324.Aq Pa stdio.h .
233.Pp 325.Pp
234It is also possible to handle digits as option letters. 326It is possible to handle digits as option letters.
235This allows 327This allows
236.Fn getopt 328.Fn getopt
237to be used with programs that expect a number 329to be used with programs that expect a number
238.Pq Dq Li \&-\&3 330.Pq Dq Li \-3
239as an option. 331as an option.
240This practice is wrong, and should not be used in any current development. 332This practice is wrong, and should not be used in any current development.
241It is provided for backward compatibility 333It is provided for backward compatibility
242.Em only . 334.Em only .
243The following code fragment works in most cases. 335The following code fragment works in most cases and can handle mixed
336number and letter arguments.
244.Bd -literal -offset indent 337.Bd -literal -offset indent
245int length; 338int aflag = 0, bflag = 0, ch, lastch = '\e0';
246char *p; 339int length = -1, newarg = 1, prevoptind = 1;
247 340
248while ((c = getopt(argc, argv, "0123456789")) != -1) 341while ((ch = getopt(argc, argv, "0123456789ab")) != -1) {
249 switch (c) { 342 switch (ch) {
250 case '0': case '1': case '2': case '3': case '4': 343 case '0': case '1': case '2': case '3': case '4':
251 case '5': case '6': case '7': case '8': case '9': 344 case '5': case '6': case '7': case '8': case '9':
252 p = argv[optind - 1]; 345 if (newarg || !isdigit(lastch))
253 if (p[0] == '-' && p[1] == ch && !p[2]) 346 length = 0;
254 length = atoi(++p); 347 else if (length > INT_MAX / 10)
255 else 348 usage();
256 length = atoi(argv[optind] + 1); 349 length = (length * 10) + (ch - '0');
257 break; 350 break;
351 case 'a':
352 aflag = 1;
353 break;
354 case 'b':
355 bflag = 1;
356 break;
357 default:
358 usage();
258 } 359 }
360 lastch = ch;
361 newarg = optind != prevoptind;
362 prevoptind = optind;
259} 363}
260.Ed 364.Ed
diff --git a/src/lib/libc/stdlib/getopt.c b/src/lib/libc/stdlib/getopt.c
deleted file mode 100644
index 63c5e6a479..0000000000
--- a/src/lib/libc/stdlib/getopt.c
+++ /dev/null
@@ -1,118 +0,0 @@
1/*
2 * Copyright (c) 1987, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. 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#if defined(LIBC_SCCS) && !defined(lint)
35/* static char sccsid[] = "from: @(#)getopt.c 8.2 (Berkeley) 4/2/94"; */
36static char *rcsid = "$Id: getopt.c,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */
38
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42
43int opterr = 1, /* if error message should be printed */
44 optind = 1, /* index into parent argv vector */
45 optopt, /* character checked for validity */
46 optreset; /* reset getopt */
47char *optarg; /* argument associated with option */
48
49#define BADCH (int)'?'
50#define BADARG (int)':'
51#define EMSG ""
52
53/*
54 * getopt --
55 * Parse argc/argv argument vector.
56 */
57int
58getopt(nargc, nargv, ostr)
59 int nargc;
60 char * const *nargv;
61 const char *ostr;
62{
63 extern char *__progname;
64 static char *place = EMSG; /* option letter processing */
65 char *oli; /* option letter list index */
66
67 if (optreset || !*place) { /* update scanning pointer */
68 optreset = 0;
69 if (optind >= nargc || *(place = nargv[optind]) != '-') {
70 place = EMSG;
71 return (-1);
72 }
73 if (place[1] && *++place == '-') { /* found "--" */
74 ++optind;
75 place = EMSG;
76 return (-1);
77 }
78 } /* option letter okay? */
79 if ((optopt = (int)*place++) == (int)':' ||
80 !(oli = strchr(ostr, optopt))) {
81 /*
82 * if the user didn't specify '-' as an option,
83 * assume it means -1.
84 */
85 if (optopt == (int)'-')
86 return (-1);
87 if (!*place)
88 ++optind;
89 if (opterr && *ostr != ':')
90 (void)fprintf(stderr,
91 "%s: illegal option -- %c\n", __progname, optopt);
92 return (BADCH);
93 }
94 if (*++oli != ':') { /* don't need argument */
95 optarg = NULL;
96 if (!*place)
97 ++optind;
98 }
99 else { /* need an argument */
100 if (*place) /* no white space */
101 optarg = place;
102 else if (nargc <= ++optind) { /* no arg */
103 place = EMSG;
104 if (*ostr == ':')
105 return (BADARG);
106 if (opterr)
107 (void)fprintf(stderr,
108 "%s: option requires an argument -- %c\n",
109 __progname, optopt);
110 return (BADCH);
111 }
112 else /* white space */
113 optarg = nargv[optind];
114 place = EMSG;
115 ++optind;
116 }
117 return (optopt); /* dump back option letter */
118}
diff --git a/src/lib/libc/stdlib/getopt_long.3 b/src/lib/libc/stdlib/getopt_long.3
new file mode 100644
index 0000000000..eaa5ead1c7
--- /dev/null
+++ b/src/lib/libc/stdlib/getopt_long.3
@@ -0,0 +1,445 @@
1.\" $OpenBSD: getopt_long.3,v 1.19 2011/03/21 13:41:50 espie 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: March 21 2011 $
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 an array to be initialized describing the long
104options.
105Each element of the array is a structure:
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 IMPLEMENTATION DIFFERENCES
208This section describes differences to the GNU implementation
209found in glibc-2.1.3:
210.Bl -bullet
211.It
212handling of
213.Ql -
214within the option string (not the first character):
215.Bl -tag -width "OpenBSD"
216.It GNU
217treats a
218.Ql -
219on the command line as a non-argument.
220.It OpenBSD
221a
222.Ql -
223within the option string matches a
224.Ql -
225(single dash) on the command line.
226This functionality is provided for backward compatibility with
227programs, such as
228.Xr su 1 ,
229that use
230.Ql -
231as an option flag.
232This practice is wrong, and should not be used in any current development.
233.El
234.It
235handling of
236.Ql ::
237in the option string in the presence of
238.Ev POSIXLY_CORRECT :
239.Bl -tag -width "OpenBSD"
240.It Both
241GNU and
242.Ox
243ignore
244.Ev POSIXLY_CORRECT
245here and take
246.Ql ::
247to mean the preceding option takes an optional argument.
248.El
249.It
250return value in case of missing argument if first character
251(after
252.Ql +
253or
254.Ql - )
255in the option string is not
256.Ql \&: :
257.Bl -tag -width "OpenBSD"
258.It GNU
259returns
260.Ql \&?
261.It OpenBSD
262returns
263.Ql \&:
264(since
265.Ox Ns 's
266.Xr getopt 3
267does).
268.El
269.It
270handling of
271.Ql --a
272in
273.Xr getopt 3 :
274.Bl -tag -width "OpenBSD"
275.It GNU
276parses this as option
277.Ql - ,
278option
279.Ql a .
280.It OpenBSD
281parses this as
282.Ql -- ,
283and returns \-1 (ignoring the
284.Ql a )
285(because the original
286.Fn getopt
287did.)
288.El
289.It
290setting of
291.Va optopt
292for long options with
293.Va flag
294.No non- Ns Dv NULL :
295.Bl -tag -width "OpenBSD"
296.It GNU
297sets
298.Va optopt
299to
300.Va val .
301.It OpenBSD
302sets
303.Va optopt
304to 0 (since
305.Va val
306would never be returned).
307.El
308.It
309handling of
310.Ql -W
311with
312.Ql W;
313in the option string in
314.Xr getopt 3
315(not
316.Fn getopt_long ) :
317.Bl -tag -width "OpenBSD"
318.It GNU
319causes a segmentation fault.
320.It OpenBSD
321no special handling is done;
322.Ql W;
323is interpreted as two separate options, neither of which take an argument.
324.El
325.It
326setting of
327.Va optarg
328for long options without an argument that are invoked via
329.Ql -W
330(with
331.Ql W;
332in the option string):
333.Bl -tag -width "OpenBSD"
334.It GNU
335sets
336.Va optarg
337to the option name (the argument of
338.Ql -W ) .
339.It OpenBSD
340sets
341.Va optarg
342to
343.Dv NULL
344(the argument of the long option).
345.El
346.It
347handling of
348.Ql -W
349with an argument that is not (a prefix to) a known long option
350(with
351.Ql W;
352in the option string):
353.Bl -tag -width "OpenBSD"
354.It GNU
355returns
356.Ql -W
357with
358.Va optarg
359set to the unknown option.
360.It OpenBSD
361treats this as an error (unknown option) and returns
362.Ql \&?
363with
364.Va optopt
365set to 0 and
366.Va optarg
367set to
368.Dv NULL
369(as GNU's man page documents).
370.El
371.It
372The error messages are different.
373.It
374.Ox
375does not permute the argument vector at the same points in
376the calling sequence as GNU does.
377The aspects normally used by the caller
378(ordering after \-1 is returned, value of
379.Va optind
380relative to current positions) are the same, though.
381(We do fewer variable swaps.)
382.El
383.Sh ENVIRONMENT
384.Bl -tag -width Ev
385.It Ev POSIXLY_CORRECT
386If set, option processing stops when the first non-option is found and
387a leading
388.Sq +
389in the
390.Ar optstring
391is ignored.
392.El
393.Sh EXAMPLES
394.Bd -literal
395int bflag, ch, fd;
396int daggerset;
397
398/* options descriptor */
399static struct option longopts[] = {
400 { "buffy", no_argument, NULL, 'b' },
401 { "fluoride", required_argument, NULL, 'f' },
402 { "daggerset", no_argument, &daggerset, 1 },
403 { NULL, 0, NULL, 0 }
404};
405
406bflag = 0;
407while ((ch = getopt_long(argc, argv, "bf:", longopts, NULL)) != -1)
408 switch (ch) {
409 case 'b':
410 bflag = 1;
411 break;
412 case 'f':
413 if ((fd = open(optarg, O_RDONLY, 0)) == -1)
414 err(1, "unable to open %s", optarg);
415 break;
416 case 0:
417 if (daggerset)
418 fprintf(stderr, "Buffy will use her dagger to "
419 "apply fluoride to dracula's teeth\en");
420 break;
421 default:
422 usage();
423 /* NOTREACHED */
424 }
425argc -= optind;
426argv += optind;
427.Ed
428.Sh SEE ALSO
429.Xr getopt 3
430.Sh HISTORY
431The
432.Fn getopt_long
433and
434.Fn getopt_long_only
435functions first appeared in GNU libiberty.
436This implementation first appeared in
437.Ox 3.3 .
438.Sh BUGS
439The
440.Ar argv
441argument is not really
442.Dv const
443as its elements may be permuted (unless
444.Ev POSIXLY_CORRECT
445is 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..e149fe0ace
--- /dev/null
+++ b/src/lib/libc/stdlib/getopt_long.c
@@ -0,0 +1,511 @@
1/* $OpenBSD: getopt_long.c,v 1.25 2011/03/05 22:10:11 guenther 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
58int opterr = 1; /* if error message should be printed */
59int optind = 1; /* index into parent argv vector */
60int optopt = '?'; /* character checked for validity */
61int optreset; /* reset getopt */
62char *optarg; /* argument associated with option */
63
64#define PRINT_ERROR ((opterr) && (*options != ':'))
65
66#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
67#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
68#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
69
70/* return values */
71#define BADCH (int)'?'
72#define BADARG ((*options == ':') ? (int)':' : (int)'?')
73#define INORDER (int)1
74
75#define EMSG ""
76
77static int getopt_internal(int, char * const *, const char *,
78 const struct option *, int *, int);
79static int parse_long_options(char * const *, const char *,
80 const struct option *, int *, int);
81static int gcd(int, int);
82static void permute_args(int, int, int, char * const *);
83
84static char *place = EMSG; /* option letter processing */
85
86/* XXX: set optreset to 1 rather than these two */
87static int nonopt_start = -1; /* first non option argument (for permute) */
88static int nonopt_end = -1; /* first option after non options (for permute) */
89
90/* Error messages */
91static const char recargchar[] = "option requires an argument -- %c";
92static const char recargstring[] = "option requires an argument -- %s";
93static const char ambig[] = "ambiguous option -- %.*s";
94static const char noarg[] = "option doesn't take an argument -- %.*s";
95static const char illoptchar[] = "unknown option -- %c";
96static const char illoptstring[] = "unknown option -- %s";
97
98/*
99 * Compute the greatest common divisor of a and b.
100 */
101static int
102gcd(int a, int b)
103{
104 int c;
105
106 c = a % b;
107 while (c != 0) {
108 a = b;
109 b = c;
110 c = a % b;
111 }
112
113 return (b);
114}
115
116/*
117 * Exchange the block from nonopt_start to nonopt_end with the block
118 * from nonopt_end to opt_end (keeping the same order of arguments
119 * in each block).
120 */
121static void
122permute_args(int panonopt_start, int panonopt_end, int opt_end,
123 char * const *nargv)
124{
125 int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
126 char *swap;
127
128 /*
129 * compute lengths of blocks and number and size of cycles
130 */
131 nnonopts = panonopt_end - panonopt_start;
132 nopts = opt_end - panonopt_end;
133 ncycle = gcd(nnonopts, nopts);
134 cyclelen = (opt_end - panonopt_start) / ncycle;
135
136 for (i = 0; i < ncycle; i++) {
137 cstart = panonopt_end+i;
138 pos = cstart;
139 for (j = 0; j < cyclelen; j++) {
140 if (pos >= panonopt_end)
141 pos -= nnonopts;
142 else
143 pos += nopts;
144 swap = nargv[pos];
145 /* LINTED const cast */
146 ((char **) nargv)[pos] = nargv[cstart];
147 /* LINTED const cast */
148 ((char **)nargv)[cstart] = swap;
149 }
150 }
151}
152
153/*
154 * parse_long_options --
155 * Parse long options in argc/argv argument vector.
156 * Returns -1 if short_too is set and the option does not match long_options.
157 */
158static int
159parse_long_options(char * const *nargv, const char *options,
160 const struct option *long_options, int *idx, int short_too)
161{
162 char *current_argv, *has_equal;
163 size_t current_argv_len;
164 int i, match;
165
166 current_argv = place;
167 match = -1;
168
169 optind++;
170
171 if ((has_equal = strchr(current_argv, '=')) != NULL) {
172 /* argument found (--option=arg) */
173 current_argv_len = has_equal - current_argv;
174 has_equal++;
175 } else
176 current_argv_len = strlen(current_argv);
177
178 for (i = 0; long_options[i].name; i++) {
179 /* find matching long option */
180 if (strncmp(current_argv, long_options[i].name,
181 current_argv_len))
182 continue;
183
184 if (strlen(long_options[i].name) == current_argv_len) {
185 /* exact match */
186 match = i;
187 break;
188 }
189 /*
190 * If this is a known short option, don't allow
191 * a partial match of a single character.
192 */
193 if (short_too && current_argv_len == 1)
194 continue;
195
196 if (match == -1) /* partial match */
197 match = i;
198 else {
199 /* ambiguous abbreviation */
200 if (PRINT_ERROR)
201 warnx(ambig, (int)current_argv_len,
202 current_argv);
203 optopt = 0;
204 return (BADCH);
205 }
206 }
207 if (match != -1) { /* option found */
208 if (long_options[match].has_arg == no_argument
209 && has_equal) {
210 if (PRINT_ERROR)
211 warnx(noarg, (int)current_argv_len,
212 current_argv);
213 /*
214 * XXX: GNU sets optopt to val regardless of flag
215 */
216 if (long_options[match].flag == NULL)
217 optopt = long_options[match].val;
218 else
219 optopt = 0;
220 return (BADARG);
221 }
222 if (long_options[match].has_arg == required_argument ||
223 long_options[match].has_arg == optional_argument) {
224 if (has_equal)
225 optarg = has_equal;
226 else if (long_options[match].has_arg ==
227 required_argument) {
228 /*
229 * optional argument doesn't use next nargv
230 */
231 optarg = nargv[optind++];
232 }
233 }
234 if ((long_options[match].has_arg == required_argument)
235 && (optarg == NULL)) {
236 /*
237 * Missing argument; leading ':' indicates no error
238 * should be generated.
239 */
240 if (PRINT_ERROR)
241 warnx(recargstring,
242 current_argv);
243 /*
244 * XXX: GNU sets optopt to val regardless of flag
245 */
246 if (long_options[match].flag == NULL)
247 optopt = long_options[match].val;
248 else
249 optopt = 0;
250 --optind;
251 return (BADARG);
252 }
253 } else { /* unknown option */
254 if (short_too) {
255 --optind;
256 return (-1);
257 }
258 if (PRINT_ERROR)
259 warnx(illoptstring, current_argv);
260 optopt = 0;
261 return (BADCH);
262 }
263 if (idx)
264 *idx = match;
265 if (long_options[match].flag) {
266 *long_options[match].flag = long_options[match].val;
267 return (0);
268 } else
269 return (long_options[match].val);
270}
271
272/*
273 * getopt_internal --
274 * Parse argc/argv argument vector. Called by user level routines.
275 */
276static int
277getopt_internal(int nargc, char * const *nargv, const char *options,
278 const struct option *long_options, int *idx, int flags)
279{
280 char *oli; /* option letter list index */
281 int optchar, short_too;
282 static int posixly_correct = -1;
283
284 if (options == NULL)
285 return (-1);
286
287 /*
288 * XXX Some GNU programs (like cvs) set optind to 0 instead of
289 * XXX using optreset. Work around this braindamage.
290 */
291 if (optind == 0)
292 optind = optreset = 1;
293
294 /*
295 * Disable GNU extensions if POSIXLY_CORRECT is set or options
296 * string begins with a '+'.
297 */
298 if (posixly_correct == -1 || optreset)
299 posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
300 if (*options == '-')
301 flags |= FLAG_ALLARGS;
302 else if (posixly_correct || *options == '+')
303 flags &= ~FLAG_PERMUTE;
304 if (*options == '+' || *options == '-')
305 options++;
306
307 optarg = NULL;
308 if (optreset)
309 nonopt_start = nonopt_end = -1;
310start:
311 if (optreset || !*place) { /* update scanning pointer */
312 optreset = 0;
313 if (optind >= nargc) { /* end of argument vector */
314 place = EMSG;
315 if (nonopt_end != -1) {
316 /* do permutation, if we have to */
317 permute_args(nonopt_start, nonopt_end,
318 optind, nargv);
319 optind -= nonopt_end - nonopt_start;
320 }
321 else if (nonopt_start != -1) {
322 /*
323 * If we skipped non-options, set optind
324 * to the first of them.
325 */
326 optind = nonopt_start;
327 }
328 nonopt_start = nonopt_end = -1;
329 return (-1);
330 }
331 if (*(place = nargv[optind]) != '-' ||
332 (place[1] == '\0' && strchr(options, '-') == NULL)) {
333 place = EMSG; /* found non-option */
334 if (flags & FLAG_ALLARGS) {
335 /*
336 * GNU extension:
337 * return non-option as argument to option 1
338 */
339 optarg = nargv[optind++];
340 return (INORDER);
341 }
342 if (!(flags & FLAG_PERMUTE)) {
343 /*
344 * If no permutation wanted, stop parsing
345 * at first non-option.
346 */
347 return (-1);
348 }
349 /* do permutation */
350 if (nonopt_start == -1)
351 nonopt_start = optind;
352 else if (nonopt_end != -1) {
353 permute_args(nonopt_start, nonopt_end,
354 optind, nargv);
355 nonopt_start = optind -
356 (nonopt_end - nonopt_start);
357 nonopt_end = -1;
358 }
359 optind++;
360 /* process next argument */
361 goto start;
362 }
363 if (nonopt_start != -1 && nonopt_end == -1)
364 nonopt_end = optind;
365
366 /*
367 * If we have "-" do nothing, if "--" we are done.
368 */
369 if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
370 optind++;
371 place = EMSG;
372 /*
373 * We found an option (--), so if we skipped
374 * non-options, we have to permute.
375 */
376 if (nonopt_end != -1) {
377 permute_args(nonopt_start, nonopt_end,
378 optind, nargv);
379 optind -= nonopt_end - nonopt_start;
380 }
381 nonopt_start = nonopt_end = -1;
382 return (-1);
383 }
384 }
385
386 /*
387 * Check long options if:
388 * 1) we were passed some
389 * 2) the arg is not just "-"
390 * 3) either the arg starts with -- we are getopt_long_only()
391 */
392 if (long_options != NULL && place != nargv[optind] &&
393 (*place == '-' || (flags & FLAG_LONGONLY))) {
394 short_too = 0;
395 if (*place == '-')
396 place++; /* --foo long option */
397 else if (*place != ':' && strchr(options, *place) != NULL)
398 short_too = 1; /* could be short option too */
399
400 optchar = parse_long_options(nargv, options, long_options,
401 idx, short_too);
402 if (optchar != -1) {
403 place = EMSG;
404 return (optchar);
405 }
406 }
407
408 if ((optchar = (int)*place++) == (int)':' ||
409 (optchar == (int)'-' && *place != '\0') ||
410 (oli = strchr(options, optchar)) == NULL) {
411 /*
412 * If the user specified "-" and '-' isn't listed in
413 * options, return -1 (non-option) as per POSIX.
414 * Otherwise, it is an unknown option character (or ':').
415 */
416 if (optchar == (int)'-' && *place == '\0')
417 return (-1);
418 if (!*place)
419 ++optind;
420 if (PRINT_ERROR)
421 warnx(illoptchar, optchar);
422 optopt = optchar;
423 return (BADCH);
424 }
425 if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
426 /* -W long-option */
427 if (*place) /* no space */
428 /* NOTHING */;
429 else if (++optind >= nargc) { /* no arg */
430 place = EMSG;
431 if (PRINT_ERROR)
432 warnx(recargchar, optchar);
433 optopt = optchar;
434 return (BADARG);
435 } else /* white space */
436 place = nargv[optind];
437 optchar = parse_long_options(nargv, options, long_options,
438 idx, 0);
439 place = EMSG;
440 return (optchar);
441 }
442 if (*++oli != ':') { /* doesn't take argument */
443 if (!*place)
444 ++optind;
445 } else { /* takes (optional) argument */
446 optarg = NULL;
447 if (*place) /* no white space */
448 optarg = place;
449 else if (oli[1] != ':') { /* arg not optional */
450 if (++optind >= nargc) { /* no arg */
451 place = EMSG;
452 if (PRINT_ERROR)
453 warnx(recargchar, optchar);
454 optopt = optchar;
455 return (BADARG);
456 } else
457 optarg = nargv[optind];
458 }
459 place = EMSG;
460 ++optind;
461 }
462 /* dump back option letter */
463 return (optchar);
464}
465
466/*
467 * getopt --
468 * Parse argc/argv argument vector.
469 *
470 * [eventually this will replace the BSD getopt]
471 */
472int
473getopt(int nargc, char * const *nargv, const char *options)
474{
475
476 /*
477 * We don't pass FLAG_PERMUTE to getopt_internal() since
478 * the BSD getopt(3) (unlike GNU) has never done this.
479 *
480 * Furthermore, since many privileged programs call getopt()
481 * before dropping privileges it makes sense to keep things
482 * as simple (and bug-free) as possible.
483 */
484 return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
485}
486
487/*
488 * getopt_long --
489 * Parse argc/argv argument vector.
490 */
491int
492getopt_long(int nargc, char * const *nargv, const char *options,
493 const struct option *long_options, int *idx)
494{
495
496 return (getopt_internal(nargc, nargv, options, long_options, idx,
497 FLAG_PERMUTE));
498}
499
500/*
501 * getopt_long_only --
502 * Parse argc/argv argument vector.
503 */
504int
505getopt_long_only(int nargc, char * const *nargv, const char *options,
506 const struct option *long_options, int *idx)
507{
508
509 return (getopt_internal(nargc, nargv, options, long_options, idx,
510 FLAG_PERMUTE|FLAG_LONGONLY));
511}
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..ea264b57c8
--- /dev/null
+++ b/src/lib/libc/stdlib/hcreate.3
@@ -0,0 +1,239 @@
1.\" $OpenBSD: hcreate.3,v 1.6 2010/07/28 09:00:20 ray Exp $
2.\" $NetBSD: hcreate.3,v 1.8 2010/05/01 06:18:03 jruoho 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: July 28 2010 $
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.Vt ENTRY ,
88defined in the
89.In search.h
90header.
91This is a structure type that contains two pointers:
92.Pp
93.Bl -tag -compact -offset indent -width "void *data "
94.It Fa char *key
95comparison key
96.It Fa void *data
97pointer to data associated with
98.Fa key
99.El
100.Pp
101The key comparison function used by
102.Fn hsearch
103is
104.Xr strcmp 3 .
105.Pp
106The
107.Fa action
108argument is of type
109.Vt ACTION ,
110an enumeration type which defines the following values:
111.Bl -tag -offset indent -width ENTERXX
112.It Dv ENTER
113Insert
114.Fa item
115into the hash table.
116If an existing item with the same key is found, it is not replaced.
117Note that the
118.Fa key
119and
120.Fa data
121elements of
122.Fa item
123are used directly by the new table entry.
124The storage for the
125key must not be modified during the lifetime of the hash table.
126.It Dv FIND
127Search the hash table without inserting
128.Fa item .
129.El
130.Pp
131Note that the comparison
132.Fa key
133must be allocated using
134.Xr malloc 3
135or
136.Xr calloc 3
137if action is
138.Dv ENTER
139and
140.Fn hdestroy
141will be called.
142This is because
143.Fn hdestroy
144will call
145.Xr free 3
146for each comparison
147.Fa key
148(but not
149.Fa data ) .
150Typically the comparison
151.Fa key
152is allocated by using
153.Xr strdup 3 .
154.Sh RETURN VALUES
155If successful, the
156.Fn hcreate
157function returns a non-zero value.
158Otherwise, a value of 0 is returned and
159.Va errno
160is set to indicate the error.
161.Pp
162The
163.Fn hdestroy
164functions
165returns no value.
166.Pp
167If successful, the
168.Fn hsearch
169function returns a pointer to a hash table entry matching
170the provided key.
171If the action is
172.Dv FIND
173and the item was not found, or if the action is
174.Dv ENTER
175and the insertion failed,
176.Dv NULL
177is returned and
178.Va errno
179is set to indicate the error.
180If the action is
181.Dv ENTER
182and an entry already existed in the table matching the given
183key, the existing entry is returned and is not replaced.
184.Sh ERRORS
185The
186.Fn hcreate
187and
188.Fn hsearch
189functions will fail if:
190.Bl -tag -width Er
191.It Bq Er ENOMEM
192Insufficient memory is available.
193.El
194.Sh SEE ALSO
195.Xr bsearch 3 ,
196.Xr lsearch 3 ,
197.Xr malloc 3 ,
198.Xr strcmp 3
199.Sh STANDARDS
200The
201.Fn hcreate ,
202.Fn hdestroy
203and
204.Fn hsearch
205functions conform to
206.St -xpg4.2 .
207.Sh HISTORY
208The
209.Fn hcreate ,
210.Fn hdestroy
211and
212.Fn hsearch
213functions first appeared in
214.At V .
215.Sh CAVEATS
216At least the following limitations can be mentioned:
217.Bl -bullet
218.It
219The interface permits the use of only one hash table at a time.
220.It
221Individual hash table entries can be added, but not deleted.
222.It
223The standard is indecipherable about the
224internal memory usage of the functions,
225mentioning only that
226.Do
227.Fn hcreate
228and
229.Fn hsearch
230functions may use
231.Fn malloc
232to allocate space
233.Dc .
234This limits the portability of the functions,
235given that other implementations may not
236.Xr free 3
237the buffer pointed by
238.Fa key .
239.El
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
index bd998fa357..ad3fffbcd9 100644
--- a/src/lib/libc/stdlib/heapsort.c
+++ b/src/lib/libc/stdlib/heapsort.c
@@ -13,11 +13,7 @@
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution. 15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software 16 * 3. Neither the name of the University nor the names of its contributors
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software 17 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission. 18 * without specific prior written permission.
23 * 19 *
@@ -34,11 +30,6 @@
34 * SUCH DAMAGE. 30 * SUCH DAMAGE.
35 */ 31 */
36 32
37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char sccsid[] = "from: @(#)heapsort.c 8.1 (Berkeley) 6/4/93";*/
39static char *rcsid = "$Id: heapsort.c,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */
41
42#include <sys/types.h> 33#include <sys/types.h>
43#include <errno.h> 34#include <errno.h>
44#include <stdlib.h> 35#include <stdlib.h>
@@ -73,7 +64,7 @@ static char *rcsid = "$Id: heapsort.c,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp
73 * Build the list into a heap, where a heap is defined such that for 64 * Build the list into a heap, where a heap is defined such that for
74 * the records K1 ... KN, Kj/2 >= Kj for 1 <= j/2 <= j <= N. 65 * the records K1 ... KN, Kj/2 >= Kj for 1 <= j/2 <= j <= N.
75 * 66 *
76 * There two cases. If j == nmemb, select largest of Ki and Kj. If 67 * There are two cases. If j == nmemb, select largest of Ki and Kj. If
77 * j < nmemb, select largest of Ki, Kj and Kj+1. 68 * j < nmemb, select largest of Ki, Kj and Kj+1.
78 */ 69 */
79#define CREATE(initval, nmemb, par_i, child_i, par, child, size, count, tmp) { \ 70#define CREATE(initval, nmemb, par_i, child_i, par, child, size, count, tmp) { \
@@ -95,12 +86,12 @@ static char *rcsid = "$Id: heapsort.c,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp
95 * Select the top of the heap and 'heapify'. Since by far the most expensive 86 * Select the top of the heap and 'heapify'. Since by far the most expensive
96 * action is the call to the compar function, a considerable optimization 87 * action is the call to the compar function, a considerable optimization
97 * in the average case can be achieved due to the fact that k, the displaced 88 * in the average case can be achieved due to the fact that k, the displaced
98 * elememt, is ususally quite small, so it would be preferable to first 89 * element, is usually quite small, so it would be preferable to first
99 * heapify, always maintaining the invariant that the larger child is copied 90 * heapify, always maintaining the invariant that the larger child is copied
100 * over its parent's record. 91 * over its parent's record.
101 * 92 *
102 * Then, starting from the *bottom* of the heap, finding k's correct place, 93 * Then, starting from the *bottom* of the heap, finding k's correct place,
103 * again maintianing the invariant. As a result of the invariant no element 94 * again maintaining the invariant. As a result of the invariant no element
104 * is 'lost' when k is assigned its correct place in the heap. 95 * is 'lost' when k is assigned its correct place in the heap.
105 * 96 *
106 * The time savings from this optimization are on the order of 15-20% for the 97 * The time savings from this optimization are on the order of 15-20% for the
@@ -139,13 +130,11 @@ static char *rcsid = "$Id: heapsort.c,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp
139 * only advantage over quicksort is that it requires little additional memory. 130 * only advantage over quicksort is that it requires little additional memory.
140 */ 131 */
141int 132int
142heapsort(vbase, nmemb, size, compar) 133heapsort(void *vbase, size_t nmemb, size_t size,
143 void *vbase; 134 int (*compar)(const void *, const void *))
144 size_t nmemb, size;
145 int (*compar) __P((const void *, const void *));
146{ 135{
147 register int cnt, i, j, l; 136 size_t cnt, i, j, l;
148 register char tmp, *tmp1, *tmp2; 137 char tmp, *tmp1, *tmp2;
149 char *base, *k, *p, *t; 138 char *base, *k, *p, *t;
150 139
151 if (nmemb <= 1) 140 if (nmemb <= 1)
diff --git a/src/lib/libc/stdlib/free.3 b/src/lib/libc/stdlib/imaxabs.3
index 3d0131d7de..74b724fcbf 100644
--- a/src/lib/libc/stdlib/free.3
+++ b/src/lib/libc/stdlib/imaxabs.3
@@ -1,4 +1,4 @@
1.\" Copyright (c) 1991 The Regents of the University of California. 1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved. 2.\" All rights reserved.
3.\" 3.\"
4.\" This code is derived from software contributed to Berkeley by 4.\" This code is derived from software contributed to Berkeley by
@@ -13,11 +13,7 @@
13.\" 2. Redistributions in binary form must reproduce the above copyright 13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the 14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution. 15.\" documentation and/or other materials provided with the distribution.
16.\" 3. All advertising materials mentioning features or use of this software 16.\" 3. Neither the name of the University nor the names of its contributors
17.\" must display the following acknowledgement:
18.\" This product includes software developed by the University of
19.\" California, Berkeley and its contributors.
20.\" 4. Neither the name of the University nor the names of its contributors
21.\" may be used to endorse or promote products derived from this software 17.\" may be used to endorse or promote products derived from this software
22.\" without specific prior written permission. 18.\" without specific prior written permission.
23.\" 19.\"
@@ -33,50 +29,37 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
35.\" 31.\"
36.\" from: @(#)free.3 5.2 (Berkeley) 6/29/91 32.\" $OpenBSD: imaxabs.3,v 1.5 2011/07/07 13:30:28 jmc Exp $
37.\" $Id: free.3,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $
38.\" 33.\"
39.Dd June 29, 1991 34.Dd $Mdocdate: July 7 2011 $
40.Dt FREE 3 35.Dt IMAXABS 3
41.Os 36.Os
42.Sh NAME 37.Sh NAME
43.Nm free 38.Nm imaxabs
44.Nd free up memory allocated with malloc, calloc or realloc 39.Nd integer absolute value function
45.Sh SYNOPSIS 40.Sh SYNOPSIS
46.Fd #include <stdlib.h> 41.Fd #include <inttypes.h>
47.Ft void 42.Ft intmax_t
48.Fn free "void *ptr" 43.Fn imaxabs "intmax_t j"
49.Sh DESCRIPTION 44.Sh DESCRIPTION
50The 45The
51.Fn free 46.Fn imaxabs
52function causes the space pointed to by 47function computes the absolute value of the intmax_t variable
53.Fa ptr 48.Fa j .
54to be deallocated, that is, made available
55for further allocation.
56If
57.Fa ptr
58is a null pointer, no action occurs.
59Otherwise, if the argument does not match a pointer earlier
60returned by the
61.Xr calloc ,
62.Xr malloc ,
63or
64.Xr realloc
65function, or if the space has been deallocated by a call to
66.Fn free
67or
68.Xr realloc ,
69general havoc may occur.
70.Sh RETURN VALUES 49.Sh RETURN VALUES
71The 50The
72.Fn free 51.Fn imaxabs
73function returns no value. 52function returns the absolute value.
74.Sh SEE ALSO 53.Sh SEE ALSO
75.Xr calloc 3 , 54.Xr abs 3 ,
76.Xr malloc 3 , 55.Xr cabs 3 ,
77.Xr realloc 3 56.Xr floor 3 ,
57.Xr hypot 3 ,
58.Xr labs 3
78.Sh STANDARDS 59.Sh STANDARDS
79The 60The
80.Fn free 61.Fn imaxabs
81function conforms to 62function conforms to
82.St -ansiC . 63.St -ansiC-99 .
64.Sh BUGS
65The 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..2448f3f054
--- /dev/null
+++ b/src/lib/libc/stdlib/imaxdiv.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.\" 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.4 2011/07/07 13:30:28 jmc Exp $
33.\"
34.Dd $Mdocdate: July 7 2011 $
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 qdiv 3
62.Sh STANDARDS
63The
64.Fn imaxdiv
65function conforms to
66.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..dbda059c43
--- /dev/null
+++ b/src/lib/libc/stdlib/insque.3
@@ -0,0 +1,106 @@
1.\" $OpenBSD: insque.3,v 1.8 2011/01/14 07:33:47 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: January 14 2011 $
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 superseded 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
index 205781e0ee..cb8c592750 100644
--- a/src/lib/libc/stdlib/jrand48.c
+++ b/src/lib/libc/stdlib/jrand48.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: jrand48.c,v 1.3 2005/08/08 08:05:36 espie Exp $ */
1/* 2/*
2 * Copyright (c) 1993 Martin Birgmeier 3 * Copyright (c) 1993 Martin Birgmeier
3 * All rights reserved. 4 * All rights reserved.
diff --git a/src/lib/libc/stdlib/l64a.c b/src/lib/libc/stdlib/l64a.c
index 3069b31bf6..4f33df37b2 100644
--- a/src/lib/libc/stdlib/l64a.c
+++ b/src/lib/libc/stdlib/l64a.c
@@ -1,25 +1,24 @@
1/* $OpenBSD: l64a.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
1/* 2/*
2 * Written by J.T. Conklin <jtc@netbsd.org>. 3 * Written by J.T. Conklin <jtc@netbsd.org>.
3 * Public domain. 4 * Public domain.
4 */ 5 */
5 6
6#if defined(LIBC_SCCS) && !defined(lint) 7#include <errno.h>
7static char *rcsid = "$NetBSD: l64a.c,v 1.4 1995/05/11 23:04:52 jtc Exp $";
8#endif
9
10#include <stdlib.h> 8#include <stdlib.h>
11 9
12char * 10char *
13l64a (value) 11l64a(long value)
14 long value;
15{ 12{
16 static char buf[8]; 13 static char buf[8];
17 char *s = buf; 14 char *s = buf;
18 int digit; 15 int digit;
19 int i; 16 int i;
20 17
21 if (!value) 18 if (value < 0) {
22 return NULL; 19 errno = EINVAL;
20 return(NULL);
21 }
23 22
24 for (i = 0; value != 0 && i < 6; i++) { 23 for (i = 0; value != 0 && i < 6; i++) {
25 digit = value & 0x3f; 24 digit = value & 0x3f;
@@ -39,5 +38,5 @@ l64a (value)
39 38
40 *s = '\0'; 39 *s = '\0';
41 40
42 return buf; 41 return(buf);
43} 42}
diff --git a/src/lib/libc/stdlib/labs.3 b/src/lib/libc/stdlib/labs.3
index 28e4d2053c..9658c3ad51 100644
--- a/src/lib/libc/stdlib/labs.3
+++ b/src/lib/libc/stdlib/labs.3
@@ -13,11 +13,7 @@
13.\" 2. Redistributions in binary form must reproduce the above copyright 13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the 14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution. 15.\" documentation and/or other materials provided with the distribution.
16.\" 3. All advertising materials mentioning features or use of this software 16.\" 3. Neither the name of the University nor the names of its contributors
17.\" must display the following acknowledgement:
18.\" This product includes software developed by the University of
19.\" California, Berkeley and its contributors.
20.\" 4. Neither the name of the University nor the names of its contributors
21.\" may be used to endorse or promote products derived from this software 17.\" may be used to endorse or promote products derived from this software
22.\" without specific prior written permission. 18.\" without specific prior written permission.
23.\" 19.\"
@@ -33,35 +29,40 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
35.\" 31.\"
36.\" from: @(#)labs.3 5.3 (Berkeley) 6/29/91 32.\" $OpenBSD: labs.3,v 1.10 2011/07/07 13:30:28 jmc Exp $
37.\" $Id: labs.3,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $
38.\" 33.\"
39.Dd June 29, 1991 34.Dd $Mdocdate: July 7 2011 $
40.Dt LABS 3 35.Dt LABS 3
41.Os 36.Os
42.Sh NAME 37.Sh NAME
43.Nm labs 38.Nm labs, llabs
44.Nd return the absolute value of a long integer 39.Nd return the absolute value of a long integer
45.Sh SYNOPSIS 40.Sh SYNOPSIS
46.Fd #include <stdlib.h> 41.Fd #include <stdlib.h>
47.Ft long 42.Ft long
48.Fn labs "long j" 43.Fn labs "long i"
44.Ft long long
45.Fn llabs "long long j"
49.Sh DESCRIPTION 46.Sh DESCRIPTION
50The 47The
51.Fn labs 48.Fn labs
52function 49function returns the absolute value of the long integer
53returns the absolute value of the long integer 50.Fa i .
54.Ar j . 51The
52.Fn llabs
53function returns the absolute value of the long long integer
54.Fa j .
55.Sh SEE ALSO 55.Sh SEE ALSO
56.Xr abs 3 , 56.Xr abs 3 ,
57.Xr floor 3 ,
58.Xr cabs 3 , 57.Xr cabs 3 ,
59.Xr math 3 58.Xr floor 3 ,
59.Xr imaxabs 3
60.Sh STANDARDS 60.Sh STANDARDS
61The 61The
62.Fn labs 62.Fn labs
63function 63and
64conforms to 64.Fn llabs
65.St -ansiC . 65functions conform to
66.St -ansiC-99 .
66.Sh BUGS 67.Sh BUGS
67The absolute value of the most negative integer remains negative. 68The absolute value of the most negative integer remains negative.
diff --git a/src/lib/libc/stdlib/labs.c b/src/lib/libc/stdlib/labs.c
index ccf1415792..ca60b9aba2 100644
--- a/src/lib/libc/stdlib/labs.c
+++ b/src/lib/libc/stdlib/labs.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: labs.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
1/*- 2/*-
2 * Copyright (c) 1990 The Regents of the University of California. 3 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved. 4 * All rights reserved.
@@ -10,11 +11,7 @@
10 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. 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 15 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission. 16 * without specific prior written permission.
20 * 17 *
@@ -31,16 +28,10 @@
31 * SUCH DAMAGE. 28 * SUCH DAMAGE.
32 */ 29 */
33 30
34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)labs.c 5.2 (Berkeley) 5/17/90";*/
36static char *rcsid = "$Id: labs.c,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */
38
39#include <stdlib.h> 31#include <stdlib.h>
40 32
41long 33long
42labs(j) 34labs(long j)
43 long j;
44{ 35{
45 return(j < 0 ? -j : j); 36 return(j < 0 ? -j : j);
46} 37}
diff --git a/src/lib/libc/stdlib/lcong48.c b/src/lib/libc/stdlib/lcong48.c
index 965d46b17a..2cf5c271ba 100644
--- a/src/lib/libc/stdlib/lcong48.c
+++ b/src/lib/libc/stdlib/lcong48.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: lcong48.c,v 1.3 2005/08/08 08:05:36 espie Exp $ */
1/* 2/*
2 * Copyright (c) 1993 Martin Birgmeier 3 * Copyright (c) 1993 Martin Birgmeier
3 * All rights reserved. 4 * All rights reserved.
diff --git a/src/lib/libc/stdlib/ldiv.3 b/src/lib/libc/stdlib/ldiv.3
index a7b5ccf878..d300187887 100644
--- a/src/lib/libc/stdlib/ldiv.3
+++ b/src/lib/libc/stdlib/ldiv.3
@@ -13,11 +13,7 @@
13.\" 2. Redistributions in binary form must reproduce the above copyright 13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the 14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution. 15.\" documentation and/or other materials provided with the distribution.
16.\" 3. All advertising materials mentioning features or use of this software 16.\" 3. Neither the name of the University nor the names of its contributors
17.\" must display the following acknowledgement:
18.\" This product includes software developed by the University of
19.\" California, Berkeley and its contributors.
20.\" 4. Neither the name of the University nor the names of its contributors
21.\" may be used to endorse or promote products derived from this software 17.\" may be used to endorse or promote products derived from this software
22.\" without specific prior written permission. 18.\" without specific prior written permission.
23.\" 19.\"
@@ -33,10 +29,9 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
35.\" 31.\"
36.\" from: @(#)ldiv.3 5.3 (Berkeley) 6/29/91 32.\" $OpenBSD: ldiv.3,v 1.10 2011/07/07 13:30:28 jmc Exp $
37.\" $Id: ldiv.3,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $
38.\" 33.\"
39.Dd June 29, 1991 34.Dd $Mdocdate: July 7 2011 $
40.Dt LDIV 3 35.Dt LDIV 3
41.Os 36.Os
42.Sh NAME 37.Sh NAME
@@ -49,24 +44,23 @@
49.Sh DESCRIPTION 44.Sh DESCRIPTION
50The 45The
51.Fn ldiv 46.Fn ldiv
52function 47function computes the value
53computes the value 48.Fa num Ns / Ns Fa denom
54.Ar num/denom
55and returns the quotient and remainder in a structure named 49and returns the quotient and remainder in a structure named
56.Ar ldiv_t 50.Li ldiv_t
57that contains two 51that contains two
58.Em long integer 52.Li long integer
59members named 53members named
60.Ar quot 54.Fa quot
61and 55and
62.Ar rem . 56.Fa rem .
63.Sh SEE ALSO 57.Sh SEE ALSO
64.Xr div 3 , 58.Xr div 3 ,
65.Xr qdiv 3 , 59.Xr imaxdiv 3 ,
66.Xr math 3 60.Xr lldiv 3 ,
61.Xr qdiv 3
67.Sh STANDARDS 62.Sh STANDARDS
68The 63The
69.Fn ldiv 64.Fn ldiv
70function 65function conforms to
71conforms to
72.St -ansiC . 66.St -ansiC .
diff --git a/src/lib/libc/stdlib/ldiv.c b/src/lib/libc/stdlib/ldiv.c
index f7074507e5..775065f525 100644
--- a/src/lib/libc/stdlib/ldiv.c
+++ b/src/lib/libc/stdlib/ldiv.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: ldiv.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
1/* 2/*
2 * Copyright (c) 1990 Regents of the University of California. 3 * Copyright (c) 1990 Regents of the University of California.
3 * All rights reserved. 4 * All rights reserved.
@@ -13,11 +14,7 @@
13 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software 17 * 3. Neither the name of the University nor the names of its contributors
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software 18 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission. 19 * without specific prior written permission.
23 * 20 *
@@ -34,16 +31,10 @@
34 * SUCH DAMAGE. 31 * SUCH DAMAGE.
35 */ 32 */
36 33
37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char *sccsid = "from: @(#)ldiv.c 5.2 (Berkeley) 4/16/91";*/
39static char *rcsid = "$Id: ldiv.c,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */
41
42#include <stdlib.h> /* ldiv_t */ 34#include <stdlib.h> /* ldiv_t */
43 35
44ldiv_t 36ldiv_t
45ldiv(num, denom) 37ldiv(long num, long denom)
46 long num, denom;
47{ 38{
48 ldiv_t r; 39 ldiv_t r;
49 40
diff --git a/src/lib/libc/stdlib/calloc.c b/src/lib/libc/stdlib/llabs.c
index 3353fab052..fc2cd8261c 100644
--- a/src/lib/libc/stdlib/calloc.c
+++ b/src/lib/libc/stdlib/llabs.c
@@ -1,3 +1,5 @@
1/* $OpenBSD: llabs.c,v 1.3 2007/01/08 19:39:25 deraadt Exp $ */
2
1/*- 3/*-
2 * Copyright (c) 1990 The Regents of the University of California. 4 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved. 5 * All rights reserved.
@@ -10,11 +12,7 @@
10 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software 15 * 3. Neither the name of the University nor the names of its contributors
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. 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 16 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission. 17 * without specific prior written permission.
20 * 18 *
@@ -31,23 +29,10 @@
31 * SUCH DAMAGE. 29 * SUCH DAMAGE.
32 */ 30 */
33 31
34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)calloc.c 5.6 (Berkeley) 2/23/91";*/
36static char *rcsid = "$Id: calloc.c,v 1.1.1.1 1995/10/18 08:42:17 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */
38
39#include <stdlib.h> 32#include <stdlib.h>
40#include <string.h>
41 33
42void * 34long long
43calloc(num, size) 35llabs(long long j)
44 size_t num;
45 register size_t size;
46{ 36{
47 register void *p; 37 return (j < 0 ? -j : j);
48
49 size *= num;
50 if (p = malloc(size))
51 memset(p, '\0', size);
52 return(p);
53} 38}
diff --git a/src/lib/libc/stdlib/memory.3 b/src/lib/libc/stdlib/lldiv.3
index 735252c837..4c97d7c9b7 100644
--- a/src/lib/libc/stdlib/memory.3
+++ b/src/lib/libc/stdlib/lldiv.3
@@ -1,6 +1,10 @@
1.\" Copyright (c) 1991 Regents of the University of California. 1.\" Copyright (c) 1990, 1991 The Regents of the University of California.
2.\" All rights reserved. 2.\" All rights reserved.
3.\" 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.\"
4.\" Redistribution and use in source and binary forms, with or without 8.\" Redistribution and use in source and binary forms, with or without
5.\" modification, are permitted provided that the following conditions 9.\" modification, are permitted provided that the following conditions
6.\" are met: 10.\" are met:
@@ -9,11 +13,7 @@
9.\" 2. Redistributions in binary form must reproduce the above copyright 13.\" 2. Redistributions in binary form must reproduce the above copyright
10.\" notice, this list of conditions and the following disclaimer in the 14.\" notice, this list of conditions and the following disclaimer in the
11.\" documentation and/or other materials provided with the distribution. 15.\" documentation and/or other materials provided with the distribution.
12.\" 3. All advertising materials mentioning features or use of this software 16.\" 3. Neither the name of the University nor the names of its contributors
13.\" must display the following acknowledgement:
14.\" This product includes software developed by the University of
15.\" California, Berkeley and its contributors.
16.\" 4. 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 17.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission. 18.\" without specific prior written permission.
19.\" 19.\"
@@ -29,43 +29,38 @@
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
31.\" 31.\"
32.\" from: @(#)memory.3 5.1 (Berkeley) 5/2/91 32.\" $OpenBSD: lldiv.3,v 1.3 2011/07/07 13:30:28 jmc Exp $
33.\" $Id: memory.3,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $
34.\" 33.\"
35.Dd May 2, 1991 34.Dd $Mdocdate: July 7 2011 $
36.Dt MEMORY 3 35.Dt LLDIV 3
37.Os BSD 4 36.Os
38.Sh NAME 37.Sh NAME
39.Nm malloc , 38.Nm lldiv
40.Nm free , 39.Nd return quotient and remainder from division
41.Nm realloc ,
42.Nm calloc ,
43.Nm alloca
44.Nd general memory allocation operations
45.Sh SYNOPSIS 40.Sh SYNOPSIS
46.Fd #include <stdlib.h> 41.Fd #include <stdlib.h>
47.Ft void * 42.Ft lldiv_t
48.Fn malloc "size_t size" 43.Fn lldiv "long long num" "long long denom"
49.Ft void
50.Fn free "void *ptr"
51.Ft void *
52.Fn realloc "void *ptr" "size_t size"
53.Ft void *
54.Fn calloc "size_t nelem" "size_t elsize"
55.Ft void *
56.Fn alloca "size_t size"
57.Sh DESCRIPTION 44.Sh DESCRIPTION
58These functions allocate and free memory for the calling process. 45The
59They are described in the 46.Fn lldiv
60individual manual pages. 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 .
61.Sh SEE ALSO 57.Sh SEE ALSO
62.Xr calloc 3 , 58.Xr div 3 ,
63.Xr free 3 , 59.Xr imaxdiv 3 ,
64.Xr malloc 3 , 60.Xr ldiv 3 ,
65.Xr realloc 3 , 61.Xr qdiv 3
66.Xr alloca 3 ,
67.Sh STANDARDS 62.Sh STANDARDS
68These functions, with the exception of 63The
69.Fn alloca 64.Fn lldiv
70conform to 65function conforms to
71.St -ansiC . 66.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
index 8e7f26237f..21beb858ca 100644
--- a/src/lib/libc/stdlib/lrand48.c
+++ b/src/lib/libc/stdlib/lrand48.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: lrand48.c,v 1.3 2005/08/08 08:05:36 espie Exp $ */
1/* 2/*
2 * Copyright (c) 1993 Martin Birgmeier 3 * Copyright (c) 1993 Martin Birgmeier
3 * All rights reserved. 4 * All rights reserved.
diff --git a/src/lib/libc/stdlib/lsearch.3 b/src/lib/libc/stdlib/lsearch.3
new file mode 100644
index 0000000000..86638ae621
--- /dev/null
+++ b/src/lib/libc/stdlib/lsearch.3
@@ -0,0 +1,108 @@
1.\" $OpenBSD: lsearch.3,v 1.9 2009/02/10 21:47:56 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: February 10 2009 $
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)(const void *, const void *)"
44.Ft char *
45.Fn lfind "const void *key" "const void *base" "size_t *nelp" \
46 "size_t width" "int (*compar)(const void *, const 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..a01d80e008
--- /dev/null
+++ b/src/lib/libc/stdlib/lsearch.c
@@ -0,0 +1,84 @@
1/* $OpenBSD: lsearch.c,v 1.4 2009/10/27 23:59:59 deraadt 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#include <sys/types.h>
36#include <string.h>
37#include <search.h>
38
39typedef int (*cmp_fn_t)(const void *, const void *);
40static void *linear_base(const void *, const void *, size_t *, size_t,
41 cmp_fn_t, int);
42
43void *
44lsearch(const void *key, const void *base, size_t *nelp, size_t width,
45 cmp_fn_t compar)
46{
47
48 return(linear_base(key, base, nelp, width, compar, 1));
49}
50
51void *
52lfind(const void *key, const void *base, size_t *nelp, size_t width,
53 cmp_fn_t compar)
54{
55 return(linear_base(key, base, nelp, width, compar, 0));
56}
57
58static void *
59linear_base(const void *key, const void *base, size_t *nelp, size_t width,
60 cmp_fn_t compar, int add_flag)
61{
62 const char *element, *end;
63
64 end = (const char *)base + *nelp * width;
65 for (element = base; element < end; element += width)
66 if (!compar(key, element)) /* key found */
67 return((void *)element);
68
69 if (!add_flag) /* key not found */
70 return(NULL);
71
72 /*
73 * The UNIX System User's Manual, 1986 edition claims that
74 * a NULL pointer is returned by lsearch with errno set
75 * appropriately, if there is not enough room in the table
76 * to add a new item. This can't be done as none of these
77 * routines have any method of determining the size of the
78 * table. This comment isn't in the 1986-87 System V
79 * manual.
80 */
81 ++*nelp;
82 memcpy((void *)end, key, width);
83 return((void *)end);
84}
diff --git a/src/lib/libc/stdlib/malloc.3 b/src/lib/libc/stdlib/malloc.3
index 3bbf2bf65e..6a012fd23d 100644
--- a/src/lib/libc/stdlib/malloc.3
+++ b/src/lib/libc/stdlib/malloc.3
@@ -1,5 +1,6 @@
1.\" Copyright (c) 1980, 1991 Regents of the University of California. 1.\"
2.\" All rights reserved. 2.\" Copyright (c) 1980, 1991, 1993
3.\" The Regents of the University of California. All rights reserved.
3.\" 4.\"
4.\" This code is derived from software contributed to Berkeley by 5.\" This code is derived from software contributed to Berkeley by
5.\" the American National Standards Committee X3, on Information 6.\" the American National Standards Committee X3, on Information
@@ -13,11 +14,7 @@
13.\" 2. Redistributions in binary form must reproduce the above copyright 14.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the 15.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution. 16.\" documentation and/or other materials provided with the distribution.
16.\" 3. All advertising materials mentioning features or use of this software 17.\" 3. Neither the name of the University nor the names of its contributors
17.\" must display the following acknowledgement:
18.\" This product includes software developed by the University of
19.\" California, Berkeley and its contributors.
20.\" 4. Neither the name of the University nor the names of its contributors
21.\" may be used to endorse or promote products derived from this software 18.\" may be used to endorse or promote products derived from this software
22.\" without specific prior written permission. 19.\" without specific prior written permission.
23.\" 20.\"
@@ -33,19 +30,32 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 31.\" SUCH DAMAGE.
35.\" 32.\"
36.\" from: @(#)malloc.3 6.7 (Berkeley) 6/29/91 33.\" $OpenBSD: malloc.3,v 1.70 2011/07/22 07:00:44 otto Exp $
37.\" $Id: malloc.3,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $
38.\" 34.\"
39.Dd June 29, 1991 35.Dd $Mdocdate: July 22 2011 $
40.Dt MALLOC 3 36.Dt MALLOC 3
41.Os BSD 4 37.Os
42.Sh NAME 38.Sh NAME
43.Nm malloc 39.Nm malloc ,
44.Nd general memory allocation function 40.Nm calloc ,
41.Nm realloc ,
42.Nm free ,
43.Nm cfree
44.Nd memory allocation and deallocation
45.Sh SYNOPSIS 45.Sh SYNOPSIS
46.Fd #include <stdlib.h> 46.Fd #include <stdlib.h>
47.Ft void * 47.Ft void *
48.Fn malloc "size_t size" 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 ;
49.Sh DESCRIPTION 59.Sh DESCRIPTION
50The 60The
51.Fn malloc 61.Fn malloc
@@ -59,33 +69,390 @@ space from the appropriate list.
59.Pp 69.Pp
60The allocated space is 70The allocated space is
61suitably aligned (after possible pointer 71suitably aligned (after possible pointer
62coercion) for storage of any type of object. If the space is of 72coercion) for storage of any type of object.
73If the space is of
63.Em pagesize 74.Em pagesize
64or larger, the memory returned will be page-aligned. 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.Sh MALLOC_OPTIONS
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 internal
219inconsistencies or incorrect usage.
220This is the default and a very handy debugging aid,
221since the core file represents the time of failure,
222rather than when the bogus pointer was used.
223.It Cm D
224.Dq Dump .
225.Fn malloc
226will dump statistics to the file
227.Pa ./malloc.out ,
228if it already exists,
229at exit.
230This option requires the library to have been compiled with -DMALLOC_STATS in
231order to have any effect.
232.It Cm F
233.Dq Freeguard .
234Enable use after free protection.
235Unused pages on the freelist are read and write protected to
236cause a segmentation fault upon access.
237This will also switch off the delayed freeing of chunks,
238reducing random behaviour but detecting double
239.Fn free
240calls as early as possible.
241.It Cm G
242.Dq Guard .
243Enable guard pages.
244Each page size or larger allocation is followed by a guard page that will
245cause a segmentation fault upon any access.
246.It Cm H
247.Dq Hint .
248Pass a hint to the kernel about pages we don't use.
249If the machine is paging a lot this may help a bit.
250.It Cm J
251.Dq Junk .
252Fill some junk into the area allocated.
253Currently junk is bytes of 0xd0 when allocating; this is pronounced
254.Dq Duh .
255\&:-)
256Freed chunks are filled with 0xdf.
257.It Cm P
258.Dq Move allocations within a page.
259Allocations larger than half a page but smaller than a page
260are aligned to the end of a page to catch buffer overruns in more
261cases.
262This is the default.
263.It Cm R
264.Dq realloc .
265Always reallocate when
266.Fn realloc
267is called, even if the initial allocation was big enough.
268This can substantially aid in compacting memory.
269.\".Pp
270.\".It Cm U
271.\".Dq utrace .
272.\"Generate entries for
273.\".Xr ktrace 1
274.\"for all operations.
275.\"Consult the source for this one.
276.It Cm S
277Enable all options suitable for security auditing.
278.It Cm X
279.Dq xmalloc .
280Rather than return failure,
281.Xr abort 3
282the program with a diagnostic message on stderr.
283It is the intention that this option be set at compile time by
284including in the source:
285.Bd -literal -offset indent
286extern char *malloc_options;
287malloc_options = "X";
288.Ed
289.Pp
290Note that this will cause code that is supposed to handle
291out-of-memory conditions gracefully to abort instead.
292.It Cm Z
293.Dq Zero .
294Fill some junk into the area allocated (see
295.Cm J ) ,
296except for the exact length the user asked for, which is zeroed.
297.It Cm <
298.Dq Half the cache size .
299Decrease the size of the free page cache by a factor of two.
300.It Cm >
301.Dq Double the cache size .
302Increase the size of the free page cache by a factor of two.
303.El
304.Pp
305So to set a systemwide reduction of the cache to a quarter of the
306default size and use guard pages:
307.Dl # ln -s 'G\*(Lt\*(Lt' /etc/malloc.conf
308.Pp
309The flags are mostly for testing and debugging.
310If a program changes behavior if any of these options (except
311.Cm X )
312are used,
313it is buggy.
314.Pp
315The default number of free pages cached is 64.
65.Sh RETURN VALUES 316.Sh RETURN VALUES
66The 317The
67.Fn malloc 318.Fn malloc
68function returns 319and
69a pointer to the allocated space if successful; otherwise 320.Fn calloc
70a null pointer is returned. 321functions return a pointer to the allocated space if successful; otherwise,
322a null pointer is returned and
323.Va errno
324is set to
325.Er ENOMEM .
326.Pp
327The
328.Fn free
329and
330.Fn cfree
331functions return no value.
332.Pp
333The
334.Fn realloc
335function returns a pointer to the (possibly moved) allocated space
336if successful; otherwise, a null pointer is returned and
337.Va errno
338is set to
339.Er ENOMEM .
340.Sh ENVIRONMENT
341.Bl -tag -width Ev
342.It Ev MALLOC_OPTIONS
343See above.
344.El
345.Sh FILES
346.Bl -tag -width "/etc/malloc.conf"
347.It Pa /etc/malloc.conf
348symbolic link to filename containing option flags
349.El
350.Sh DIAGNOSTICS
351If
352.Fn malloc ,
353.Fn calloc ,
354.Fn realloc ,
355or
356.Fn free
357detect an error condition,
358a message will be printed to file descriptor
3592 (not using stdio).
360Errors will result in the process being aborted,
361unless the
362.Cm a
363option has been specified.
364.Pp
365Here is a brief description of the error messages and what they mean:
366.Bl -tag -width Ds
367.It Dq out of memory
368If the
369.Cm X
370option is specified it is an error for
371.Fn malloc ,
372.Fn calloc ,
373or
374.Fn realloc
375to return
376.Dv NULL .
377.It Dq malloc init mmap failed
378This is a rather weird condition that is most likely to indicate a
379seriously overloaded system or a ulimit restriction.
380.It Dq bogus pointer (double free?)
381An attempt to
382.Fn free
383or
384.Fn realloc
385an unallocated pointer was made.
386.It Dq chunk is already free
387There was an attempt to free a chunk that had already been freed.
388.It Dq modified chunk-pointer
389The pointer passed to
390.Fn free
391or
392.Fn realloc
393has been modified.
394.It Dq recursive call
395An attempt was made to call recursively into these functions, i.e., from a
396signal handler.
397This behavior is not supported.
398In particular, signal handlers should
399.Em not
400use any of the
401.Fn malloc
402functions nor utilize any other functions which may call
403.Fn malloc
404(e.g.,
405.Xr stdio 3
406routines).
407.It Dq unknown char in MALLOC_OPTIONS
408We found something we didn't understand.
409.It Dq malloc cache overflow/underflow
410The internal malloc page cache has been corrupted.
411.It Dq malloc free slot lost
412The internal malloc page cache has been corrupted.
413.It Dq guard size
414An inconsistent guard size was detected.
415.It any other error
416.Fn malloc
417detected an internal error;
418consult sources and/or wizards.
419.El
71.Sh SEE ALSO 420.Sh SEE ALSO
72.Xr brk 2 , 421.Xr brk 2 ,
73.Xr getpagesize 2 , 422.Xr mmap 2 ,
74.Xr free 3 , 423.Xr munmap 2 ,
75.Xr calloc 3 ,
76.Xr alloca 3 , 424.Xr alloca 3 ,
77.Xr realloc 3 , 425.Xr getpagesize 3 ,
78.Xr memory 3 426.Xr posix_memalign 3
79.Sh STANDARDS 427.Sh STANDARDS
80The 428The
81.Fn malloc 429.Fn malloc
82function conforms to 430function conforms to
83.St -ansiC . 431.St -ansiC .
84.Sh BUGS 432.Sh HISTORY
85The current implementation of 433The
86.Xr malloc 434.Nm
87does not always fail gracefully when system 435family of functions first appeared in
88memory limits are approached. 436.At v7 .
89It may fail to allocate memory when larger free blocks could be broken 437A new implementation by Chris Kingsley was introduced in
90up, or when limits are exceeded because the size is rounded up. 438.Bx 4.2 ,
91It is optimized for sizes that are powers of two. 439followed by a complete rewrite by Poul-Henning Kamp which appeared in
440.Fx 2.2
441and was included in
442.Ox 2.0 .
443These implementations were all
444.Xr sbrk 2
445based.
446In
447.Ox 3.8 ,
448Thierry Deval rewrote
449.Nm
450to use the
451.Xr mmap 2
452system call,
453making the page addresses returned by
454.Nm
455random.
456A rewrite by Otto Moerbeek introducing a new central data structure and more
457randomization appeared in
458.Ox 4.4 .
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c
index 3c57fad024..5fc75c2c75 100644
--- a/src/lib/libc/stdlib/malloc.c
+++ b/src/lib/libc/stdlib/malloc.c
@@ -1,421 +1,1693 @@
1/* $OpenBSD: malloc.c,v 1.140 2011/10/06 14:37:04 otto Exp $ */
1/* 2/*
2 * Copyright (c) 1983 Regents of the University of California. 3 * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
3 * All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Permission to use, copy, modify, and distribute this software for any
6 * modification, are permitted provided that the following conditions 6 * purpose with or without fee is hereby granted, provided that the above
7 * are met: 7 * copyright notice and this permission notice appear in all copies.
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. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. 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 * 8 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
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 */ 16 */
33 17
34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)malloc.c 5.11 (Berkeley) 2/23/91";*/
36static char *rcsid = "$Id: malloc.c,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */
38
39/* 18/*
40 * malloc.c (Caltech) 2/21/82 19 * Parts of this code, mainly the sub page sized chunk management code is
41 * Chris Kingsley, kingsley@cit-20. 20 * derived from the malloc implementation with the following license:
42 * 21 */
43 * This is a very fast storage allocator. It allocates blocks of a small 22/*
44 * number of different sizes, and keeps free lists of each size. Blocks that 23 * ----------------------------------------------------------------------------
45 * don't exactly fit are passed up to the next larger size. In this 24 * "THE BEER-WARE LICENSE" (Revision 42):
46 * implementation, the available sizes are 2^n-4 (or 2^n-10) bytes long. 25 * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you
47 * This is designed for use in a virtual memory environment. 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 * ----------------------------------------------------------------------------
48 */ 29 */
49 30
31/* #define MALLOC_STATS */
32
50#include <sys/types.h> 33#include <sys/types.h>
34#include <sys/param.h>
35#include <sys/queue.h>
36#include <sys/mman.h>
37#include <sys/uio.h>
38#include <errno.h>
39#include <stdint.h>
51#include <stdlib.h> 40#include <stdlib.h>
52#include <string.h> 41#include <string.h>
42#include <stdio.h>
53#include <unistd.h> 43#include <unistd.h>
54 44
55#define NULL 0 45#ifdef MALLOC_STATS
46#include <sys/tree.h>
47#include <fcntl.h>
48#endif
49
50#include "thread_private.h"
51
52#if defined(__sparc__) && !defined(__sparcv9__)
53#define MALLOC_PAGESHIFT (13U)
54#elif defined(__mips64__)
55#define MALLOC_PAGESHIFT (14U)
56#else
57#define MALLOC_PAGESHIFT (PGSHIFT)
58#endif
59
60#define MALLOC_MINSHIFT 4
61#define MALLOC_MAXSHIFT (MALLOC_PAGESHIFT - 1)
62#define MALLOC_PAGESIZE (1UL << MALLOC_PAGESHIFT)
63#define MALLOC_MINSIZE (1UL << MALLOC_MINSHIFT)
64#define MALLOC_PAGEMASK (MALLOC_PAGESIZE - 1)
65#define MASK_POINTER(p) ((void *)(((uintptr_t)(p)) & ~MALLOC_PAGEMASK))
56 66
57static void morecore(); 67#define MALLOC_MAXCHUNK (1 << MALLOC_MAXSHIFT)
58static int findbucket(); 68#define MALLOC_MAXCACHE 256
69#define MALLOC_DELAYED_CHUNKS 15 /* max of getrnibble() */
70#define MALLOC_INITIAL_REGIONS 512
71#define MALLOC_DEFAULT_CACHE 64
59 72
60/* 73/*
61 * The overhead on a block is at least 4 bytes. When free, this space 74 * When the P option is active, we move allocations between half a page
62 * contains a pointer to the next free block, and the bottom two bits must 75 * and a whole page towards the end, subject to alignment constraints.
63 * be zero. When in use, the first byte is set to MAGIC, and the second 76 * This is the extra headroom we allow. Set to zero to be the most
64 * byte is the size index. The remaining bytes are for alignment. 77 * strict.
65 * If range checking is enabled then a second word holds the size of the
66 * requested block, less 1, rounded up to a multiple of sizeof(RMAGIC).
67 * The order of elements is critical: ov_magic must overlay the low order
68 * bits of ov_next, and ov_magic can not be a valid ov_next bit pattern.
69 */ 78 */
70union overhead { 79#define MALLOC_LEEWAY 0
71 union overhead *ov_next; /* when free */ 80
72 struct { 81#define PAGEROUND(x) (((x) + (MALLOC_PAGEMASK)) & ~MALLOC_PAGEMASK)
73 u_char ovu_magic; /* magic number */ 82
74 u_char ovu_index; /* bucket # */ 83/*
75#ifdef RCHECK 84 * What to use for Junk. This is the byte value we use to fill with
76 u_short ovu_rmagic; /* range magic number */ 85 * when the 'J' option is enabled. Use SOME_JUNK right after alloc,
77 u_long ovu_size; /* actual block size */ 86 * and SOME_FREEJUNK right before free.
87 */
88#define SOME_JUNK 0xd0 /* as in "Duh" :-) */
89#define SOME_FREEJUNK 0xdf
90
91#define MMAP(sz) mmap(NULL, (size_t)(sz), PROT_READ | PROT_WRITE, \
92 MAP_ANON | MAP_PRIVATE, -1, (off_t) 0)
93
94#define MMAPA(a,sz) mmap((a), (size_t)(sz), PROT_READ | PROT_WRITE, \
95 MAP_ANON | MAP_PRIVATE, -1, (off_t) 0)
96
97struct region_info {
98 void *p; /* page; low bits used to mark chunks */
99 uintptr_t size; /* size for pages, or chunk_info pointer */
100#ifdef MALLOC_STATS
101 void *f; /* where allocated from */
78#endif 102#endif
79 } ovu;
80#define ov_magic ovu.ovu_magic
81#define ov_index ovu.ovu_index
82#define ov_rmagic ovu.ovu_rmagic
83#define ov_size ovu.ovu_size
84}; 103};
85 104
86#define MAGIC 0xef /* magic # on accounting info */ 105LIST_HEAD(chunk_head, chunk_info);
87#define RMAGIC 0x5555 /* magic # on range info */
88 106
89#ifdef RCHECK 107struct dir_info {
90#define RSLOP sizeof (u_short) 108 u_int32_t canary1;
109 struct region_info *r; /* region slots */
110 size_t regions_total; /* number of region slots */
111 size_t regions_free; /* number of free slots */
112 /* lists of free chunk info structs */
113 struct chunk_head chunk_info_list[MALLOC_MAXSHIFT + 1];
114 /* lists of chunks with free slots */
115 struct chunk_head chunk_dir[MALLOC_MAXSHIFT + 1];
116 size_t free_regions_size; /* free pages cached */
117 /* free pages cache */
118 struct region_info free_regions[MALLOC_MAXCACHE];
119 /* delayed free chunk slots */
120 void *delayed_chunks[MALLOC_DELAYED_CHUNKS + 1];
121 u_short chunk_start;
122#ifdef MALLOC_STATS
123 size_t inserts;
124 size_t insert_collisions;
125 size_t finds;
126 size_t find_collisions;
127 size_t deletes;
128 size_t delete_moves;
129 size_t cheap_realloc_tries;
130 size_t cheap_reallocs;
131#define STATS_INC(x) ((x)++)
132#define STATS_ZERO(x) ((x) = 0)
133#define STATS_SETF(x,y) ((x)->f = (y))
91#else 134#else
92#define RSLOP 0 135#define STATS_INC(x) /* nothing */
93#endif 136#define STATS_ZERO(x) /* nothing */
137#define STATS_SETF(x,y) /* nothing */
138#endif /* MALLOC_STATS */
139 u_int32_t canary2;
140};
141#define DIR_INFO_RSZ ((sizeof(struct dir_info) + MALLOC_PAGEMASK) & \
142 ~MALLOC_PAGEMASK)
94 143
95/* 144/*
96 * nextf[i] is the pointer to the next free block of size 2^(i+3). The 145 * This structure describes a page worth of chunks.
97 * smallest allocatable block is 8 bytes. The overhead information 146 *
98 * precedes the data area returned to the user. 147 * How many bits per u_short in the bitmap
99 */ 148 */
100#define NBUCKETS 30 149#define MALLOC_BITS (NBBY * sizeof(u_short))
101static union overhead *nextf[NBUCKETS]; 150struct chunk_info {
102extern char *sbrk(); 151 LIST_ENTRY(chunk_info) entries;
152 void *page; /* pointer to the page */
153 u_int32_t canary;
154 u_short size; /* size of this page's chunks */
155 u_short shift; /* how far to shift for this size */
156 u_short free; /* how many free chunks */
157 u_short total; /* how many chunk */
158 /* which chunks are free */
159 u_short bits[1];
160};
161
162struct malloc_readonly {
163 struct dir_info *g_pool; /* Main bookkeeping information */
164 int malloc_abort; /* abort() on error */
165 int malloc_freeprot; /* mprotect free pages PROT_NONE? */
166 int malloc_hint; /* call madvice on free pages? */
167 int malloc_junk; /* junk fill? */
168 int malloc_move; /* move allocations to end of page? */
169 int malloc_realloc; /* always realloc? */
170 int malloc_xmalloc; /* xmalloc behaviour? */
171 int malloc_zero; /* zero fill? */
172 size_t malloc_guard; /* use guard pages after allocations? */
173 u_int malloc_cache; /* free pages we cache */
174#ifdef MALLOC_STATS
175 int malloc_stats; /* dump statistics at end */
176#endif
177 u_int32_t malloc_canary; /* Matched against ones in g_pool */
178};
103 179
104static int pagesz; /* page size */ 180/* This object is mapped PROT_READ after initialisation to prevent tampering */
105static int pagebucket; /* page size bucket */ 181static union {
182 struct malloc_readonly mopts;
183 u_char _pad[MALLOC_PAGESIZE];
184} malloc_readonly __attribute__((aligned(MALLOC_PAGESIZE)));
185#define mopts malloc_readonly.mopts
186#define g_pool mopts.g_pool
106 187
107#ifdef MSTATS 188char *malloc_options; /* compile-time options */
108/* 189
109 * nmalloc[i] is the difference between the number of mallocs and frees 190static char *malloc_func; /* current function */
110 * for a given block size. 191static int malloc_active; /* status of malloc */
192
193static size_t malloc_guarded; /* bytes used for guards */
194static size_t malloc_used; /* bytes allocated */
195
196static size_t rnibblesused; /* random nibbles used */
197static u_char rbytes[512]; /* random bytes */
198static u_char getrnibble(void);
199
200extern char *__progname;
201
202#ifdef MALLOC_STATS
203void malloc_dump(int);
204static void malloc_exit(void);
205#define CALLER __builtin_return_address(0)
206#else
207#define CALLER NULL
208#endif
209
210/* low bits of r->p determine size: 0 means >= page size and p->size holding
211 * real size, otherwise r->size is a shift count, or 1 for malloc(0)
111 */ 212 */
112static u_int nmalloc[NBUCKETS]; 213#define REALSIZE(sz, r) \
113#include <stdio.h> 214 (sz) = (uintptr_t)(r)->p & MALLOC_PAGEMASK, \
215 (sz) = ((sz) == 0 ? (r)->size : ((sz) == 1 ? 0 : (1 << ((sz)-1))))
216
217static inline size_t
218hash(void *p)
219{
220 size_t sum;
221 union {
222 uintptr_t p;
223 unsigned short a[sizeof(void *) / sizeof(short)];
224 } u;
225 u.p = (uintptr_t)p >> MALLOC_PAGESHIFT;
226 sum = u.a[0];
227 sum = (sum << 7) - sum + u.a[1];
228#ifdef __LP64__
229 sum = (sum << 7) - sum + u.a[2];
230 sum = (sum << 7) - sum + u.a[3];
114#endif 231#endif
232 return sum;
233}
115 234
116#if defined(DEBUG) || defined(RCHECK) 235static void
117#define ASSERT(p) if (!(p)) botch("p") 236wrterror(char *msg, void *p)
118#include <stdio.h>
119static
120botch(s)
121 char *s;
122{ 237{
123 fprintf(stderr, "\r\nassertion botched: %s\r\n", s); 238 char *q = " error: ";
124 (void) fflush(stderr); /* just in case user buffered it */ 239 struct iovec iov[6];
125 abort(); 240 char buf[20];
241 int saved_errno = errno;
242
243 iov[0].iov_base = __progname;
244 iov[0].iov_len = strlen(__progname);
245 iov[1].iov_base = malloc_func;
246 iov[1].iov_len = strlen(malloc_func);
247 iov[2].iov_base = q;
248 iov[2].iov_len = strlen(q);
249 iov[3].iov_base = msg;
250 iov[3].iov_len = strlen(msg);
251 iov[4].iov_base = buf;
252 if (p == NULL)
253 iov[4].iov_len = 0;
254 else {
255 snprintf(buf, sizeof(buf), " %p", p);
256 iov[4].iov_len = strlen(buf);
257 }
258 iov[5].iov_base = "\n";
259 iov[5].iov_len = 1;
260 writev(STDERR_FILENO, iov, 6);
261
262#ifdef MALLOC_STATS
263 if (mopts.malloc_stats)
264 malloc_dump(STDERR_FILENO);
265#endif /* MALLOC_STATS */
266
267 errno = saved_errno;
268 if (mopts.malloc_abort)
269 abort();
126} 270}
127#else
128#define ASSERT(p)
129#endif
130 271
131void * 272static void
132malloc(nbytes) 273rbytes_init(void)
133 size_t nbytes; 274{
275 arc4random_buf(rbytes, sizeof(rbytes));
276 rnibblesused = 0;
277}
278
279static inline u_char
280getrnibble(void)
281{
282 u_char x;
283
284 if (rnibblesused >= 2 * sizeof(rbytes))
285 rbytes_init();
286 x = rbytes[rnibblesused++ / 2];
287 return (rnibblesused & 1 ? x & 0xf : x >> 4);
288}
289
290/*
291 * Cache maintenance. We keep at most malloc_cache pages cached.
292 * If the cache is becoming full, unmap pages in the cache for real,
293 * and then add the region to the cache
294 * Opposed to the regular region data structure, the sizes in the
295 * cache are in MALLOC_PAGESIZE units.
296 */
297static void
298unmap(struct dir_info *d, void *p, size_t sz)
134{ 299{
135 register union overhead *op; 300 size_t psz = sz >> MALLOC_PAGESHIFT;
136 register long bucket, n; 301 size_t rsz, tounmap;
137 register unsigned amt; 302 struct region_info *r;
303 u_int i, offset;
304
305 if (sz != PAGEROUND(sz)) {
306 wrterror("munmap round", NULL);
307 return;
308 }
309
310 if (psz > mopts.malloc_cache) {
311 if (munmap(p, sz))
312 wrterror("munmap", p);
313 malloc_used -= sz;
314 return;
315 }
316 tounmap = 0;
317 rsz = mopts.malloc_cache - d->free_regions_size;
318 if (psz > rsz)
319 tounmap = psz - rsz;
320 offset = getrnibble();
321 for (i = 0; tounmap > 0 && i < mopts.malloc_cache; i++) {
322 r = &d->free_regions[(i + offset) & (mopts.malloc_cache - 1)];
323 if (r->p != NULL) {
324 rsz = r->size << MALLOC_PAGESHIFT;
325 if (munmap(r->p, rsz))
326 wrterror("munmap", r->p);
327 r->p = NULL;
328 if (tounmap > r->size)
329 tounmap -= r->size;
330 else
331 tounmap = 0;
332 d->free_regions_size -= r->size;
333 r->size = 0;
334 malloc_used -= rsz;
335 }
336 }
337 if (tounmap > 0)
338 wrterror("malloc cache underflow", NULL);
339 for (i = 0; i < mopts.malloc_cache; i++) {
340 r = &d->free_regions[i];
341 if (r->p == NULL) {
342 if (mopts.malloc_hint)
343 madvise(p, sz, MADV_FREE);
344 if (mopts.malloc_freeprot)
345 mprotect(p, sz, PROT_NONE);
346 r->p = p;
347 r->size = psz;
348 d->free_regions_size += psz;
349 break;
350 }
351 }
352 if (i == mopts.malloc_cache)
353 wrterror("malloc free slot lost", NULL);
354 if (d->free_regions_size > mopts.malloc_cache)
355 wrterror("malloc cache overflow", NULL);
356}
357
358static void
359zapcacheregion(struct dir_info *d, void *p)
360{
361 u_int i;
362 struct region_info *r;
363 size_t rsz;
364
365 for (i = 0; i < mopts.malloc_cache; i++) {
366 r = &d->free_regions[i];
367 if (r->p == p) {
368 rsz = r->size << MALLOC_PAGESHIFT;
369 if (munmap(r->p, rsz))
370 wrterror("munmap", r->p);
371 r->p = NULL;
372 d->free_regions_size -= r->size;
373 r->size = 0;
374 malloc_used -= rsz;
375 }
376 }
377}
378
379static void *
380map(struct dir_info *d, size_t sz, int zero_fill)
381{
382 size_t psz = sz >> MALLOC_PAGESHIFT;
383 struct region_info *r, *big = NULL;
384 u_int i, offset;
385 void *p;
386
387 if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) ||
388 d->canary1 != ~d->canary2)
389 wrterror("internal struct corrupt", NULL);
390 if (sz != PAGEROUND(sz)) {
391 wrterror("map round", NULL);
392 return NULL;
393 }
394 if (psz > d->free_regions_size) {
395 p = MMAP(sz);
396 if (p != MAP_FAILED)
397 malloc_used += sz;
398 /* zero fill not needed */
399 return p;
400 }
401 offset = getrnibble();
402 for (i = 0; i < mopts.malloc_cache; i++) {
403 r = &d->free_regions[(i + offset) & (mopts.malloc_cache - 1)];
404 if (r->p != NULL) {
405 if (r->size == psz) {
406 p = r->p;
407 if (mopts.malloc_freeprot)
408 mprotect(p, sz, PROT_READ | PROT_WRITE);
409 if (mopts.malloc_hint)
410 madvise(p, sz, MADV_NORMAL);
411 r->p = NULL;
412 r->size = 0;
413 d->free_regions_size -= psz;
414 if (zero_fill)
415 memset(p, 0, sz);
416 else if (mopts.malloc_junk &&
417 mopts.malloc_freeprot)
418 memset(p, SOME_FREEJUNK, sz);
419 return p;
420 } else if (r->size > psz)
421 big = r;
422 }
423 }
424 if (big != NULL) {
425 r = big;
426 p = (char *)r->p + ((r->size - psz) << MALLOC_PAGESHIFT);
427 if (mopts.malloc_freeprot)
428 mprotect(p, sz, PROT_READ | PROT_WRITE);
429 if (mopts.malloc_hint)
430 madvise(p, sz, MADV_NORMAL);
431 r->size -= psz;
432 d->free_regions_size -= psz;
433 if (zero_fill)
434 memset(p, 0, sz);
435 else if (mopts.malloc_junk && mopts.malloc_freeprot)
436 memset(p, SOME_FREEJUNK, sz);
437 return p;
438 }
439 p = MMAP(sz);
440 if (p != MAP_FAILED)
441 malloc_used += sz;
442 if (d->free_regions_size > mopts.malloc_cache)
443 wrterror("malloc cache", NULL);
444 /* zero fill not needed */
445 return p;
446}
447
448/*
449 * Initialize a dir_info, which should have been cleared by caller
450 */
451static int
452omalloc_init(struct dir_info **dp)
453{
454 char *p, b[64];
455 int i, j;
456 size_t d_avail, regioninfo_size;
457 struct dir_info *d;
458
459 rbytes_init();
138 460
139 /* 461 /*
140 * First time malloc is called, setup page size and 462 * Default options
141 * align break pointer so all data will be page aligned.
142 */ 463 */
143 if (pagesz == 0) { 464 mopts.malloc_abort = 1;
144 pagesz = n = getpagesize(); 465 mopts.malloc_move = 1;
145 op = (union overhead *)sbrk(0); 466 mopts.malloc_cache = MALLOC_DEFAULT_CACHE;
146 n = n - sizeof (*op) - ((long)op & (n - 1)); 467
147 if (n < 0) 468 for (i = 0; i < 3; i++) {
148 n += pagesz; 469 switch (i) {
149 if (n) { 470 case 0:
150 if (sbrk(n) == (char *)-1) 471 j = readlink("/etc/malloc.conf", b, sizeof b - 1);
151 return (NULL); 472 if (j <= 0)
473 continue;
474 b[j] = '\0';
475 p = b;
476 break;
477 case 1:
478 if (issetugid() == 0)
479 p = getenv("MALLOC_OPTIONS");
480 else
481 continue;
482 break;
483 case 2:
484 p = malloc_options;
485 break;
486 default:
487 p = NULL;
152 } 488 }
153 bucket = 0; 489
154 amt = 8; 490 for (; p != NULL && *p != '\0'; p++) {
155 while (pagesz > amt) { 491 switch (*p) {
156 amt <<= 1; 492 case '>':
157 bucket++; 493 mopts.malloc_cache <<= 1;
494 if (mopts.malloc_cache > MALLOC_MAXCACHE)
495 mopts.malloc_cache = MALLOC_MAXCACHE;
496 break;
497 case '<':
498 mopts.malloc_cache >>= 1;
499 break;
500 case 'a':
501 mopts.malloc_abort = 0;
502 break;
503 case 'A':
504 mopts.malloc_abort = 1;
505 break;
506#ifdef MALLOC_STATS
507 case 'd':
508 mopts.malloc_stats = 0;
509 break;
510 case 'D':
511 mopts.malloc_stats = 1;
512 break;
513#endif /* MALLOC_STATS */
514 case 'f':
515 mopts.malloc_freeprot = 0;
516 break;
517 case 'F':
518 mopts.malloc_freeprot = 1;
519 break;
520 case 'g':
521 mopts.malloc_guard = 0;
522 break;
523 case 'G':
524 mopts.malloc_guard = MALLOC_PAGESIZE;
525 break;
526 case 'h':
527 mopts.malloc_hint = 0;
528 break;
529 case 'H':
530 mopts.malloc_hint = 1;
531 break;
532 case 'j':
533 mopts.malloc_junk = 0;
534 break;
535 case 'J':
536 mopts.malloc_junk = 1;
537 break;
538 case 'n':
539 case 'N':
540 break;
541 case 'p':
542 mopts.malloc_move = 0;
543 break;
544 case 'P':
545 mopts.malloc_move = 1;
546 break;
547 case 'r':
548 mopts.malloc_realloc = 0;
549 break;
550 case 'R':
551 mopts.malloc_realloc = 1;
552 break;
553 case 's':
554 mopts.malloc_freeprot = mopts.malloc_junk = 0;
555 mopts.malloc_guard = 0;
556 mopts.malloc_cache = MALLOC_DEFAULT_CACHE;
557 break;
558 case 'S':
559 mopts.malloc_freeprot = mopts.malloc_junk = 1;
560 mopts.malloc_guard = MALLOC_PAGESIZE;
561 mopts.malloc_cache = 0;
562 break;
563 case 'x':
564 mopts.malloc_xmalloc = 0;
565 break;
566 case 'X':
567 mopts.malloc_xmalloc = 1;
568 break;
569 case 'z':
570 mopts.malloc_zero = 0;
571 break;
572 case 'Z':
573 mopts.malloc_zero = 1;
574 break;
575 default: {
576 static const char q[] = "malloc() warning: "
577 "unknown char in MALLOC_OPTIONS\n";
578 write(STDERR_FILENO, q, sizeof(q) - 1);
579 break;
580 }
581 }
158 } 582 }
159 pagebucket = bucket;
160 } 583 }
584
161 /* 585 /*
162 * Convert amount of memory requested into closest block size 586 * We want junk in the entire allocation, and zero only in the part
163 * stored in hash buckets which satisfies request. 587 * the user asked for.
164 * Account for space used per block for accounting.
165 */ 588 */
166 if (nbytes <= (n = pagesz - sizeof (*op) - RSLOP)) { 589 if (mopts.malloc_zero)
167#ifndef RCHECK 590 mopts.malloc_junk = 1;
168 amt = 8; /* size of first bucket */ 591
169 bucket = 0; 592#ifdef MALLOC_STATS
170#else 593 if (mopts.malloc_stats && (atexit(malloc_exit) == -1)) {
171 amt = 16; /* size of first bucket */ 594 static const char q[] = "malloc() warning: atexit(2) failed."
172 bucket = 1; 595 " Will not be able to dump stats on exit\n";
173#endif 596 write(STDERR_FILENO, q, sizeof(q) - 1);
174 n = -((long)sizeof (*op) + RSLOP);
175 } else {
176 amt = pagesz;
177 bucket = pagebucket;
178 }
179 while (nbytes > amt + n) {
180 amt <<= 1;
181 if (amt == 0)
182 return (NULL);
183 bucket++;
184 } 597 }
598#endif /* MALLOC_STATS */
599
600 while ((mopts.malloc_canary = arc4random()) == 0)
601 ;
602
185 /* 603 /*
186 * If nothing in hash bucket right now, 604 * Allocate dir_info with a guard page on either side. Also
187 * request more memory from the system. 605 * randomise offset inside the page at which the dir_info
606 * lies (subject to alignment by 1 << MALLOC_MINSHIFT)
188 */ 607 */
189 if ((op = nextf[bucket]) == NULL) { 608 if ((p = MMAP(DIR_INFO_RSZ + (MALLOC_PAGESIZE * 2))) == MAP_FAILED)
190 morecore(bucket); 609 return -1;
191 if ((op = nextf[bucket]) == NULL) 610 mprotect(p, MALLOC_PAGESIZE, PROT_NONE);
192 return (NULL); 611 mprotect(p + MALLOC_PAGESIZE + DIR_INFO_RSZ,
193 } 612 MALLOC_PAGESIZE, PROT_NONE);
194 /* remove from linked list */ 613 d_avail = (DIR_INFO_RSZ - sizeof(*d)) >> MALLOC_MINSHIFT;
195 nextf[bucket] = op->ov_next; 614 d = (struct dir_info *)(p + MALLOC_PAGESIZE +
196 op->ov_magic = MAGIC; 615 (arc4random_uniform(d_avail) << MALLOC_MINSHIFT));
197 op->ov_index = bucket; 616
198#ifdef MSTATS 617 d->regions_free = d->regions_total = MALLOC_INITIAL_REGIONS;
199 nmalloc[bucket]++; 618 regioninfo_size = d->regions_total * sizeof(struct region_info);
200#endif 619 d->r = MMAP(regioninfo_size);
201#ifdef RCHECK 620 if (d->r == MAP_FAILED) {
621 wrterror("malloc init mmap failed", NULL);
622 d->regions_total = 0;
623 return 1;
624 }
625 for (i = 0; i <= MALLOC_MAXSHIFT; i++) {
626 LIST_INIT(&d->chunk_info_list[i]);
627 LIST_INIT(&d->chunk_dir[i]);
628 }
629 malloc_used += regioninfo_size;
630 d->canary1 = mopts.malloc_canary ^ (u_int32_t)(uintptr_t)d;
631 d->canary2 = ~d->canary1;
632
633 *dp = d;
634
202 /* 635 /*
203 * Record allocated size of block and 636 * Options have been set and will never be reset.
204 * bound space with magic numbers. 637 * Prevent further tampering with them.
205 */ 638 */
206 op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); 639 if (((uintptr_t)&malloc_readonly & MALLOC_PAGEMASK) == 0)
207 op->ov_rmagic = RMAGIC; 640 mprotect(&malloc_readonly, sizeof(malloc_readonly), PROT_READ);
208 *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC; 641
209#endif 642 return 0;
210 return ((char *)(op + 1));
211} 643}
212 644
213/* 645static int
214 * Allocate more memory to the indicated bucket. 646omalloc_grow(struct dir_info *d)
215 */
216static void
217morecore(bucket)
218 int bucket;
219{ 647{
220 register union overhead *op; 648 size_t newtotal;
221 register long sz; /* size of desired block */ 649 size_t newsize;
222 long amt; /* amount to allocate */ 650 size_t mask;
223 int nblks; /* how many blocks we get */ 651 size_t i;
652 struct region_info *p;
224 653
225 /* 654 if (d->regions_total > SIZE_MAX / sizeof(struct region_info) / 2 )
226 * sbrk_size <= 0 only for big, FLUFFY, requests (about 655 return 1;
227 * 2^30 bytes on a VAX, I think) or for a negative arg. 656
228 */ 657 newtotal = d->regions_total * 2;
229 sz = 1 << (bucket + 3); 658 newsize = newtotal * sizeof(struct region_info);
230#ifdef DEBUG 659 mask = newtotal - 1;
231 ASSERT(sz > 0); 660
232#else 661 p = MMAP(newsize);
233 if (sz <= 0) 662 if (p == MAP_FAILED)
234 return; 663 return 1;
235#endif 664
236 if (sz < pagesz) { 665 malloc_used += newsize;
237 amt = pagesz; 666 memset(p, 0, newsize);
238 nblks = amt / sz; 667 STATS_ZERO(d->inserts);
239 } else { 668 STATS_ZERO(d->insert_collisions);
240 amt = sz + pagesz; 669 for (i = 0; i < d->regions_total; i++) {
241 nblks = 1; 670 void *q = d->r[i].p;
671 if (q != NULL) {
672 size_t index = hash(q) & mask;
673 STATS_INC(d->inserts);
674 while (p[index].p != NULL) {
675 index = (index - 1) & mask;
676 STATS_INC(d->insert_collisions);
677 }
678 p[index] = d->r[i];
679 }
242 } 680 }
243 op = (union overhead *)sbrk(amt); 681 /* avoid pages containing meta info to end up in cache */
244 /* no more room! */ 682 if (munmap(d->r, d->regions_total * sizeof(struct region_info)))
245 if ((long)op == -1) 683 wrterror("munmap", d->r);
246 return; 684 else
247 /* 685 malloc_used -= d->regions_total * sizeof(struct region_info);
248 * Add new memory allocated to that on 686 d->regions_free = d->regions_free + d->regions_total;
249 * free list for this hash bucket. 687 d->regions_total = newtotal;
250 */ 688 d->r = p;
251 nextf[bucket] = op; 689 return 0;
252 while (--nblks > 0) {
253 op->ov_next = (union overhead *)((caddr_t)op + sz);
254 op = (union overhead *)((caddr_t)op + sz);
255 }
256} 690}
257 691
258void 692static struct chunk_info *
259free(cp) 693alloc_chunk_info(struct dir_info *d, int bits)
260 void *cp; 694{
261{ 695 struct chunk_info *p;
262 register long size; 696 size_t size, count;
263 register union overhead *op; 697
264 698 if (bits == 0)
265 if (cp == NULL) 699 count = MALLOC_PAGESIZE / MALLOC_MINSIZE;
266 return; 700 else
267 op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); 701 count = MALLOC_PAGESIZE >> bits;
268#ifdef DEBUG 702
269 ASSERT(op->ov_magic == MAGIC); /* make sure it was in use */ 703 size = howmany(count, MALLOC_BITS);
270#else 704 size = sizeof(struct chunk_info) + (size - 1) * sizeof(u_short);
271 if (op->ov_magic != MAGIC) 705 size = ALIGN(size);
272 return; /* sanity */ 706
273#endif 707 if (LIST_EMPTY(&d->chunk_info_list[bits])) {
274#ifdef RCHECK 708 void *q;
275 ASSERT(op->ov_rmagic == RMAGIC); 709 int i;
276 ASSERT(*(u_short *)((caddr_t)(op + 1) + op->ov_size) == RMAGIC); 710
277#endif 711 q = MMAP(MALLOC_PAGESIZE);
278 size = op->ov_index; 712 if (q == MAP_FAILED)
279 ASSERT(size < NBUCKETS); 713 return NULL;
280 op->ov_next = nextf[size]; /* also clobbers ov_magic */ 714 malloc_used += MALLOC_PAGESIZE;
281 nextf[size] = op; 715 count = MALLOC_PAGESIZE / size;
282#ifdef MSTATS 716 for (i = 0; i < count; i++, q += size)
283 nmalloc[size]--; 717 LIST_INSERT_HEAD(&d->chunk_info_list[bits],
718 (struct chunk_info *)q, entries);
719 }
720 p = LIST_FIRST(&d->chunk_info_list[bits]);
721 LIST_REMOVE(p, entries);
722 memset(p, 0, size);
723 p->canary = d->canary1;
724 return p;
725}
726
727static int
728insert(struct dir_info *d, void *p, size_t sz, void *f)
729{
730 size_t index;
731 size_t mask;
732 void *q;
733
734 if (d->regions_free * 4 < d->regions_total) {
735 if (omalloc_grow(d))
736 return 1;
737 }
738 mask = d->regions_total - 1;
739 index = hash(p) & mask;
740 q = d->r[index].p;
741 STATS_INC(d->inserts);
742 while (q != NULL) {
743 index = (index - 1) & mask;
744 q = d->r[index].p;
745 STATS_INC(d->insert_collisions);
746 }
747 d->r[index].p = p;
748 d->r[index].size = sz;
749#ifdef MALLOC_STATS
750 d->r[index].f = f;
284#endif 751#endif
752 d->regions_free--;
753 return 0;
285} 754}
286 755
756static struct region_info *
757find(struct dir_info *d, void *p)
758{
759 size_t index;
760 size_t mask = d->regions_total - 1;
761 void *q, *r;
762
763 if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) ||
764 d->canary1 != ~d->canary2)
765 wrterror("internal struct corrupt", NULL);
766 p = MASK_POINTER(p);
767 index = hash(p) & mask;
768 r = d->r[index].p;
769 q = MASK_POINTER(r);
770 STATS_INC(d->finds);
771 while (q != p && r != NULL) {
772 index = (index - 1) & mask;
773 r = d->r[index].p;
774 q = MASK_POINTER(r);
775 STATS_INC(d->find_collisions);
776 }
777 return q == p ? &d->r[index] : NULL;
778}
779
780static void
781delete(struct dir_info *d, struct region_info *ri)
782{
783 /* algorithm R, Knuth Vol III section 6.4 */
784 size_t mask = d->regions_total - 1;
785 size_t i, j, r;
786
787 if (d->regions_total & (d->regions_total - 1))
788 wrterror("regions_total not 2^x", NULL);
789 d->regions_free++;
790 STATS_INC(g_pool->deletes);
791
792 i = ri - d->r;
793 for (;;) {
794 d->r[i].p = NULL;
795 d->r[i].size = 0;
796 j = i;
797 for (;;) {
798 i = (i - 1) & mask;
799 if (d->r[i].p == NULL)
800 return;
801 r = hash(d->r[i].p) & mask;
802 if ((i <= r && r < j) || (r < j && j < i) ||
803 (j < i && i <= r))
804 continue;
805 d->r[j] = d->r[i];
806 STATS_INC(g_pool->delete_moves);
807 break;
808 }
809
810 }
811}
812
287/* 813/*
288 * When a program attempts "storage compaction" as mentioned in the 814 * Allocate a page of chunks
289 * old malloc man page, it realloc's an already freed block. Usually
290 * this is the last block it freed; occasionally it might be farther
291 * back. We have to search all the free lists for the block in order
292 * to determine its bucket: 1st we make one pass thru the lists
293 * checking only the first block in each; if that fails we search
294 * ``realloc_srchlen'' blocks in each list for a match (the variable
295 * is extern so the caller can modify it). If that fails we just copy
296 * however many bytes was given to realloc() and hope it's not huge.
297 */ 815 */
298int realloc_srchlen = 4; /* 4 should be plenty, -1 =>'s whole list */ 816static struct chunk_info *
817omalloc_make_chunks(struct dir_info *d, int bits)
818{
819 struct chunk_info *bp;
820 void *pp;
821 int i, k;
299 822
300void * 823 /* Allocate a new bucket */
301realloc(cp, nbytes) 824 pp = map(d, MALLOC_PAGESIZE, 0);
302 void *cp; 825 if (pp == MAP_FAILED)
303 size_t nbytes; 826 return NULL;
304{ 827
305 register u_long onb; 828 bp = alloc_chunk_info(d, bits);
306 register long i; 829 if (bp == NULL) {
307 union overhead *op; 830 unmap(d, pp, MALLOC_PAGESIZE);
308 char *res; 831 return NULL;
309 int was_alloced = 0; 832 }
310 833
311 if (cp == NULL) 834 /* memory protect the page allocated in the malloc(0) case */
312 return (malloc(nbytes)); 835 if (bits == 0) {
313 op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); 836 bp->size = 0;
314 if (op->ov_magic == MAGIC) { 837 bp->shift = 1;
315 was_alloced++; 838 i = MALLOC_MINSIZE - 1;
316 i = op->ov_index; 839 while (i >>= 1)
317 } else { 840 bp->shift++;
318 /* 841 bp->total = bp->free = MALLOC_PAGESIZE >> bp->shift;
319 * Already free, doing "compaction". 842 bp->page = pp;
320 * 843
321 * Search for the old block of memory on the 844 k = mprotect(pp, MALLOC_PAGESIZE, PROT_NONE);
322 * free list. First, check the most common 845 if (k < 0) {
323 * case (last element free'd), then (this failing) 846 unmap(d, pp, MALLOC_PAGESIZE);
324 * the last ``realloc_srchlen'' items free'd. 847 LIST_INSERT_HEAD(&d->chunk_info_list[0], bp, entries);
325 * If all lookups fail, then assume the size of 848 return NULL;
326 * the memory block being realloc'd is the
327 * largest possible (so that all "nbytes" of new
328 * memory are copied into). Note that this could cause
329 * a memory fault if the old area was tiny, and the moon
330 * is gibbous. However, that is very unlikely.
331 */
332 if ((i = findbucket(op, 1)) < 0 &&
333 (i = findbucket(op, realloc_srchlen)) < 0)
334 i = NBUCKETS;
335 }
336 onb = 1 << (i + 3);
337 if (onb < pagesz)
338 onb -= sizeof (*op) + RSLOP;
339 else
340 onb += pagesz - sizeof (*op) - RSLOP;
341 /* avoid the copy if same size block */
342 if (was_alloced) {
343 if (i) {
344 i = 1 << (i + 2);
345 if (i < pagesz)
346 i -= sizeof (*op) + RSLOP;
347 else
348 i += pagesz - sizeof (*op) - RSLOP;
349 } 849 }
350 if (nbytes <= onb && nbytes > i) { 850 } else {
351#ifdef RCHECK 851 bp->size = 1U << bits;
352 op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); 852 bp->shift = bits;
353 *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC; 853 bp->total = bp->free = MALLOC_PAGESIZE >> bits;
354#endif 854 bp->page = pp;
355 return(cp);
356 } else
357 free(cp);
358 } 855 }
359 if ((res = malloc(nbytes)) == NULL) 856
360 return (NULL); 857 /* set all valid bits in the bitmap */
361 if (cp != res) /* common optimization if "compacting" */ 858 k = bp->total;
362 bcopy(cp, res, (nbytes < onb) ? nbytes : onb); 859 i = 0;
363 return (res); 860
861 /* Do a bunch at a time */
862 for (; (k - i) >= MALLOC_BITS; i += MALLOC_BITS)
863 bp->bits[i / MALLOC_BITS] = (u_short)~0U;
864
865 for (; i < k; i++)
866 bp->bits[i / MALLOC_BITS] |= (u_short)1U << (i % MALLOC_BITS);
867
868 LIST_INSERT_HEAD(&d->chunk_dir[bits], bp, entries);
869
870 bits++;
871 if ((uintptr_t)pp & bits)
872 wrterror("pp & bits", pp);
873
874 insert(d, (void *)((uintptr_t)pp | bits), (uintptr_t)bp, NULL);
875 return bp;
364} 876}
365 877
878
366/* 879/*
367 * Search ``srchlen'' elements of each free list for a block whose 880 * Allocate a chunk
368 * header starts at ``freep''. If srchlen is -1 search the whole list.
369 * Return bucket number, or -1 if not found.
370 */ 881 */
371static 882static void *
372findbucket(freep, srchlen) 883malloc_bytes(struct dir_info *d, size_t size, void *f)
373 union overhead *freep;
374 int srchlen;
375{ 884{
376 register union overhead *p; 885 int i, j;
377 register int i, j; 886 size_t k;
887 u_short u, *lp;
888 struct chunk_info *bp;
889
890 if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) ||
891 d->canary1 != ~d->canary2)
892 wrterror("internal struct corrupt", NULL);
893 /* Don't bother with anything less than this */
894 /* unless we have a malloc(0) requests */
895 if (size != 0 && size < MALLOC_MINSIZE)
896 size = MALLOC_MINSIZE;
378 897
379 for (i = 0; i < NBUCKETS; i++) { 898 /* Find the right bucket */
899 if (size == 0)
380 j = 0; 900 j = 0;
381 for (p = nextf[i]; p && j != srchlen; p = p->ov_next) { 901 else {
382 if (p == freep) 902 j = MALLOC_MINSHIFT;
383 return (i); 903 i = (size - 1) >> (MALLOC_MINSHIFT - 1);
904 while (i >>= 1)
384 j++; 905 j++;
906 }
907
908 /* If it's empty, make a page more of that size chunks */
909 if (LIST_EMPTY(&d->chunk_dir[j])) {
910 bp = omalloc_make_chunks(d, j);
911 if (bp == NULL)
912 return NULL;
913 } else
914 bp = LIST_FIRST(&d->chunk_dir[j]);
915
916 if (bp->canary != d->canary1)
917 wrterror("chunk info corrupted", NULL);
918
919 i = d->chunk_start;
920 if (bp->free > 1)
921 i += getrnibble();
922 if (i >= bp->total)
923 i &= bp->total - 1;
924 for (;;) {
925 for (;;) {
926 lp = &bp->bits[i / MALLOC_BITS];
927 if (!*lp) {
928 i += MALLOC_BITS;
929 i &= ~(MALLOC_BITS - 1);
930 if (i >= bp->total)
931 i = 0;
932 } else
933 break;
934 }
935 k = i % MALLOC_BITS;
936 u = 1 << k;
937 if (*lp & u)
938 break;
939 if (++i >= bp->total)
940 i = 0;
941 }
942 d->chunk_start += i + 1;
943#ifdef MALLOC_STATS
944 if (i == 0) {
945 struct region_info *r = find(d, bp->page);
946 r->f = f;
947 }
948#endif
949
950 *lp ^= u;
951
952 /* If there are no more free, remove from free-list */
953 if (!--bp->free)
954 LIST_REMOVE(bp, entries);
955
956 /* Adjust to the real offset of that chunk */
957 k += (lp - bp->bits) * MALLOC_BITS;
958 k <<= bp->shift;
959
960 if (mopts.malloc_junk && bp->size > 0)
961 memset((char *)bp->page + k, SOME_JUNK, bp->size);
962 return ((char *)bp->page + k);
963}
964
965
966/*
967 * Free a chunk, and possibly the page it's on, if the page becomes empty.
968 */
969static void
970free_bytes(struct dir_info *d, struct region_info *r, void *ptr)
971{
972 struct chunk_head *mp;
973 struct chunk_info *info;
974 int i;
975
976 info = (struct chunk_info *)r->size;
977 if (info->canary != d->canary1)
978 wrterror("chunk info corrupted", NULL);
979
980 /* Find the chunk number on the page */
981 i = ((uintptr_t)ptr & MALLOC_PAGEMASK) >> info->shift;
982
983 if ((uintptr_t)ptr & ((1U << (info->shift)) - 1)) {
984 wrterror("modified chunk-pointer", ptr);
985 return;
986 }
987 if (info->bits[i / MALLOC_BITS] & (1U << (i % MALLOC_BITS))) {
988 wrterror("chunk is already free", ptr);
989 return;
990 }
991
992 info->bits[i / MALLOC_BITS] |= 1U << (i % MALLOC_BITS);
993 info->free++;
994
995 if (info->size != 0)
996 mp = d->chunk_dir + info->shift;
997 else
998 mp = d->chunk_dir;
999
1000 if (info->free == 1) {
1001 /* Page became non-full */
1002 LIST_INSERT_HEAD(mp, info, entries);
1003 return;
1004 }
1005 if (info->free != info->total)
1006 return;
1007
1008 LIST_REMOVE(info, entries);
1009
1010 if (info->size == 0 && !mopts.malloc_freeprot)
1011 mprotect(info->page, MALLOC_PAGESIZE, PROT_READ | PROT_WRITE);
1012 unmap(d, info->page, MALLOC_PAGESIZE);
1013
1014 delete(d, r);
1015 if (info->size != 0)
1016 mp = &d->chunk_info_list[info->shift];
1017 else
1018 mp = &d->chunk_info_list[0];
1019 LIST_INSERT_HEAD(mp, info, entries);
1020}
1021
1022
1023
1024static void *
1025omalloc(size_t sz, int zero_fill, void *f)
1026{
1027 void *p;
1028 size_t psz;
1029
1030 if (sz > MALLOC_MAXCHUNK) {
1031 if (sz >= SIZE_MAX - mopts.malloc_guard - MALLOC_PAGESIZE) {
1032 errno = ENOMEM;
1033 return NULL;
1034 }
1035 sz += mopts.malloc_guard;
1036 psz = PAGEROUND(sz);
1037 p = map(g_pool, psz, zero_fill);
1038 if (p == MAP_FAILED) {
1039 errno = ENOMEM;
1040 return NULL;
1041 }
1042 if (insert(g_pool, p, sz, f)) {
1043 unmap(g_pool, p, psz);
1044 errno = ENOMEM;
1045 return NULL;
385 } 1046 }
1047 if (mopts.malloc_guard) {
1048 if (mprotect((char *)p + psz - mopts.malloc_guard,
1049 mopts.malloc_guard, PROT_NONE))
1050 wrterror("mprotect", NULL);
1051 malloc_guarded += mopts.malloc_guard;
1052 }
1053
1054 if (mopts.malloc_move &&
1055 sz - mopts.malloc_guard < MALLOC_PAGESIZE -
1056 MALLOC_LEEWAY) {
1057 /* fill whole allocation */
1058 if (mopts.malloc_junk)
1059 memset(p, SOME_JUNK, psz - mopts.malloc_guard);
1060 /* shift towards the end */
1061 p = ((char *)p) + ((MALLOC_PAGESIZE - MALLOC_LEEWAY -
1062 (sz - mopts.malloc_guard)) & ~(MALLOC_MINSIZE-1));
1063 /* fill zeros if needed and overwritten above */
1064 if (zero_fill && mopts.malloc_junk)
1065 memset(p, 0, sz - mopts.malloc_guard);
1066 } else {
1067 if (mopts.malloc_junk) {
1068 if (zero_fill)
1069 memset((char *)p + sz - mopts.malloc_guard,
1070 SOME_JUNK, psz - sz);
1071 else
1072 memset(p, SOME_JUNK,
1073 psz - mopts.malloc_guard);
1074 }
1075 }
1076
1077 } else {
1078 /* takes care of SOME_JUNK */
1079 p = malloc_bytes(g_pool, sz, f);
1080 if (zero_fill && p != NULL && sz > 0)
1081 memset(p, 0, sz);
386 } 1082 }
387 return (-1); 1083
1084 return p;
388} 1085}
389 1086
390#ifdef MSTATS
391/* 1087/*
392 * mstats - print out statistics about malloc 1088 * Common function for handling recursion. Only
393 * 1089 * print the error message once, to avoid making the problem
394 * Prints two lines of numbers, one showing the length of the free list 1090 * potentially worse.
395 * for each size category, the second showing the number of mallocs -
396 * frees for each size category.
397 */ 1091 */
398mstats(s) 1092static void
399 char *s; 1093malloc_recurse(void)
400{ 1094{
401 register int i, j; 1095 static int noprint;
402 register union overhead *p; 1096
403 int totfree = 0, 1097 if (noprint == 0) {
404 totused = 0; 1098 noprint = 1;
405 1099 wrterror("recursive call", NULL);
406 fprintf(stderr, "Memory allocation statistics %s\nfree:\t", s); 1100 }
407 for (i = 0; i < NBUCKETS; i++) { 1101 malloc_active--;
408 for (j = 0, p = nextf[i]; p; p = p->ov_next, j++) 1102 _MALLOC_UNLOCK();
409 ; 1103 errno = EDEADLK;
410 fprintf(stderr, " %d", j); 1104}
411 totfree += j * (1 << (i + 3)); 1105
412 } 1106static int
413 fprintf(stderr, "\nused:\t"); 1107malloc_init(void)
414 for (i = 0; i < NBUCKETS; i++) { 1108{
415 fprintf(stderr, " %d", nmalloc[i]); 1109 if (omalloc_init(&g_pool)) {
416 totused += nmalloc[i] * (1 << (i + 3)); 1110 _MALLOC_UNLOCK();
417 } 1111 if (mopts.malloc_xmalloc)
418 fprintf(stderr, "\n\tTotal in use: %d, total free: %d\n", 1112 wrterror("out of memory", NULL);
419 totused, totfree); 1113 errno = ENOMEM;
1114 return -1;
1115 }
1116 return 0;
420} 1117}
1118
1119void *
1120malloc(size_t size)
1121{
1122 void *r;
1123 int saved_errno = errno;
1124
1125 _MALLOC_LOCK();
1126 malloc_func = " in malloc():";
1127 if (g_pool == NULL) {
1128 if (malloc_init() != 0)
1129 return NULL;
1130 }
1131 if (malloc_active++) {
1132 malloc_recurse();
1133 return NULL;
1134 }
1135 r = omalloc(size, mopts.malloc_zero, CALLER);
1136 malloc_active--;
1137 _MALLOC_UNLOCK();
1138 if (r == NULL && mopts.malloc_xmalloc) {
1139 wrterror("out of memory", NULL);
1140 errno = ENOMEM;
1141 }
1142 if (r != NULL)
1143 errno = saved_errno;
1144 return r;
1145}
1146
1147static void
1148ofree(void *p)
1149{
1150 struct region_info *r;
1151 size_t sz;
1152
1153 r = find(g_pool, p);
1154 if (r == NULL) {
1155 wrterror("bogus pointer (double free?)", p);
1156 return;
1157 }
1158 REALSIZE(sz, r);
1159 if (sz > MALLOC_MAXCHUNK) {
1160 if (sz - mopts.malloc_guard >= MALLOC_PAGESIZE -
1161 MALLOC_LEEWAY) {
1162 if (r->p != p) {
1163 wrterror("bogus pointer", p);
1164 return;
1165 }
1166 } else {
1167#if notyetbecause_of_realloc
1168 /* shifted towards the end */
1169 if (p != ((char *)r->p) + ((MALLOC_PAGESIZE -
1170 MALLOC_MINSIZE - sz - mopts.malloc_guard) &
1171 ~(MALLOC_MINSIZE-1))) {
1172 }
421#endif 1173#endif
1174 p = r->p;
1175 }
1176 if (mopts.malloc_guard) {
1177 if (sz < mopts.malloc_guard)
1178 wrterror("guard size", NULL);
1179 if (!mopts.malloc_freeprot) {
1180 if (mprotect((char *)p + PAGEROUND(sz) -
1181 mopts.malloc_guard, mopts.malloc_guard,
1182 PROT_READ | PROT_WRITE))
1183 wrterror("mprotect", NULL);
1184 }
1185 malloc_guarded -= mopts.malloc_guard;
1186 }
1187 if (mopts.malloc_junk && !mopts.malloc_freeprot)
1188 memset(p, SOME_FREEJUNK,
1189 PAGEROUND(sz) - mopts.malloc_guard);
1190 unmap(g_pool, p, PAGEROUND(sz));
1191 delete(g_pool, r);
1192 } else {
1193 void *tmp;
1194 int i;
1195
1196 if (mopts.malloc_junk && sz > 0)
1197 memset(p, SOME_FREEJUNK, sz);
1198 if (!mopts.malloc_freeprot) {
1199 i = getrnibble();
1200 tmp = p;
1201 p = g_pool->delayed_chunks[i];
1202 g_pool->delayed_chunks[i] = tmp;
1203 }
1204 if (p != NULL) {
1205 r = find(g_pool, p);
1206 if (r == NULL) {
1207 wrterror("bogus pointer (double free?)", p);
1208 return;
1209 }
1210 free_bytes(g_pool, r, p);
1211 }
1212 }
1213}
1214
1215void
1216free(void *ptr)
1217{
1218 int saved_errno = errno;
1219
1220 /* This is legal. */
1221 if (ptr == NULL)
1222 return;
1223
1224 _MALLOC_LOCK();
1225 malloc_func = " in free():";
1226 if (g_pool == NULL) {
1227 _MALLOC_UNLOCK();
1228 wrterror("free() called before allocation", NULL);
1229 return;
1230 }
1231 if (malloc_active++) {
1232 malloc_recurse();
1233 return;
1234 }
1235 ofree(ptr);
1236 malloc_active--;
1237 _MALLOC_UNLOCK();
1238 errno = saved_errno;
1239}
1240
1241
1242static void *
1243orealloc(void *p, size_t newsz, void *f)
1244{
1245 struct region_info *r;
1246 size_t oldsz, goldsz, gnewsz;
1247 void *q;
1248
1249 if (p == NULL)
1250 return omalloc(newsz, 0, f);
1251
1252 r = find(g_pool, p);
1253 if (r == NULL) {
1254 wrterror("bogus pointer (double free?)", p);
1255 return NULL;
1256 }
1257 if (newsz >= SIZE_MAX - mopts.malloc_guard - MALLOC_PAGESIZE) {
1258 errno = ENOMEM;
1259 return NULL;
1260 }
1261
1262 REALSIZE(oldsz, r);
1263 goldsz = oldsz;
1264 if (oldsz > MALLOC_MAXCHUNK) {
1265 if (oldsz < mopts.malloc_guard)
1266 wrterror("guard size", NULL);
1267 oldsz -= mopts.malloc_guard;
1268 }
1269
1270 gnewsz = newsz;
1271 if (gnewsz > MALLOC_MAXCHUNK)
1272 gnewsz += mopts.malloc_guard;
1273
1274 if (newsz > MALLOC_MAXCHUNK && oldsz > MALLOC_MAXCHUNK && p == r->p &&
1275 !mopts.malloc_realloc) {
1276 size_t roldsz = PAGEROUND(goldsz);
1277 size_t rnewsz = PAGEROUND(gnewsz);
1278
1279 if (rnewsz > roldsz) {
1280 if (!mopts.malloc_guard) {
1281 STATS_INC(g_pool->cheap_realloc_tries);
1282 zapcacheregion(g_pool, (char *)p + roldsz);
1283 q = MMAPA((char *)p + roldsz, rnewsz - roldsz);
1284 if (q == (char *)p + roldsz) {
1285 malloc_used += rnewsz - roldsz;
1286 if (mopts.malloc_junk)
1287 memset(q, SOME_JUNK,
1288 rnewsz - roldsz);
1289 r->size = newsz;
1290 STATS_SETF(r, f);
1291 STATS_INC(g_pool->cheap_reallocs);
1292 return p;
1293 } else if (q != MAP_FAILED)
1294 munmap(q, rnewsz - roldsz);
1295 }
1296 } else if (rnewsz < roldsz) {
1297 if (mopts.malloc_guard) {
1298 if (mprotect((char *)p + roldsz -
1299 mopts.malloc_guard, mopts.malloc_guard,
1300 PROT_READ | PROT_WRITE))
1301 wrterror("mprotect", NULL);
1302 if (mprotect((char *)p + rnewsz -
1303 mopts.malloc_guard, mopts.malloc_guard,
1304 PROT_NONE))
1305 wrterror("mprotect", NULL);
1306 }
1307 unmap(g_pool, (char *)p + rnewsz, roldsz - rnewsz);
1308 r->size = gnewsz;
1309 STATS_SETF(r, f);
1310 return p;
1311 } else {
1312 if (newsz > oldsz && mopts.malloc_junk)
1313 memset((char *)p + newsz, SOME_JUNK,
1314 rnewsz - mopts.malloc_guard - newsz);
1315 r->size = gnewsz;
1316 STATS_SETF(r, f);
1317 return p;
1318 }
1319 }
1320 if (newsz <= oldsz && newsz > oldsz / 2 && !mopts.malloc_realloc) {
1321 if (mopts.malloc_junk && newsz > 0)
1322 memset((char *)p + newsz, SOME_JUNK, oldsz - newsz);
1323 STATS_SETF(r, f);
1324 return p;
1325 } else if (newsz != oldsz || mopts.malloc_realloc) {
1326 q = omalloc(newsz, 0, f);
1327 if (q == NULL)
1328 return NULL;
1329 if (newsz != 0 && oldsz != 0)
1330 memcpy(q, p, oldsz < newsz ? oldsz : newsz);
1331 ofree(p);
1332 return q;
1333 } else {
1334 STATS_SETF(r, f);
1335 return p;
1336 }
1337}
1338
1339void *
1340realloc(void *ptr, size_t size)
1341{
1342 void *r;
1343 int saved_errno = errno;
1344
1345 _MALLOC_LOCK();
1346 malloc_func = " in realloc():";
1347 if (g_pool == NULL) {
1348 if (malloc_init() != 0)
1349 return NULL;
1350 }
1351 if (malloc_active++) {
1352 malloc_recurse();
1353 return NULL;
1354 }
1355 r = orealloc(ptr, size, CALLER);
1356
1357 malloc_active--;
1358 _MALLOC_UNLOCK();
1359 if (r == NULL && mopts.malloc_xmalloc) {
1360 wrterror("out of memory", NULL);
1361 errno = ENOMEM;
1362 }
1363 if (r != NULL)
1364 errno = saved_errno;
1365 return r;
1366}
1367
1368
1369#define MUL_NO_OVERFLOW (1UL << (sizeof(size_t) * 4))
1370
1371void *
1372calloc(size_t nmemb, size_t size)
1373{
1374 void *r;
1375 int saved_errno = errno;
1376
1377 _MALLOC_LOCK();
1378 malloc_func = " in calloc():";
1379 if (g_pool == NULL) {
1380 if (malloc_init() != 0)
1381 return NULL;
1382 }
1383 if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
1384 nmemb > 0 && SIZE_MAX / nmemb < size) {
1385 _MALLOC_UNLOCK();
1386 if (mopts.malloc_xmalloc)
1387 wrterror("out of memory", NULL);
1388 errno = ENOMEM;
1389 return NULL;
1390 }
1391
1392 if (malloc_active++) {
1393 malloc_recurse();
1394 return NULL;
1395 }
1396
1397 size *= nmemb;
1398 r = omalloc(size, 1, CALLER);
1399
1400 malloc_active--;
1401 _MALLOC_UNLOCK();
1402 if (r == NULL && mopts.malloc_xmalloc) {
1403 wrterror("out of memory", NULL);
1404 errno = ENOMEM;
1405 }
1406 if (r != NULL)
1407 errno = saved_errno;
1408 return r;
1409}
1410
1411int
1412posix_memalign(void **memptr, size_t alignment, size_t size)
1413{
1414 void *result;
1415
1416 /* Make sure that alignment is a large enough power of 2. */
1417 if (((alignment - 1) & alignment) != 0 || alignment < sizeof(void *) ||
1418 alignment > MALLOC_PAGESIZE)
1419 return EINVAL;
1420
1421 /*
1422 * max(size, alignment) is enough to assure the requested alignment,
1423 * since the allocator always allocates power-of-two blocks.
1424 */
1425 if (size < alignment)
1426 size = alignment;
1427 result = malloc(size);
1428
1429 if (result == NULL)
1430 return ENOMEM;
1431
1432 *memptr = result;
1433 return 0;
1434}
1435
1436#ifdef MALLOC_STATS
1437
1438struct malloc_leak {
1439 void (*f)();
1440 size_t total_size;
1441 int count;
1442};
1443
1444struct leaknode {
1445 RB_ENTRY(leaknode) entry;
1446 struct malloc_leak d;
1447};
1448
1449static int
1450leakcmp(struct leaknode *e1, struct leaknode *e2)
1451{
1452 return e1->d.f < e2->d.f ? -1 : e1->d.f > e2->d.f;
1453}
1454
1455static RB_HEAD(leaktree, leaknode) leakhead;
1456RB_GENERATE_STATIC(leaktree, leaknode, entry, leakcmp)
1457
1458static void
1459putleakinfo(void *f, size_t sz, int cnt)
1460{
1461 struct leaknode key, *p;
1462 static struct leaknode *page;
1463 static int used;
1464
1465 if (cnt == 0)
1466 return;
1467
1468 key.d.f = f;
1469 p = RB_FIND(leaktree, &leakhead, &key);
1470 if (p == NULL) {
1471 if (page == NULL ||
1472 used >= MALLOC_PAGESIZE / sizeof(struct leaknode)) {
1473 page = MMAP(MALLOC_PAGESIZE);
1474 if (page == MAP_FAILED)
1475 return;
1476 used = 0;
1477 }
1478 p = &page[used++];
1479 p->d.f = f;
1480 p->d.total_size = sz * cnt;
1481 p->d.count = cnt;
1482 RB_INSERT(leaktree, &leakhead, p);
1483 } else {
1484 p->d.total_size += sz * cnt;
1485 p->d.count += cnt;
1486 }
1487}
1488
1489static struct malloc_leak *malloc_leaks;
1490
1491static void
1492dump_leaks(int fd)
1493{
1494 struct leaknode *p;
1495 char buf[64];
1496 int i = 0;
1497
1498 snprintf(buf, sizeof(buf), "Leak report\n");
1499 write(fd, buf, strlen(buf));
1500 snprintf(buf, sizeof(buf), " f sum # avg\n");
1501 write(fd, buf, strlen(buf));
1502 /* XXX only one page of summary */
1503 if (malloc_leaks == NULL)
1504 malloc_leaks = MMAP(MALLOC_PAGESIZE);
1505 if (malloc_leaks != MAP_FAILED)
1506 memset(malloc_leaks, 0, MALLOC_PAGESIZE);
1507 RB_FOREACH(p, leaktree, &leakhead) {
1508 snprintf(buf, sizeof(buf), "%12p %7zu %6u %6zu\n", p->d.f,
1509 p->d.total_size, p->d.count, p->d.total_size / p->d.count);
1510 write(fd, buf, strlen(buf));
1511 if (malloc_leaks == MAP_FAILED ||
1512 i >= MALLOC_PAGESIZE / sizeof(struct malloc_leak))
1513 continue;
1514 malloc_leaks[i].f = p->d.f;
1515 malloc_leaks[i].total_size = p->d.total_size;
1516 malloc_leaks[i].count = p->d.count;
1517 i++;
1518 }
1519}
1520
1521static void
1522dump_chunk(int fd, struct chunk_info *p, void *f, int fromfreelist)
1523{
1524 char buf[64];
1525
1526 while (p != NULL) {
1527 snprintf(buf, sizeof(buf), "chunk %12p %12p %4d %d/%d\n",
1528 p->page, ((p->bits[0] & 1) ? NULL : f),
1529 p->size, p->free, p->total);
1530 write(fd, buf, strlen(buf));
1531 if (!fromfreelist) {
1532 if (p->bits[0] & 1)
1533 putleakinfo(NULL, p->size, p->total - p->free);
1534 else {
1535 putleakinfo(f, p->size, 1);
1536 putleakinfo(NULL, p->size,
1537 p->total - p->free - 1);
1538 }
1539 break;
1540 }
1541 p = LIST_NEXT(p, entries);
1542 if (p != NULL) {
1543 snprintf(buf, sizeof(buf), " ");
1544 write(fd, buf, strlen(buf));
1545 }
1546 }
1547}
1548
1549static void
1550dump_free_chunk_info(int fd, struct dir_info *d)
1551{
1552 char buf[64];
1553 int i, count;
1554
1555 snprintf(buf, sizeof(buf), "Free chunk structs:\n");
1556 write(fd, buf, strlen(buf));
1557 for (i = 0; i <= MALLOC_MAXSHIFT; i++) {
1558 struct chunk_info *p;
1559
1560 count = 0;
1561 LIST_FOREACH(p, &d->chunk_info_list[i], entries)
1562 count++;
1563 p = LIST_FIRST(&d->chunk_dir[i]);
1564 if (p == NULL && count == 0)
1565 continue;
1566 snprintf(buf, sizeof(buf), "%2d) %3d ", i, count);
1567 write(fd, buf, strlen(buf));
1568 if (p != NULL)
1569 dump_chunk(fd, p, NULL, 1);
1570 else
1571 write(fd, "\n", 1);
1572 }
1573
1574}
1575
1576static void
1577dump_free_page_info(int fd, struct dir_info *d)
1578{
1579 char buf[64];
1580 int i;
1581
1582 snprintf(buf, sizeof(buf), "Free pages cached: %zu\n",
1583 d->free_regions_size);
1584 write(fd, buf, strlen(buf));
1585 for (i = 0; i < mopts.malloc_cache; i++) {
1586 if (d->free_regions[i].p != NULL) {
1587 snprintf(buf, sizeof(buf), "%2d) ", i);
1588 write(fd, buf, strlen(buf));
1589 snprintf(buf, sizeof(buf), "free at %p: %zu\n",
1590 d->free_regions[i].p, d->free_regions[i].size);
1591 write(fd, buf, strlen(buf));
1592 }
1593 }
1594}
1595
1596static void
1597malloc_dump1(int fd, struct dir_info *d)
1598{
1599 char buf[64];
1600 size_t i, realsize;
1601
1602 snprintf(buf, sizeof(buf), "Malloc dir of %s at %p\n", __progname, d);
1603 write(fd, buf, strlen(buf));
1604 if (d == NULL)
1605 return;
1606 snprintf(buf, sizeof(buf), "Region slots free %zu/%zu\n",
1607 d->regions_free, d->regions_total);
1608 write(fd, buf, strlen(buf));
1609 snprintf(buf, sizeof(buf), "Finds %zu/%zu\n", d->finds,
1610 d->find_collisions);
1611 write(fd, buf, strlen(buf));
1612 snprintf(buf, sizeof(buf), "Inserts %zu/%zu\n", d->inserts,
1613 d->insert_collisions);
1614 write(fd, buf, strlen(buf));
1615 snprintf(buf, sizeof(buf), "Deletes %zu/%zu\n", d->deletes,
1616 d->delete_moves);
1617 write(fd, buf, strlen(buf));
1618 snprintf(buf, sizeof(buf), "Cheap reallocs %zu/%zu\n",
1619 d->cheap_reallocs, d->cheap_realloc_tries);
1620 write(fd, buf, strlen(buf));
1621 dump_free_chunk_info(fd, d);
1622 dump_free_page_info(fd, d);
1623 snprintf(buf, sizeof(buf),
1624 "slot) hash d type page f size [free/n]\n");
1625 write(fd, buf, strlen(buf));
1626 for (i = 0; i < d->regions_total; i++) {
1627 if (d->r[i].p != NULL) {
1628 size_t h = hash(d->r[i].p) &
1629 (d->regions_total - 1);
1630 snprintf(buf, sizeof(buf), "%4zx) #%4zx %zd ",
1631 i, h, h - i);
1632 write(fd, buf, strlen(buf));
1633 REALSIZE(realsize, &d->r[i]);
1634 if (realsize > MALLOC_MAXCHUNK) {
1635 putleakinfo(d->r[i].f, realsize, 1);
1636 snprintf(buf, sizeof(buf),
1637 "pages %12p %12p %zu\n", d->r[i].p,
1638 d->r[i].f, realsize);
1639 write(fd, buf, strlen(buf));
1640 } else
1641 dump_chunk(fd,
1642 (struct chunk_info *)d->r[i].size,
1643 d->r[i].f, 0);
1644 }
1645 }
1646 snprintf(buf, sizeof(buf), "In use %zu\n", malloc_used);
1647 write(fd, buf, strlen(buf));
1648 snprintf(buf, sizeof(buf), "Guarded %zu\n", malloc_guarded);
1649 write(fd, buf, strlen(buf));
1650 dump_leaks(fd);
1651 write(fd, "\n", 1);
1652}
1653
1654void
1655malloc_dump(int fd)
1656{
1657 int i;
1658 void *p;
1659 struct region_info *r;
1660 int saved_errno = errno;
1661
1662 for (i = 0; i <= MALLOC_DELAYED_CHUNKS; i++) {
1663 p = g_pool->delayed_chunks[i];
1664 if (p == NULL)
1665 continue;
1666 r = find(g_pool, p);
1667 if (r == NULL)
1668 wrterror("bogus pointer in malloc_dump", p);
1669 free_bytes(g_pool, r, p);
1670 g_pool->delayed_chunks[i] = NULL;
1671 }
1672 /* XXX leak when run multiple times */
1673 RB_INIT(&leakhead);
1674 malloc_dump1(fd, g_pool);
1675 errno = saved_errno;
1676}
1677
1678static void
1679malloc_exit(void)
1680{
1681 static const char q[] = "malloc() warning: Couldn't dump stats\n";
1682 int save_errno = errno, fd;
1683
1684 fd = open("malloc.out", O_RDWR|O_APPEND);
1685 if (fd != -1) {
1686 malloc_dump(fd);
1687 close(fd);
1688 } else
1689 write(STDERR_FILENO, q, sizeof(q) - 1);
1690 errno = save_errno;
1691}
1692
1693#endif /* MALLOC_STATS */
diff --git a/src/lib/libc/stdlib/merge.c b/src/lib/libc/stdlib/merge.c
index 381fdc0830..43ef8b08e2 100644
--- a/src/lib/libc/stdlib/merge.c
+++ b/src/lib/libc/stdlib/merge.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: merge.c,v 1.9 2011/03/06 00:55:38 deraadt Exp $ */
1/*- 2/*-
2 * Copyright (c) 1992, 1993 3 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved. 4 * The Regents of the University of California. All rights reserved.
@@ -13,11 +14,7 @@
13 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software 17 * 3. Neither the name of the University nor the names of its contributors
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software 18 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission. 19 * without specific prior written permission.
23 * 20 *
@@ -34,11 +31,6 @@
34 * SUCH DAMAGE. 31 * SUCH DAMAGE.
35 */ 32 */
36 33
37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char sccsid[] = "from: @(#)merge.c 8.2 (Berkeley) 2/14/94";*/
39static char *rcsid = "$Id: merge.c,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */
41
42/* 34/*
43 * Hybrid exponential search/linear search merge sort with hybrid 35 * Hybrid exponential search/linear search merge sort with hybrid
44 * natural/pairwise first pass. Requires about .3% more comparisons 36 * natural/pairwise first pass. Requires about .3% more comparisons
@@ -59,8 +51,8 @@ static char *rcsid = "$Id: merge.c,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $";
59#include <stdlib.h> 51#include <stdlib.h>
60#include <string.h> 52#include <string.h>
61 53
62static void setup __P((u_char *, u_char *, size_t, size_t, int (*)())); 54static void setup(u_char *, u_char *, size_t, size_t, int (*)());
63static void insertionsort __P((u_char *, size_t, size_t, int (*)())); 55static void insertionsort(u_char *, size_t, size_t, int (*)());
64 56
65#define ISIZE sizeof(int) 57#define ISIZE sizeof(int)
66#define PSIZE sizeof(u_char *) 58#define PSIZE sizeof(u_char *)
@@ -96,15 +88,12 @@ static void insertionsort __P((u_char *, size_t, size_t, int (*)()));
96 * Arguments are as for qsort. 88 * Arguments are as for qsort.
97 */ 89 */
98int 90int
99mergesort(base, nmemb, size, cmp) 91mergesort(void *base, size_t nmemb, size_t size,
100 void *base; 92 int (*cmp)(const void *, const void *))
101 size_t nmemb;
102 register size_t size;
103 int (*cmp) __P((const void *, const void *));
104{ 93{
105 register int i, sense; 94 int i, sense;
106 int big, iflag; 95 int big, iflag;
107 register u_char *f1, *f2, *t, *b, *tp2, *q, *l1, *l2; 96 u_char *f1, *f2, *t, *b, *tp2, *q, *l1, *l2;
108 u_char *list2, *list1, *p2, *p, *last, **p1; 97 u_char *list2, *list1, *p2, *p, *last, **p1;
109 98
110 if (size < PSIZE / 2) { /* Pointers must fit into 2 * size. */ 99 if (size < PSIZE / 2) { /* Pointers must fit into 2 * size. */
@@ -148,7 +137,7 @@ mergesort(base, nmemb, size, cmp)
148 sense = 0; 137 sense = 0;
149 } 138 }
150 if (!big) { /* here i = 0 */ 139 if (!big) { /* here i = 0 */
151LINEAR: while ((b += size) < t && cmp(q, b) >sense) 140 while ((b += size) < t && cmp(q, b) >sense)
152 if (++i == 6) { 141 if (++i == 6) {
153 big = 1; 142 big = 1;
154 goto EXPONENTIAL; 143 goto EXPONENTIAL;
@@ -169,7 +158,7 @@ EXPONENTIAL: for (i = size; ; i <<= 1)
169 goto FASTCASE; 158 goto FASTCASE;
170 } else 159 } else
171 b = p; 160 b = p;
172SLOWCASE: while (t > b+size) { 161 while (t > b+size) {
173 i = (((t - b) / size) >> 1) * size; 162 i = (((t - b) / size) >> 1) * size;
174 if ((*cmp)(q, p = b + i) <= sense) 163 if ((*cmp)(q, p = b + i) <= sense)
175 t = p; 164 t = p;
@@ -256,13 +245,11 @@ COPY: b = t;
256 * is defined. Otherwise simple pairwise merging is used.) 245 * is defined. Otherwise simple pairwise merging is used.)
257 */ 246 */
258void 247void
259setup(list1, list2, n, size, cmp) 248setup(u_char *list1, u_char *list2, size_t n, size_t size,
260 size_t n, size; 249 int (*cmp)(const void *, const void *))
261 int (*cmp) __P((const void *, const void *));
262 u_char *list1, *list2;
263{ 250{
264 int i, length, size2, tmp, sense; 251 int i, length, size2, sense;
265 u_char *f1, *f2, *s, *l2, *last, *p2; 252 u_char tmp, *f1, *f2, *s, *l2, *last, *p2;
266 253
267 size2 = size*2; 254 size2 = size*2;
268 if (n <= 5) { 255 if (n <= 5) {
@@ -330,10 +317,8 @@ setup(list1, list2, n, size, cmp)
330 * last 4 elements. 317 * last 4 elements.
331 */ 318 */
332static void 319static void
333insertionsort(a, n, size, cmp) 320insertionsort(u_char *a, size_t n, size_t size,
334 u_char *a; 321 int (*cmp)(const void *, const void *))
335 size_t n, size;
336 int (*cmp) __P((const void *, const void *));
337{ 322{
338 u_char *ai, *s, *t, *u, tmp; 323 u_char *ai, *s, *t, *u, tmp;
339 int i; 324 int i;
diff --git a/src/lib/libc/stdlib/mrand48.c b/src/lib/libc/stdlib/mrand48.c
index 43356e66b3..977264aba5 100644
--- a/src/lib/libc/stdlib/mrand48.c
+++ b/src/lib/libc/stdlib/mrand48.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: mrand48.c,v 1.3 2005/08/08 08:05:37 espie Exp $ */
1/* 2/*
2 * Copyright (c) 1993 Martin Birgmeier 3 * Copyright (c) 1993 Martin Birgmeier
3 * All rights reserved. 4 * All rights reserved.
diff --git a/src/lib/libc/stdlib/multibyte.c b/src/lib/libc/stdlib/multibyte.c
deleted file mode 100644
index fe1cd5781b..0000000000
--- a/src/lib/libc/stdlib/multibyte.c
+++ /dev/null
@@ -1,131 +0,0 @@
1/*
2 * Copyright (c) 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. 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#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)multibyte.c 5.1 (Berkeley) 2/18/91";*/
36static char *rcsid = "$Id: multibyte.c,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */
38
39#include <stdlib.h>
40
41/*
42 * Stub multibyte character functions.
43 * This cheezy implementation is fixed to the native single-byte
44 * character set.
45 */
46
47int
48mblen(s, n)
49 const char *s;
50 size_t n;
51{
52 if (s == NULL || *s == '\0')
53 return 0;
54 if (n == 0)
55 return -1;
56 return 1;
57}
58
59/*ARGSUSED*/
60int
61mbtowc(pwc, s, n)
62 wchar_t *pwc;
63 const char *s;
64 size_t n;
65{
66 if (s == NULL)
67 return 0;
68 if (n == 0)
69 return -1;
70 if (pwc)
71 *pwc = (wchar_t) *s;
72 return (*s != '\0');
73}
74
75/*ARGSUSED*/
76int
77#ifdef __STDC__
78wctomb(char *s, wchar_t wchar)
79#else
80wctomb(s, wchar)
81 char *s;
82 wchar_t wchar;
83#endif
84{
85 if (s == NULL)
86 return 0;
87
88 *s = (char) wchar;
89 return 1;
90}
91
92/*ARGSUSED*/
93size_t
94mbstowcs(pwcs, s, n)
95 wchar_t *pwcs;
96 const char *s;
97 size_t n;
98{
99 int count = 0;
100
101 if (n != 0) {
102 do {
103 if ((*pwcs++ = (wchar_t) *s++) == 0)
104 break;
105 count++;
106 } while (--n != 0);
107 }
108
109 return count;
110}
111
112/*ARGSUSED*/
113size_t
114wcstombs(s, pwcs, n)
115 char *s;
116 const wchar_t *pwcs;
117 size_t n;
118{
119 int count = 0;
120
121 if (n != 0) {
122 do {
123 if ((*s++ = (char) *pwcs++) == 0)
124 break;
125 count++;
126 } while (--n != 0);
127 }
128
129 return count;
130}
131
diff --git a/src/lib/libc/stdlib/nrand48.c b/src/lib/libc/stdlib/nrand48.c
index 63f839cb05..f1f548c3af 100644
--- a/src/lib/libc/stdlib/nrand48.c
+++ b/src/lib/libc/stdlib/nrand48.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: nrand48.c,v 1.3 2005/08/08 08:05:37 espie Exp $ */
1/* 2/*
2 * Copyright (c) 1993 Martin Birgmeier 3 * Copyright (c) 1993 Martin Birgmeier
3 * All rights reserved. 4 * All rights reserved.
diff --git a/src/lib/libc/stdlib/posix_memalign.3 b/src/lib/libc/stdlib/posix_memalign.3
new file mode 100644
index 0000000000..46b74af7be
--- /dev/null
+++ b/src/lib/libc/stdlib/posix_memalign.3
@@ -0,0 +1,94 @@
1.\" $OpenBSD: posix_memalign.3,v 1.2 2010/05/19 06:32:43 jmc Exp $
2.\" Copyright (C) 2006 Jason Evans <jasone@FreeBSD.org>.
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(s), this list of conditions and the following disclaimer as
10.\" the first lines of this file unmodified other than the possible
11.\" addition of one or more copyright notices.
12.\" 2. Redistributions in binary form must reproduce the above copyright
13.\" notice(s), this list of conditions and the following disclaimer in
14.\" the documentation and/or other materials provided with the
15.\" distribution.
16.\"
17.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
18.\" EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
21.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24.\" BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26.\" OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27.\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28.\"
29.\" $FreeBSD: src/lib/libc/stdlib/posix_memalign.3,v 1.3 2007/03/28 04:32:51 jasone Exp $
30.\"
31.Dd $Mdocdate: May 19 2010 $
32.Dt POSIX_MEMALIGN 3
33.Os
34.Sh NAME
35.Nm posix_memalign
36.Nd aligned memory allocation
37.Sh SYNOPSIS
38.In stdlib.h
39.Ft int
40.Fn posix_memalign "void **ptr" "size_t alignment" "size_t size"
41.Sh DESCRIPTION
42The
43.Fn posix_memalign
44function allocates
45.Fa size
46bytes of memory such that the allocation's base address is a multiple of
47.Fa alignment ,
48and returns the allocation in the value pointed to by
49.Fa ptr .
50.Pp
51The requested
52.Fa alignment
53must be a power of 2 at least as large as
54.Fn sizeof "void *" .
55.Pp
56Memory that is allocated via
57.Fn posix_memalign
58can be used as an argument in subsequent calls to
59.Xr realloc 3
60and
61.Xr free 3 .
62.Sh RETURN VALUES
63The
64.Fn posix_memalign
65function returns the value 0 if successful; otherwise it returns an error value.
66.Sh ERRORS
67The
68.Fn posix_memalign
69function will fail if:
70.Bl -tag -width Er
71.It Bq Er EINVAL
72The
73.Fa alignment
74parameter is not a power of 2 at least as large as
75.Fn sizeof "void *" .
76.It Bq Er ENOMEM
77Memory allocation error.
78.El
79.Sh SEE ALSO
80.Xr free 3 ,
81.Xr malloc 3 ,
82.Xr realloc 3
83.Sh STANDARDS
84The
85.Fn posix_memalign
86function conforms to
87.St -p1003.1-2001 .
88.Sh HISTORY
89The
90.Fn posix_memalign
91function first appeared in
92.Ox 4.8 .
93.Sh BUGS
94Only alignments up to the page size can be specified.
diff --git a/src/lib/libc/stdlib/qabs.3 b/src/lib/libc/stdlib/qabs.3
index cb1e052191..b12dc59276 100644
--- a/src/lib/libc/stdlib/qabs.3
+++ b/src/lib/libc/stdlib/qabs.3
@@ -13,11 +13,7 @@
13.\" 2. Redistributions in binary form must reproduce the above copyright 13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the 14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution. 15.\" documentation and/or other materials provided with the distribution.
16.\" 3. All advertising materials mentioning features or use of this software 16.\" 3. Neither the name of the University nor the names of its contributors
17.\" must display the following acknowledgement:
18.\" This product includes software developed by the University of
19.\" California, Berkeley and its contributors.
20.\" 4. Neither the name of the University nor the names of its contributors
21.\" may be used to endorse or promote products derived from this software 17.\" may be used to endorse or promote products derived from this software
22.\" without specific prior written permission. 18.\" without specific prior written permission.
23.\" 19.\"
@@ -33,10 +29,9 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
35.\" 31.\"
36.\" from: @(#)labs.3 5.3 (Berkeley) 6/29/91 32.\" $OpenBSD: qabs.3,v 1.12 2011/07/07 13:30:28 jmc Exp $
37.\" $Id: qabs.3,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $
38.\" 33.\"
39.Dd June 29, 1991 34.Dd $Mdocdate: July 7 2011 $
40.Dt QABS 3 35.Dt QABS 3
41.Os 36.Os
42.Sh NAME 37.Sh NAME
@@ -49,14 +44,13 @@
49.Sh DESCRIPTION 44.Sh DESCRIPTION
50The 45The
51.Fn qabs 46.Fn qabs
52function 47function returns the absolute value of the quad integer
53returns the absolute value of the quad integer 48.Fa j .
54.Ar j .
55.Sh SEE ALSO 49.Sh SEE ALSO
56.Xr abs 3 , 50.Xr abs 3 ,
57.Xr labs 3 ,
58.Xr floor 3 ,
59.Xr cabs 3 , 51.Xr cabs 3 ,
60.Xr math 3 52.Xr floor 3 ,
53.Xr imaxabs 3 ,
54.Xr labs 3
61.Sh BUGS 55.Sh BUGS
62The absolute value of the most negative integer remains negative. 56The absolute value of the most negative integer remains negative.
diff --git a/src/lib/libc/stdlib/qabs.c b/src/lib/libc/stdlib/qabs.c
index 9c51a8baa9..656b93c822 100644
--- a/src/lib/libc/stdlib/qabs.c
+++ b/src/lib/libc/stdlib/qabs.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: qabs.c,v 1.5 2005/08/08 08:05:37 espie Exp $ */
1/*- 2/*-
2 * Copyright (c) 1990 The Regents of the University of California. 3 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved. 4 * All rights reserved.
@@ -10,11 +11,7 @@
10 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. 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 15 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission. 16 * without specific prior written permission.
20 * 17 *
@@ -31,16 +28,10 @@
31 * SUCH DAMAGE. 28 * SUCH DAMAGE.
32 */ 29 */
33 30
34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)labs.c 5.2 (Berkeley) 5/17/90";*/
36static char *rcsid = "$Id: qabs.c,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */
38
39#include <stdlib.h> 31#include <stdlib.h>
40 32
41quad_t 33quad_t
42qabs(j) 34qabs(quad_t j)
43 quad_t j;
44{ 35{
45 return(j < 0 ? -j : j); 36 return(j < 0 ? -j : j);
46} 37}
diff --git a/src/lib/libc/stdlib/qdiv.3 b/src/lib/libc/stdlib/qdiv.3
index 0efcfc96ef..94e3bdffb6 100644
--- a/src/lib/libc/stdlib/qdiv.3
+++ b/src/lib/libc/stdlib/qdiv.3
@@ -13,11 +13,7 @@
13.\" 2. Redistributions in binary form must reproduce the above copyright 13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the 14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution. 15.\" documentation and/or other materials provided with the distribution.
16.\" 3. All advertising materials mentioning features or use of this software 16.\" 3. Neither the name of the University nor the names of its contributors
17.\" must display the following acknowledgement:
18.\" This product includes software developed by the University of
19.\" California, Berkeley and its contributors.
20.\" 4. Neither the name of the University nor the names of its contributors
21.\" may be used to endorse or promote products derived from this software 17.\" may be used to endorse or promote products derived from this software
22.\" without specific prior written permission. 18.\" without specific prior written permission.
23.\" 19.\"
@@ -33,10 +29,9 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
35.\" 31.\"
36.\" from: @(#)qdiv.3 5.3 (Berkeley) 6/29/91 32.\" $OpenBSD: qdiv.3,v 1.9 2011/07/07 13:30:28 jmc Exp $
37.\" $Id: qdiv.3,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $
38.\" 33.\"
39.Dd June 29, 1991 34.Dd $Mdocdate: July 7 2011 $
40.Dt QDIV 3 35.Dt QDIV 3
41.Os 36.Os
42.Sh NAME 37.Sh NAME
@@ -49,18 +44,18 @@
49.Sh DESCRIPTION 44.Sh DESCRIPTION
50The 45The
51.Fn qdiv 46.Fn qdiv
52function 47function computes the value
53computes the value 48.Fa num Ns / Ns Fa denom
54.Ar num/denom
55and returns the quotient and remainder in a structure named 49and returns the quotient and remainder in a structure named
56.Ar qdiv_t 50.Li qdiv_t
57that contains two 51that contains two
58.Em quad integer 52.Li quad integer
59members named 53members named
60.Ar quot 54.Fa quot
61and 55and
62.Ar rem . 56.Fa rem .
63.Sh SEE ALSO 57.Sh SEE ALSO
64.Xr div 3 , 58.Xr div 3 ,
59.Xr imaxdiv 3 ,
65.Xr ldiv 3 , 60.Xr ldiv 3 ,
66.Xr math 3 61.Xr lldiv 3
diff --git a/src/lib/libc/stdlib/qdiv.c b/src/lib/libc/stdlib/qdiv.c
index 8f8e3f89c4..f3db0915ed 100644
--- a/src/lib/libc/stdlib/qdiv.c
+++ b/src/lib/libc/stdlib/qdiv.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: qdiv.c,v 1.5 2005/08/08 08:05:37 espie Exp $ */
1/* 2/*
2 * Copyright (c) 1990 Regents of the University of California. 3 * Copyright (c) 1990 Regents of the University of California.
3 * All rights reserved. 4 * All rights reserved.
@@ -13,11 +14,7 @@
13 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software 17 * 3. Neither the name of the University nor the names of its contributors
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software 18 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission. 19 * without specific prior written permission.
23 * 20 *
@@ -34,16 +31,10 @@
34 * SUCH DAMAGE. 31 * SUCH DAMAGE.
35 */ 32 */
36 33
37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char *sccsid = "from: @(#)ldiv.c 5.2 (Berkeley) 4/16/91";*/
39static char *rcsid = "$Id: qdiv.c,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */
41
42#include <stdlib.h> /* qdiv_t */ 34#include <stdlib.h> /* qdiv_t */
43 35
44qdiv_t 36qdiv_t
45qdiv(num, denom) 37qdiv(quad_t num, quad_t denom)
46 quad_t num, denom;
47{ 38{
48 qdiv_t r; 39 qdiv_t r;
49 40
diff --git a/src/lib/libc/stdlib/qsort.3 b/src/lib/libc/stdlib/qsort.3
index eb122cde12..92c75d5365 100644
--- a/src/lib/libc/stdlib/qsort.3
+++ b/src/lib/libc/stdlib/qsort.3
@@ -13,11 +13,7 @@
13.\" 2. Redistributions in binary form must reproduce the above copyright 13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the 14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution. 15.\" documentation and/or other materials provided with the distribution.
16.\" 3. All advertising materials mentioning features or use of this software 16.\" 3. Neither the name of the University nor the names of its contributors
17.\" must display the following acknowledgement:
18.\" This product includes software developed by the University of
19.\" California, Berkeley and its contributors.
20.\" 4. Neither the name of the University nor the names of its contributors
21.\" may be used to endorse or promote products derived from this software 17.\" may be used to endorse or promote products derived from this software
22.\" without specific prior written permission. 18.\" without specific prior written permission.
23.\" 19.\"
@@ -33,14 +29,15 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
35.\" 31.\"
36.\" from: @(#)qsort.3 8.1 (Berkeley) 6/4/93 32.\" $OpenBSD: qsort.3,v 1.15 2007/05/31 19:19:31 jmc Exp $
37.\" $Id: qsort.3,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $
38.\" 33.\"
39.Dd June 4, 1993 34.Dd $Mdocdate: May 31 2007 $
40.Dt QSORT 3 35.Dt QSORT 3
41.Os 36.Os
42.Sh NAME 37.Sh NAME
43.Nm qsort, heapsort, mergesort 38.Nm qsort ,
39.Nm heapsort ,
40.Nm mergesort
44.Nd sort functions 41.Nd sort functions
45.Sh SYNOPSIS 42.Sh SYNOPSIS
46.Fd #include <stdlib.h> 43.Fd #include <stdlib.h>
@@ -72,7 +69,7 @@ objects, the initial member of which is pointed to by
72.Fa base . 69.Fa base .
73The size of each object is specified by 70The size of each object is specified by
74.Fa size . 71.Fa size .
75.Fn Mergesort 72.Fn mergesort
76behaves similarly, but 73behaves similarly, but
77.Em requires 74.Em requires
78that 75that
@@ -106,51 +103,49 @@ is stable.
106.Pp 103.Pp
107The 104The
108.Fn qsort 105.Fn qsort
109function is an implementation of C.A.R. Hoare's ``quicksort'' algorithm, 106function is an implementation of C.A.R. Hoare's
107.Dq quicksort
108algorithm,
110a variant of partition-exchange sorting; in particular, see D.E. Knuth's 109a variant of partition-exchange sorting; in particular, see D.E. Knuth's
111Algorithm Q. 110Algorithm Q.
112.Fn Qsort 111.Fn qsort
113takes O N lg N average time. 112takes O N lg N average time.
114This implementation uses median selection to avoid its 113This implementation uses median selection to avoid its
115O N**2 worst-case behavior. 114O N**2 worst-case behavior.
116.Pp 115.Pp
117The 116The
118.Fn heapsort 117.Fn heapsort
119function is an implementation of J.W.J. William's ``heapsort'' algorithm, 118function is an implementation of J.W.J. William's
119.Dq heapsort
120algorithm,
120a variant of selection sorting; in particular, see D.E. Knuth's Algorithm H. 121a variant of selection sorting; in particular, see D.E. Knuth's Algorithm H.
121.Fn Heapsort 122.Fn heapsort
122takes O N lg N worst-case time. 123takes O N lg N worst-case time.
123Its 124This implementation of
124.Em only 125.Fn heapsort
125advantage over 126is implemented without recursive function calls.
126.Fn qsort
127is that it uses almost no additional memory; while
128.Fn qsort
129does not allocate memory, it is implemented using recursion.
130.Pp 127.Pp
131The function 128The function
132.Fn mergesort 129.Fn mergesort
133requires additional memory of size 130requires additional memory of size
134.Fa nmemb * 131.Fa nmemb *
135.Fa size 132.Fa size
136bytes; it should be used only when space is not at a premium. 133bytes; it should be used only when space is not at a premium.
137.Fn Mergesort 134.Fn mergesort
138is optimized for data with pre-existing order; its worst case 135is optimized for data with pre-existing order; its worst case
139time is O N lg N; its best case is O N. 136time is O N lg N; its best case is O N.
140.Pp 137.Pp
141Normally, 138Normally,
142.Fn qsort 139.Fn qsort
143is faster than 140is faster than
144.Fn mergesort 141.Fn mergesort ,
145is faster than 142which is faster than
146.Fn heapsort . 143.Fn heapsort .
147Memory availability and pre-existing order in the data can make this 144Memory availability and pre-existing order in the data can make this untrue.
148untrue.
149.Sh RETURN VALUES 145.Sh RETURN VALUES
150The 146The
151.Fn qsort 147.Fn qsort
152function 148function returns no value.
153returns no value.
154.Pp 149.Pp
155Upon successful completion, 150Upon successful completion,
156.Fn heapsort 151.Fn heapsort
@@ -163,30 +158,25 @@ is set to indicate the error.
163.Sh ERRORS 158.Sh ERRORS
164The 159The
165.Fn heapsort 160.Fn heapsort
166function succeeds unless: 161and
162.Fn mergesort
163functions succeed unless:
167.Bl -tag -width Er 164.Bl -tag -width Er
168.It Bq Er EINVAL 165.It Bq Er EINVAL
169The 166The
170.Fa size 167.Fa size
171argument is zero, or, 168argument is zero, or the
172the
173.Fa size 169.Fa size
174argument to 170argument to
175.Fn mergesort 171.Fn mergesort
176is less than 172is less than
177.Dq "sizeof(void *) / 2" . 173.Dq "sizeof(void *) / 2" .
178.It Bq Er ENOMEM 174.It Bq Er ENOMEM
179.Fn Heapsort 175.Fn heapsort
180or 176or
181.Fn mergesort 177.Fn mergesort
182were unable to allocate memory. 178were unable to allocate memory.
183.El 179.El
184.Sh COMPATIBILITY
185Previous versions of
186.Fn qsort
187did not permit the comparison routine itself to call
188.Fn qsort 3 .
189This is no longer true.
190.Sh SEE ALSO 180.Sh SEE ALSO
191.Xr sort 1 , 181.Xr sort 1 ,
192.Xr radixsort 3 182.Xr radixsort 3
@@ -204,7 +194,7 @@ This is no longer true.
204.%T "Heapsort" 194.%T "Heapsort"
205.%J "Communications of the ACM" 195.%J "Communications of the ACM"
206.%V 7:1 196.%V 7:1
207.%P pp. 347-348 197.%P pp. 347\-348
208.Re 198.Re
209.Rs 199.Rs
210.%A Knuth, D.E. 200.%A Knuth, D.E.
@@ -212,23 +202,32 @@ This is no longer true.
212.%B "The Art of Computer Programming" 202.%B "The Art of Computer Programming"
213.%V Vol. 3 203.%V Vol. 3
214.%T "Sorting and Searching" 204.%T "Sorting and Searching"
215.%P pp. 114-123, 145-149 205.%P pp. 114\-123, 145\-149
216.Re 206.Re
217.Rs 207.Rs
218.%A Mcilroy, P.M. 208.%A McIlroy, P.M.
219.%T "Optimistic Sorting and Information Theoretic Complexity" 209.%T "Optimistic Sorting and Information Theoretic Complexity"
220.%J "Fourth Annual ACM-SIAM Symposium on Discrete Algorithms" 210.%J "Fourth Annual ACM-SIAM Symposium on Discrete Algorithms"
221.%V January 1992 211.%P pp. 467\-464
212.%D January 1993
222.Re 213.Re
223.Rs 214.Rs
224.%A Bentley, J.L. 215.%A Bentley, J.L.
216.%A McIlroy, M.D.
225.%T "Engineering a Sort Function" 217.%T "Engineering a Sort Function"
226.%J "bentley@research.att.com" 218.%J "Software \- Practice and Experience"
227.%V January 1992 219.%V Vol. 23(11)
220.%P pp. 1249\-1265
221.%D November 1993
228.Re 222.Re
229.Sh STANDARDS 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 230The
231.Fn qsort 231.Fn qsort
232function 232function conforms to
233conforms to
234.St -ansiC . 233.St -ansiC .
diff --git a/src/lib/libc/stdlib/qsort.c b/src/lib/libc/stdlib/qsort.c
index c06bd54054..f28449fb5b 100644
--- a/src/lib/libc/stdlib/qsort.c
+++ b/src/lib/libc/stdlib/qsort.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: qsort.c,v 1.11 2010/02/08 11:04:07 otto Exp $ */
1/*- 2/*-
2 * Copyright (c) 1992, 1993 3 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved. 4 * The Regents of the University of California. All rights reserved.
@@ -10,11 +11,7 @@
10 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. 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 15 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission. 16 * without specific prior written permission.
20 * 17 *
@@ -31,16 +28,11 @@
31 * SUCH DAMAGE. 28 * SUCH DAMAGE.
32 */ 29 */
33 30
34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char sccsid[] = "from: @(#)qsort.c 8.1 (Berkeley) 6/4/93";*/
36static char *rcsid = "$Id: qsort.c,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */
38
39#include <sys/types.h> 31#include <sys/types.h>
40#include <stdlib.h> 32#include <stdlib.h>
41 33
42static inline char *med3 __P((char *, char *, char *, int (*)())); 34static __inline char *med3(char *, char *, char *, int (*)(const void *, const void *));
43static inline void swapfunc __P((char *, char *, int, int)); 35static __inline void swapfunc(char *, char *, size_t, int);
44 36
45#define min(a, b) (a) < (b) ? a : b 37#define min(a, b) (a) < (b) ? a : b
46 38
@@ -48,11 +40,11 @@ static inline void swapfunc __P((char *, char *, int, int));
48 * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function". 40 * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
49 */ 41 */
50#define swapcode(TYPE, parmi, parmj, n) { \ 42#define swapcode(TYPE, parmi, parmj, n) { \
51 long i = (n) / sizeof (TYPE); \ 43 size_t i = (n) / sizeof (TYPE); \
52 register TYPE *pi = (TYPE *) (parmi); \ 44 TYPE *pi = (TYPE *) (parmi); \
53 register TYPE *pj = (TYPE *) (parmj); \ 45 TYPE *pj = (TYPE *) (parmj); \
54 do { \ 46 do { \
55 register TYPE t = *pi; \ 47 TYPE t = *pi; \
56 *pi++ = *pj; \ 48 *pi++ = *pj; \
57 *pj++ = t; \ 49 *pj++ = t; \
58 } while (--i > 0); \ 50 } while (--i > 0); \
@@ -61,12 +53,10 @@ static inline void swapfunc __P((char *, char *, int, int));
61#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \ 53#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
62 es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1; 54 es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
63 55
64static inline void 56static __inline void
65swapfunc(a, b, n, swaptype) 57swapfunc(char *a, char *b, size_t n, int swaptype)
66 char *a, *b;
67 int n, swaptype;
68{ 58{
69 if(swaptype <= 1) 59 if (swaptype <= 1)
70 swapcode(long, a, b, n) 60 swapcode(long, a, b, n)
71 else 61 else
72 swapcode(char, a, b, n) 62 swapcode(char, a, b, n)
@@ -82,10 +72,8 @@ swapfunc(a, b, n, swaptype)
82 72
83#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype) 73#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
84 74
85static inline char * 75static __inline char *
86med3(a, b, c, cmp) 76med3(char *a, char *b, char *c, int (*cmp)(const void *, const void *))
87 char *a, *b, *c;
88 int (*cmp)();
89{ 77{
90 return cmp(a, b) < 0 ? 78 return cmp(a, b) < 0 ?
91 (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a )) 79 (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))
@@ -93,27 +81,26 @@ med3(a, b, c, cmp)
93} 81}
94 82
95void 83void
96qsort(a, n, es, cmp) 84qsort(void *aa, size_t n, size_t es, int (*cmp)(const void *, const void *))
97 void *a;
98 size_t n, es;
99 int (*cmp)();
100{ 85{
101 char *pa, *pb, *pc, *pd, *pl, *pm, *pn; 86 char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
102 int d, r, swaptype, swap_cnt; 87 int cmp_result, swaptype, swap_cnt;
88 size_t d, r;
89 char *a = aa;
103 90
104loop: SWAPINIT(a, es); 91loop: SWAPINIT(a, es);
105 swap_cnt = 0; 92 swap_cnt = 0;
106 if (n < 7) { 93 if (n < 7) {
107 for (pm = a + es; pm < (char *) a + n * es; pm += es) 94 for (pm = (char *)a + es; pm < (char *) a + n * es; pm += es)
108 for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; 95 for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
109 pl -= es) 96 pl -= es)
110 swap(pl, pl - es); 97 swap(pl, pl - es);
111 return; 98 return;
112 } 99 }
113 pm = a + (n / 2) * es; 100 pm = (char *)a + (n / 2) * es;
114 if (n > 7) { 101 if (n > 7) {
115 pl = a; 102 pl = (char *)a;
116 pn = a + (n - 1) * es; 103 pn = (char *)a + (n - 1) * es;
117 if (n > 40) { 104 if (n > 40) {
118 d = (n / 8) * es; 105 d = (n / 8) * es;
119 pl = med3(pl, pl + d, pl + 2 * d, cmp); 106 pl = med3(pl, pl + d, pl + 2 * d, cmp);
@@ -123,20 +110,20 @@ loop: SWAPINIT(a, es);
123 pm = med3(pl, pm, pn, cmp); 110 pm = med3(pl, pm, pn, cmp);
124 } 111 }
125 swap(a, pm); 112 swap(a, pm);
126 pa = pb = a + es; 113 pa = pb = (char *)a + es;
127 114
128 pc = pd = a + (n - 1) * es; 115 pc = pd = (char *)a + (n - 1) * es;
129 for (;;) { 116 for (;;) {
130 while (pb <= pc && (r = cmp(pb, a)) <= 0) { 117 while (pb <= pc && (cmp_result = cmp(pb, a)) <= 0) {
131 if (r == 0) { 118 if (cmp_result == 0) {
132 swap_cnt = 1; 119 swap_cnt = 1;
133 swap(pa, pb); 120 swap(pa, pb);
134 pa += es; 121 pa += es;
135 } 122 }
136 pb += es; 123 pb += es;
137 } 124 }
138 while (pb <= pc && (r = cmp(pc, a)) >= 0) { 125 while (pb <= pc && (cmp_result = cmp(pc, a)) >= 0) {
139 if (r == 0) { 126 if (cmp_result == 0) {
140 swap_cnt = 1; 127 swap_cnt = 1;
141 swap(pc, pd); 128 swap(pc, pd);
142 pd -= es; 129 pd -= es;
@@ -151,14 +138,14 @@ loop: SWAPINIT(a, es);
151 pc -= es; 138 pc -= es;
152 } 139 }
153 if (swap_cnt == 0) { /* Switch to insertion sort */ 140 if (swap_cnt == 0) { /* Switch to insertion sort */
154 for (pm = a + es; pm < (char *) a + n * es; pm += es) 141 for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
155 for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0; 142 for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
156 pl -= es) 143 pl -= es)
157 swap(pl, pl - es); 144 swap(pl, pl - es);
158 return; 145 return;
159 } 146 }
160 147
161 pn = a + n * es; 148 pn = (char *)a + n * es;
162 r = min(pa - (char *)a, pb - pa); 149 r = min(pa - (char *)a, pb - pa);
163 vecswap(a, pb - r, r); 150 vecswap(a, pb - r, r);
164 r = min(pd - pc, pn - pd - es); 151 r = min(pd - pc, pn - pd - es);
diff --git a/src/lib/libc/stdlib/radixsort.3 b/src/lib/libc/stdlib/radixsort.3
index a2af9f17a4..b90a557718 100644
--- a/src/lib/libc/stdlib/radixsort.3
+++ b/src/lib/libc/stdlib/radixsort.3
@@ -9,11 +9,7 @@
9.\" 2. Redistributions in binary form must reproduce the above copyright 9.\" 2. Redistributions in binary form must reproduce the above copyright
10.\" notice, this list of conditions and the following disclaimer in the 10.\" notice, this list of conditions and the following disclaimer in the
11.\" documentation and/or other materials provided with the distribution. 11.\" documentation and/or other materials provided with the distribution.
12.\" 3. All advertising materials mentioning features or use of this software 12.\" 3. Neither the name of the University nor the names of its contributors
13.\" must display the following acknowledgement:
14.\" This product includes software developed by the University of
15.\" California, Berkeley and its contributors.
16.\" 4. 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 13.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission. 14.\" without specific prior written permission.
19.\" 15.\"
@@ -29,32 +25,33 @@
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE. 26.\" SUCH DAMAGE.
31.\" 27.\"
32.\" from: @(#)radixsort.3 8.2 (Berkeley) 1/27/94 28.\" $OpenBSD: radixsort.3,v 1.11 2007/05/31 19:19:31 jmc Exp $
33.\" $Id: radixsort.3,v 1.1.1.1 1995/10/18 08:42:18 deraadt Exp $
34.\" 29.\"
35.Dd January 27, 1994 30.Dd $Mdocdate: May 31 2007 $
36.Dt RADIXSORT 3 31.Dt RADIXSORT 3
37.Os 32.Os
38.Sh NAME 33.Sh NAME
39.Nm radixsort 34.Nm radixsort ,
35.Nm sradixsort
40.Nd radix sort 36.Nd radix sort
41.Sh SYNOPSIS 37.Sh SYNOPSIS
42.Fd #include <limits.h> 38.Fd #include <limits.h>
43.Fd #include <stdlib.h> 39.Fd #include <stdlib.h>
44.Ft int 40.Ft int
45.Fn radixsort "u_char **base" "int nmemb" "u_char *table" "u_int endbyte" 41.Fn radixsort "const u_char **base" "int nmemb" "const u_char *table" "u_int endbyte"
46.Ft int 42.Ft int
47.Fn sradixsort "u_char **base" "int nmemb" "u_char *table" "u_int endbyte" 43.Fn sradixsort "const u_char **base" "int nmemb" "const u_char *table" "u_int endbyte"
48.Sh DESCRIPTION 44.Sh DESCRIPTION
49The 45The
50.Fn radixsort 46.Fn radixsort
51and 47and
52.Fn sradixsort 48.Fn sradixsort
53functions 49functions are implementations of radix sort.
54are implementations of radix sort.
55.Pp 50.Pp
56These functions sort an array of pointers to byte strings, the initial 51These functions sort an array of
57member of which is referenced by 52.Fa nmemb
53pointers to byte strings.
54The initial member is referenced by
58.Fa base . 55.Fa base .
59The byte strings may contain any values; the end of each string 56The byte strings may contain any values; the end of each string
60is denoted by the user-specified value 57is denoted by the user-specified value
@@ -63,26 +60,24 @@ is denoted by the user-specified value
63Applications may specify a sort order by providing the 60Applications may specify a sort order by providing the
64.Fa table 61.Fa table
65argument. 62argument.
66If 63If non-null,
67.Pf non- Dv NULL ,
68.Fa table 64.Fa table
69must reference an array of 65must reference an array of
70.Dv UCHAR_MAX 66.Dv UCHAR_MAX
71+ 1 bytes which contains the sort 67+ 1 bytes which contains the sort weight of each possible byte value.
72weight of each possible byte value.
73The end-of-string byte must have a sort weight of 0 or 255 68The end-of-string byte must have a sort weight of 0 or 255
74(for sorting in reverse order). 69(for sorting in reverse order).
75More than one byte may have the same sort weight. 70More than one byte may have the same sort weight.
76The 71The
77.Fa table 72.Fa table
78argument 73argument is useful for applications which wish to sort different characters
79is useful for applications which wish to sort different characters 74equally; for example, providing a table with the same weights
80equally, for example, providing a table with the same weights 75for A\-Z as for a\-z will result in a case-insensitive sort.
81for A-Z as for a-z will result in a case-insensitive sort.
82If 76If
83.Fa table 77.Fa table
84is NULL, the contents of the array are sorted in ascending order 78is
85according to the 79.Dv NULL ,
80the contents of the array are sorted in ascending order according to the
86.Tn ASCII 81.Tn ASCII
87order of the byte strings they reference and 82order of the byte strings they reference and
88.Fa endbyte 83.Fa endbyte
@@ -90,7 +85,7 @@ has a sorting weight of 0.
90.Pp 85.Pp
91The 86The
92.Fn sradixsort 87.Fn sradixsort
93function is stable, that is, if two elements compare as equal, their 88function is stable; that is, if two elements compare as equal, their
94order in the sorted array is unchanged. 89order in the sorted array is unchanged.
95The 90The
96.Fn sradixsort 91.Fn sradixsort
@@ -107,7 +102,7 @@ particular, see D.E. Knuth's Algorithm R and section 5.2.5, exercise 10.
107They take linear time relative to the number of bytes in the strings. 102They take linear time relative to the number of bytes in the strings.
108.Sh RETURN VALUES 103.Sh RETURN VALUES
109Upon successful completion 0 is returned. 104Upon successful completion 0 is returned.
110Otherwise, \-1 is returned and the global variable 105Otherwise, \-1 is returned and the global variable
111.Va errno 106.Va errno
112is set to indicate the error. 107is set to indicate the error.
113.Sh ERRORS 108.Sh ERRORS
@@ -122,15 +117,13 @@ is not 0 or 255.
122.Pp 117.Pp
123Additionally, the 118Additionally, the
124.Fn sradixsort 119.Fn sradixsort
125function 120function may fail and set
126may fail and set
127.Va errno 121.Va errno
128for any of the errors specified for the library routine 122for any of the errors specified for the library routine
129.Xr malloc 3 . 123.Xr malloc 3 .
130.Sh SEE ALSO 124.Sh SEE ALSO
131.Xr sort 1 , 125.Xr sort 1 ,
132.Xr qsort 3 126.Xr qsort 3
133.Pp
134.Rs 127.Rs
135.%A Knuth, D.E. 128.%A Knuth, D.E.
136.%D 1968 129.%D 1968
@@ -158,4 +151,5 @@ for any of the errors specified for the library routine
158.Sh HISTORY 151.Sh HISTORY
159The 152The
160.Fn radixsort 153.Fn radixsort
161function first appeared in 4.4BSD. 154function first appeared in
155.Bx 4.4 .
diff --git a/src/lib/libc/stdlib/radixsort.c b/src/lib/libc/stdlib/radixsort.c
index dd51013c94..49d03b52d5 100644
--- a/src/lib/libc/stdlib/radixsort.c
+++ b/src/lib/libc/stdlib/radixsort.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: radixsort.c,v 1.9 2007/09/02 15:19:17 deraadt Exp $ */
1/*- 2/*-
2 * Copyright (c) 1990, 1993 3 * Copyright (c) 1990, 1993
3 * The Regents of the University of California. All rights reserved. 4 * The Regents of the University of California. All rights reserved.
@@ -13,11 +14,7 @@
13 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software 17 * 3. Neither the name of the University nor the names of its contributors
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software 18 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission. 19 * without specific prior written permission.
23 * 20 *
@@ -34,11 +31,6 @@
34 * SUCH DAMAGE. 31 * SUCH DAMAGE.
35 */ 32 */
36 33
37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char sccsid[] = "from: @(#)radixsort.c 8.1 (Berkeley) 6/4/93";*/
39static char *rcsid = "$Id: radixsort.c,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */
41
42/* 34/*
43 * Radixsort routines. 35 * Radixsort routines.
44 * 36 *
@@ -61,11 +53,11 @@ typedef struct {
61 int sn, si; 53 int sn, si;
62} stack; 54} stack;
63 55
64static inline void simplesort 56static __inline void simplesort
65 __P((const u_char **, int, int, const u_char *, u_int)); 57(const u_char **, int, int, const u_char *, u_int);
66static void r_sort_a __P((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);
67static void r_sort_b __P((const u_char **, 59static void r_sort_b(const u_char **,
68 const u_char **, int, int, const u_char *, u_int)); 60 const u_char **, int, int, const u_char *, u_int);
69 61
70#define THRESHOLD 20 /* Divert to simplesort(). */ 62#define THRESHOLD 20 /* Divert to simplesort(). */
71#define SIZE 512 /* Default stack size. */ 63#define SIZE 512 /* Default stack size. */
@@ -90,10 +82,7 @@ static void r_sort_b __P((const u_char **,
90} 82}
91 83
92int 84int
93radixsort(a, n, tab, endch) 85radixsort(const u_char **a, int n, const u_char *tab, u_int endch)
94 const u_char **a, *tab;
95 int n;
96 u_int endch;
97{ 86{
98 const u_char *tr; 87 const u_char *tr;
99 int c; 88 int c;
@@ -105,10 +94,7 @@ radixsort(a, n, tab, endch)
105} 94}
106 95
107int 96int
108sradixsort(a, n, tab, endch) 97sradixsort(const u_char **a, int n, const u_char *tab, u_int endch)
109 const u_char **a, *tab;
110 int n;
111 u_int endch;
112{ 98{
113 const u_char *tr, **ta; 99 const u_char *tr, **ta;
114 int c; 100 int c;
@@ -118,7 +104,7 @@ sradixsort(a, n, tab, endch)
118 if (n < THRESHOLD) 104 if (n < THRESHOLD)
119 simplesort(a, n, 0, tr, endch); 105 simplesort(a, n, 0, tr, endch);
120 else { 106 else {
121 if ((ta = malloc(n * sizeof(a))) == NULL) 107 if ((ta = calloc(n, sizeof(a))) == NULL)
122 return (-1); 108 return (-1);
123 r_sort_b(a, ta, n, 0, tr, endch); 109 r_sort_b(a, ta, n, 0, tr, endch);
124 free(ta); 110 free(ta);
@@ -133,15 +119,11 @@ sradixsort(a, n, tab, endch)
133 119
134/* Unstable, in-place sort. */ 120/* Unstable, in-place sort. */
135void 121void
136r_sort_a(a, n, i, tr, endch) 122r_sort_a(const u_char **a, int n, int i, const u_char *tr, u_int endch)
137 const u_char **a;
138 int n, i;
139 const u_char *tr;
140 u_int endch;
141{ 123{
142 static int count[256], nc, bmin; 124 static int count[256], nc, bmin;
143 register int c; 125 int c;
144 register const u_char **ak, *r; 126 const u_char **ak, *r;
145 stack s[SIZE], *sp, *sp0, *sp1, temp; 127 stack s[SIZE], *sp, *sp0, *sp1, temp;
146 int *cp, bigc; 128 int *cp, bigc;
147 const u_char **an, *t, **aj, **top[256]; 129 const u_char **an, *t, **aj, **top[256];
@@ -224,15 +206,12 @@ r_sort_a(a, n, i, tr, endch)
224 206
225/* Stable sort, requiring additional memory. */ 207/* Stable sort, requiring additional memory. */
226void 208void
227r_sort_b(a, ta, n, i, tr, endch) 209r_sort_b(const u_char **a, const u_char **ta, int n, int i, const u_char *tr,
228 const u_char **a, **ta; 210 u_int endch)
229 int n, i;
230 const u_char *tr;
231 u_int endch;
232{ 211{
233 static int count[256], nc, bmin; 212 static int count[256], nc, bmin;
234 register int c; 213 int c;
235 register const u_char **ak, **ai; 214 const u_char **ak, **ai;
236 stack s[512], *sp, *sp0, *sp1, temp; 215 stack s[512], *sp, *sp0, *sp1, temp;
237 const u_char **top[256]; 216 const u_char **top[256];
238 int *cp, bigc; 217 int *cp, bigc;
@@ -295,14 +274,11 @@ r_sort_b(a, ta, n, i, tr, endch)
295 } 274 }
296} 275}
297 276
298static inline void 277static __inline void
299simplesort(a, n, b, tr, endch) /* insertion sort */ 278simplesort(const u_char **a, int n, int b, const u_char *tr, u_int endch)
300 register const u_char **a; 279 /* insertion sort */
301 int n, b;
302 register const u_char *tr;
303 u_int endch;
304{ 280{
305 register u_char ch; 281 u_char ch;
306 const u_char **ak, **ai, *s, *t; 282 const u_char **ak, **ai, *s, *t;
307 283
308 for (ak = a+1; --n >= 1; ak++) 284 for (ak = a+1; --n >= 1; ak++)
diff --git a/src/lib/libc/stdlib/rand.3 b/src/lib/libc/stdlib/rand.3
index a0e7740e66..df4feaacdb 100644
--- a/src/lib/libc/stdlib/rand.3
+++ b/src/lib/libc/stdlib/rand.3
@@ -13,11 +13,7 @@
13.\" 2. Redistributions in binary form must reproduce the above copyright 13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the 14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution. 15.\" documentation and/or other materials provided with the distribution.
16.\" 3. All advertising materials mentioning features or use of this software 16.\" 3. Neither the name of the University nor the names of its contributors
17.\" must display the following acknowledgement:
18.\" This product includes software developed by the University of
19.\" California, Berkeley and its contributors.
20.\" 4. Neither the name of the University nor the names of its contributors
21.\" may be used to endorse or promote products derived from this software 17.\" may be used to endorse or promote products derived from this software
22.\" without specific prior written permission. 18.\" without specific prior written permission.
23.\" 19.\"
@@ -33,10 +29,9 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
35.\" 31.\"
36.\" from: @(#)rand.3 6.7 (Berkeley) 6/29/91 32.\" $OpenBSD: rand.3,v 1.10 2007/05/31 19:19:31 jmc Exp $
37.\" $Id: rand.3,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $
38.\" 33.\"
39.Dd June 29, 1991 34.Dd $Mdocdate: May 31 2007 $
40.Dt RAND 3 35.Dt RAND 3
41.Os 36.Os
42.Sh NAME 37.Sh NAME
@@ -46,12 +41,15 @@
46.Sh SYNOPSIS 41.Sh SYNOPSIS
47.Fd #include <stdlib.h> 42.Fd #include <stdlib.h>
48.Ft void 43.Ft void
49.Fn srand "unsigned seed" 44.Fn srand "unsigned int seed"
50.Ft int 45.Ft int
51.Fn rand void 46.Fn rand void
47.Ft int
48.Fn rand_r "unsigned int *seed"
52.Sh DESCRIPTION 49.Sh DESCRIPTION
53.Bf -symbolic 50.Bf -symbolic
54These interfaces are obsoleted by random(3). 51These interfaces are obsoleted by
52.Xr random 3 .
55.Ef 53.Ef
56.Pp 54.Pp
57The 55The
@@ -73,13 +71,28 @@ with the same seed value.
73.Pp 71.Pp
74If no seed value is provided, the functions are automatically 72If no seed value is provided, the functions are automatically
75seeded with a value of 1. 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.
76.Sh SEE ALSO 82.Sh SEE ALSO
83.Xr arc4random 3 ,
84.Xr rand48 3 ,
77.Xr random 3 85.Xr random 3
78.Sh STANDARDS 86.Sh STANDARDS
79The 87The
80.Fn rand 88.Fn rand
81and 89and
82.Fn srand 90.Fn srand
83functions 91functions conform to
84conform to
85.St -ansiC . 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
index 361d473448..0f9c100807 100644
--- a/src/lib/libc/stdlib/rand.c
+++ b/src/lib/libc/stdlib/rand.c
@@ -10,11 +10,7 @@
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the 11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution. 12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software 13 * 3. Neither the name of the University nor the names of its contributors
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. 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 14 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission. 15 * without specific prior written permission.
20 * 16 *
@@ -31,25 +27,26 @@
31 * SUCH DAMAGE. 27 * SUCH DAMAGE.
32 */ 28 */
33 29
34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)rand.c 5.6 (Berkeley) 6/24/91";*/
36static char *rcsid = "$Id: rand.c,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */
38
39#include <sys/types.h> 30#include <sys/types.h>
40#include <stdlib.h> 31#include <stdlib.h>
41 32
42static u_long next = 1; 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}
43 41
44int 42int
45rand() 43rand(void)
46{ 44{
47 return ((next = next * 1103515245 + 12345) % ((u_int)RAND_MAX + 1)); 45 return (rand_r(&next));
48} 46}
49 47
50void 48void
51srand(seed) 49srand(u_int seed)
52u_int seed;
53{ 50{
54 next = seed; 51 next = seed;
55} 52}
diff --git a/src/lib/libc/stdlib/rand48.3 b/src/lib/libc/stdlib/rand48.3
index 5a772c9a8c..0e8ca5389b 100644
--- a/src/lib/libc/stdlib/rand48.3
+++ b/src/lib/libc/stdlib/rand48.3
@@ -1,4 +1,4 @@
1\" Copyright (c) 1993 Martin Birgmeier 1.\" Copyright (c) 1993 Martin Birgmeier
2.\" All rights reserved. 2.\" All rights reserved.
3.\" 3.\"
4.\" You may redistribute unmodified or modified versions of this source 4.\" You may redistribute unmodified or modified versions of this source
@@ -9,9 +9,9 @@
9.\" of any kind. I shall in no event be liable for anything that happens 9.\" of any kind. I shall in no event be liable for anything that happens
10.\" to anyone/anything when using this software. 10.\" to anyone/anything when using this software.
11.\" 11.\"
12.\" $Id: rand48.3,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $ 12.\" $OpenBSD: rand48.3,v 1.11 2007/05/31 19:19:31 jmc Exp $
13.\" 13.\"
14.Dd October 8, 1993 14.Dd $Mdocdate: May 31 2007 $
15.Dt RAND48 3 15.Dt RAND48 3
16.Os 16.Os
17.Sh NAME 17.Sh NAME
@@ -24,10 +24,10 @@
24.Nm srand48 , 24.Nm srand48 ,
25.Nm seed48 , 25.Nm seed48 ,
26.Nm lcong48 26.Nm lcong48
27.Nd pseudo random number generators and initialization routines 27.Nd pseudo-random number generators and initialization routines
28.Sh SYNOPSIS 28.Sh SYNOPSIS
29.Fd #include <stdlib.h> 29.Fd #include <stdlib.h>
30.Ft double 30.Ft double
31.Fn drand48 void 31.Fn drand48 void
32.Ft double 32.Ft double
33.Fn erand48 "unsigned short xseed[3]" 33.Fn erand48 "unsigned short xseed[3]"
@@ -49,12 +49,13 @@
49The 49The
50.Fn rand48 50.Fn rand48
51family of functions generates pseudo-random numbers using a linear 51family of functions generates pseudo-random numbers using a linear
52congruential algorithm working on integers 48 bits in size. The 52congruential algorithm working on integers 48 bits in size.
53particular formula employed is 53The particular formula employed is
54r(n+1) = (a * r(n) + c) mod m 54r(n+1) = (a * r(n) + c) mod m
55where the default values are 55where the default values are
56for the multiplicand a = 0xfdeece66d = 25214903917 and 56for the multiplicand a = 0xfdeece66d = 25214903917 and
57the addend c = 0xb = 11. The modulus is always fixed at m = 2 ** 48. 57the addend c = 0xb = 11.
58The modulus is always fixed at m = 2 ** 48.
58r(n) is called the seed of the random number generator. 59r(n) is called the seed of the random number generator.
59.Pp 60.Pp
60For all the six generator routines described next, the first 61For all the six generator routines described next, the first
@@ -63,15 +64,17 @@ computational step is to perform a single iteration of the algorithm.
63.Fn drand48 64.Fn drand48
64and 65and
65.Fn erand48 66.Fn erand48
66return values of type double. The full 48 bits of r(n+1) are 67return values of type double.
68The full 48 bits of r(n+1) are
67loaded into the mantissa of the returned value, with the exponent set 69loaded into the mantissa of the returned value, with the exponent set
68such that the values produced lie in the interval [0.0, 1.0). 70such that the values produced lie in the interval [0.0, 1.0].
69.Pp 71.Pp
70.Fn lrand48 72.Fn lrand48
71and 73and
72.Fn nrand48 74.Fn nrand48
73return values of type long in the range 75return values of type long in the range
74[0, 2**31-1]. The high-order (31) bits of 76[0, 2**31-1].
77The high-order (31) bits of
75r(n+1) are loaded into the lower bits of the returned value, with 78r(n+1) are loaded into the lower bits of the returned value, with
76the topmost (sign) bit set to zero. 79the topmost (sign) bit set to zero.
77.Pp 80.Pp
@@ -79,14 +82,15 @@ the topmost (sign) bit set to zero.
79and 82and
80.Fn jrand48 83.Fn jrand48
81return values of type long in the range 84return values of type long in the range
82[-2**31, 2**31-1]. The high-order (32) bits of 85[-2**31, 2**31-1].
83r(n+1) are loaded into the returned value. 86The high-order (32) bits of r(n+1) are loaded into the returned value.
84.Pp 87.Pp
85.Fn drand48 , 88.Fn drand48 ,
86.Fn lrand48 , 89.Fn lrand48 ,
87and 90and
88.Fn mrand48 91.Fn mrand48
89use an internal buffer to store r(n). For these functions 92use an internal buffer to store r(n).
93For these functions
90the initial value of r(0) = 0x1234abcd330e = 20017429951246. 94the initial value of r(0) = 0x1234abcd330e = 20017429951246.
91.Pp 95.Pp
92On the other hand, 96On the other hand,
@@ -118,12 +122,12 @@ also initializes the internal buffer r(n) of
118and 122and
119.Fn mrand48 , 123.Fn mrand48 ,
120but here all 48 bits of the seed can be specified in an array of 3 shorts, 124but here all 48 bits of the seed can be specified in an array of 3 shorts,
121where the zeroth member specifies the lowest bits. Again, 125where the zeroth member specifies the lowest bits.
122the constant multiplicand and addend of the algorithm are 126Again, the constant multiplicand and addend of the algorithm are
123reset to the default values given above. 127reset to the default values given above.
124.Fn seed48 128.Fn seed48
125returns a pointer to an array of 3 shorts which contains the old seed. 129returns a pointer to an array of 3 shorts which contains the old seed.
126This array is statically allocated, thus its contents are lost after 130This array is statically allocated, so its contents are lost after
127each new call to 131each new call to
128.Fn seed48 . 132.Fn seed48 .
129.Pp 133.Pp
@@ -152,9 +156,10 @@ always also set the multiplicand and addend for any of the six
152generator calls. 156generator calls.
153.Pp 157.Pp
154For a more powerful random number generator, see 158For a more powerful random number generator, see
155.Xr random 3 159.Xr random 3 .
156.Sh AUTHOR
157Martin Birgmeier
158.Sh SEE ALSO 160.Sh SEE ALSO
161.Xr arc4random 3 ,
159.Xr rand 3 , 162.Xr rand 3 ,
160.Xr random 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
index 12496d1c8c..afa49f65f3 100644
--- a/src/lib/libc/stdlib/rand48.h
+++ b/src/lib/libc/stdlib/rand48.h
@@ -9,6 +9,8 @@
9 * This software is provided ``as is'', and comes with no warranties 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 10 * of any kind. I shall in no event be liable for anything that happens
11 * to anyone/anything when using this software. 11 * to anyone/anything when using this software.
12 *
13 * $OpenBSD: rand48.h,v 1.3 2002/02/16 21:27:24 millert Exp $
12 */ 14 */
13 15
14#ifndef _RAND48_H_ 16#ifndef _RAND48_H_
@@ -17,7 +19,7 @@
17#include <math.h> 19#include <math.h>
18#include <stdlib.h> 20#include <stdlib.h>
19 21
20void __dorand48 __P((unsigned short[3])); 22void __dorand48(unsigned short[3]);
21 23
22#define RAND48_SEED_0 (0x330e) 24#define RAND48_SEED_0 (0x330e)
23#define RAND48_SEED_1 (0xabcd) 25#define RAND48_SEED_1 (0xabcd)
diff --git a/src/lib/libc/stdlib/random.3 b/src/lib/libc/stdlib/random.3
index 38c15a9803..ed05df162b 100644
--- a/src/lib/libc/stdlib/random.3
+++ b/src/lib/libc/stdlib/random.3
@@ -9,11 +9,7 @@
9.\" 2. Redistributions in binary form must reproduce the above copyright 9.\" 2. Redistributions in binary form must reproduce the above copyright
10.\" notice, this list of conditions and the following disclaimer in the 10.\" notice, this list of conditions and the following disclaimer in the
11.\" documentation and/or other materials provided with the distribution. 11.\" documentation and/or other materials provided with the distribution.
12.\" 3. All advertising materials mentioning features or use of this software 12.\" 3. Neither the name of the University nor the names of its contributors
13.\" must display the following acknowledgement:
14.\" This product includes software developed by the University of
15.\" California, Berkeley and its contributors.
16.\" 4. 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 13.\" may be used to endorse or promote products derived from this software
18.\" without specific prior written permission. 14.\" without specific prior written permission.
19.\" 15.\"
@@ -29,97 +25,105 @@
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE. 26.\" SUCH DAMAGE.
31.\" 27.\"
32.\" from: @(#)random.3 6.5 (Berkeley) 4/19/91 28.\" $OpenBSD: random.3,v 1.19 2007/05/31 19:19:31 jmc Exp $
33.\" $Id: random.3,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $
34.\" 29.\"
35.Dd April 19, 1991 30.Dd $Mdocdate: May 31 2007 $
36.Dt RANDOM 3 31.Dt RANDOM 3
37.Os BSD 4.2 32.Os
38.Sh NAME 33.Sh NAME
39.Nm random , 34.Nm random ,
40.Nm srandom , 35.Nm srandom ,
36.Nm srandomdev ,
41.Nm initstate , 37.Nm initstate ,
42.Nm setstate 38.Nm setstate
43.Nd better random number generator; routines for changing generators 39.Nd better random number generator; routines for changing generators
44.Sh SYNOPSIS 40.Sh SYNOPSIS
45.Fd #include <stdlib.h> 41.Fd #include <stdlib.h>
46.Ft long 42.Ft long
47.Fn random void 43.Fn random void
48.Ft void 44.Ft void
49.Fn srandom "unsigned seed" 45.Fn srandom "unsigned int seed"
46.Ft void
47.Fn srandomdev void
50.Ft char * 48.Ft char *
51.Fn initstate "unsigned seed" "char *state" "int n" 49.Fn initstate "unsigned int seed" "char *state" "size_t n"
52.Ft char * 50.Ft char *
53.Fn setstate "char *state" 51.Fn setstate "const char *state"
54.Sh DESCRIPTION 52.Sh DESCRIPTION
55The 53The
56.Fn random 54.Fn random
57function 55function uses a non-linear additive feedback random number generator employing
58uses a non-linear additive feedback random number generator employing a 56a default table of size 31 long integers to return successive pseudo-random
59default table of size 31 long integers to return successive pseudo-random 57numbers in the range from 0 to (2**31)\-1.
60numbers in the range from 0 to
61.if t 2\u\s731\s10\d\(mi1.
62.if n (2**31)\(mi1.
63The period of this random number generator is very large, approximately 58The period of this random number generator is very large, approximately
64.if t 16\(mu(2\u\s731\s10\d\(mi1). 5916*((2**31)\-1).
65.if n 16*((2**31)\(mi1).
66.Pp 60.Pp
67The 61The
68.Fn random Ns / Fn srandom 62.Fn random
69have (almost) the same calling sequence and initialization properties as 63and
70.Xr rand 3 Ns / Xr srand 3 . 64.Fn srandom
65functions have (almost) the same calling sequence and initialization
66properties as
67.Xr rand 3 Ns / Ns Xr srand 3 .
71The difference is that 68The difference is that
72.Xr rand 69.Xr rand
73produces a much less random sequence \(em in fact, the low dozen bits 70produces a much less random sequence \(em in fact, the low dozen bits
74generated by rand go through a cyclic pattern. All the bits generated by 71generated by rand go through a cyclic pattern.
72All the bits generated by
75.Fn random 73.Fn random
76are usable. For example, 74are usable.
75For example,
77.Sq Li random()&01 76.Sq Li random()&01
78will produce a random binary 77will produce a random binary
79value. 78value.
80.Pp 79.Pp
81Unlike 80Like
82.Xr srand ,
83.Fn srandom
84does not return the old seed; the reason for this is that the amount of
85state information used is much more than a single word. (Two other
86routines are provided to deal with restarting/changing random
87number generators). Like
88.Xr rand 3 , 81.Xr rand 3 ,
89however,
90.Fn random 82.Fn random
91will by default produce a sequence of numbers that can be duplicated 83will by default produce a sequence of numbers that can be duplicated
92by calling 84by calling
93.Fn srandom 85.Fn srandom
94with 86with
95.Ql 1 87.Ql 1
96as the seed. 88as the seed.
97.Pp 89.Pp
98The 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
99.Fn initstate 103.Fn initstate
100routine allows a state array, passed in as an argument, to be initialized 104routine allows a state array, passed in as an argument, to be initialized
101for future use. The size of the state array (in bytes) is used by 105for future use.
106The size of the state array (in bytes) is used by
102.Fn initstate 107.Fn initstate
103to decide how sophisticated a random number generator it should use \(em the 108to decide how sophisticated a random number generator it should use \(em the
104more state, the better the random numbers will be. 109more state, the better the random numbers will be.
105(Current "optimal" values for the amount of state information are 110(Current "optimal" values for the amount of state information are
1068, 32, 64, 128, and 256 bytes; other amounts will be rounded down to 1118, 32, 64, 128, and 256 bytes; other amounts will be rounded down to
107the nearest known amount. Using less than 8 bytes will cause an error.) 112the nearest known amount.
113Using less than 8 bytes will cause an error.)
108The seed for the initialization (which specifies a starting point for 114The seed for the initialization (which specifies a starting point for
109the random number sequence, and provides for restarting at the same 115the random number sequence, and provides for restarting at the same
110point) is also an argument. 116point) is also an argument.
111The 117The
112.Fn initstate 118.Fn initstate
113function 119function returns a pointer to the previous state information array.
114returns a pointer to the previous state information array.
115.Pp 120.Pp
116Once a state has been initialized, the 121Once a state has been initialized, the
117.Fn setstate 122.Fn setstate
118routine provides for rapid switching between states. 123routine provides for rapid switching between states.
119The 124The
120.Fn setstate 125.Fn setstate
121function 126function returns a pointer to the previous state array; its
122returns a pointer to the previous state array; its
123argument state array is used for further random number generation 127argument state array is used for further random number generation
124until the next call to 128until the next call to
125.Fn initstate 129.Fn initstate
@@ -143,12 +147,8 @@ is that the size of the state array does not have to be remembered after
143it is initialized. 147it is initialized.
144.Pp 148.Pp
145With 256 bytes of state information, the period of the random number 149With 256 bytes of state information, the period of the random number
146generator is greater than 150generator is greater than 2**69
147.if t 2\u\s769\s10\d,
148.if n 2**69
149which should be sufficient for most purposes. 151which should be sufficient for most purposes.
150.Sh AUTHOR
151Earl T. Cohen
152.Sh DIAGNOSTICS 152.Sh DIAGNOSTICS
153If 153If
154.Fn initstate 154.Fn initstate
@@ -157,11 +157,29 @@ is called with less than 8 bytes of state information, or if
157detects that the state information has been garbled, error 157detects that the state information has been garbled, error
158messages are printed on the standard error output. 158messages are printed on the standard error output.
159.Sh SEE ALSO 159.Sh SEE ALSO
160.Xr rand 3 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.
161.Sh HISTORY 177.Sh HISTORY
162These 178These
163functions appeared in 179functions appeared in
164.Bx 4.2 . 180.Bx 4.2 .
181.Sh AUTHORS
182.An Earl T. Cohen
165.Sh BUGS 183.Sh BUGS
166About 2/3 the speed of 184About 2/3 the speed of
167.Xr rand 3 . 185.Xr rand 3 .
diff --git a/src/lib/libc/stdlib/random.c b/src/lib/libc/stdlib/random.c
index 469b6d976a..48e892042b 100644
--- a/src/lib/libc/stdlib/random.c
+++ b/src/lib/libc/stdlib/random.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: random.c,v 1.15 2005/11/30 07:51:02 otto Exp $ */
1/* 2/*
2 * Copyright (c) 1983 Regents of the University of California. 3 * Copyright (c) 1983 Regents of the University of California.
3 * All rights reserved. 4 * All rights reserved.
@@ -10,11 +11,7 @@
10 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. 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 15 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission. 16 * without specific prior written permission.
20 * 17 *
@@ -31,13 +28,13 @@
31 * SUCH DAMAGE. 28 * SUCH DAMAGE.
32 */ 29 */
33 30
34#if defined(LIBC_SCCS) && !defined(lint) 31#include <sys/param.h>
35/*static char *sccsid = "from: @(#)random.c 5.9 (Berkeley) 2/23/91";*/ 32#include <sys/sysctl.h>
36static char *rcsid = "$Id: random.c,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $"; 33#include <sys/time.h>
37#endif /* LIBC_SCCS and not lint */ 34#include <fcntl.h>
38
39#include <stdio.h> 35#include <stdio.h>
40#include <stdlib.h> 36#include <stdlib.h>
37#include <unistd.h>
41 38
42/* 39/*
43 * random.c: 40 * random.c:
@@ -55,10 +52,10 @@ static char *rcsid = "$Id: random.c,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $"
55 * congruential generator. If the amount of state information is less than 52 * congruential generator. If the amount of state information is less than
56 * 32 bytes, a simple linear congruential R.N.G. is used. 53 * 32 bytes, a simple linear congruential R.N.G. is used.
57 * 54 *
58 * Internally, the state information is treated as an array of longs; the 55 * Internally, the state information is treated as an array of int32_t; the
59 * zeroeth element of the array is the type of R.N.G. being used (small 56 * zeroeth element of the array is the type of R.N.G. being used (small
60 * integer); the remainder of the array is the state information for the 57 * integer); the remainder of the array is the state information for the
61 * R.N.G. Thus, 32 bytes of state information will give 7 longs worth of 58 * R.N.G. Thus, 32 bytes of state information will give 7 int32_ts worth of
62 * state information, which will allow a degree seven polynomial. (Note: 59 * state information, which will allow a degree seven polynomial. (Note:
63 * the zeroeth word of state information also has some other information 60 * the zeroeth word of state information also has some other information
64 * stored in it -- see setstate() for details). 61 * stored in it -- see setstate() for details).
@@ -134,14 +131,14 @@ static int seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
134 * MAX_TYPES * (rptr - state) + TYPE_3 == TYPE_3. 131 * MAX_TYPES * (rptr - state) + TYPE_3 == TYPE_3.
135 */ 132 */
136 133
137static long randtbl[DEG_3 + 1] = { 134static int32_t randtbl[DEG_3 + 1] = {
138 TYPE_3, 135 TYPE_3,
139 0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342, 0xde3b81e0, 0xdf0a6fb5, 136 0x991539b1, 0x16a5bce3, 0x6774a4cd, 0x3e01511e, 0x4e508aaa, 0x61048c05,
140 0xf103bc02, 0x48f340fb, 0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd, 137 0xf5500617, 0x846b7115, 0x6a19892c, 0x896a97af, 0xdb48f936, 0x14898454,
141 0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86, 0xda672e2a, 0x1588ca88, 138 0x37ffd106, 0xb58bff9c, 0x59e17104, 0xcf918a49, 0x09378c83, 0x52c7a471,
142 0xe369735d, 0x904f35f7, 0xd7158fd6, 0x6fa6f051, 0x616e6b96, 0xac94efdc, 139 0x8d293ea9, 0x1f4fc301, 0xc3db71be, 0x39b44e1c, 0xf8a44ef9, 0x4c8b80b1,
143 0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b, 0xf5ad9d0e, 0x8999220b, 140 0x19edc328, 0x87bf4bdd, 0xc9b240e5, 0xe9ee4b1b, 0x4382aee7, 0x535b6b41,
144 0x27fb47b9, 141 0xf3bec5da,
145}; 142};
146 143
147/* 144/*
@@ -158,8 +155,8 @@ static long randtbl[DEG_3 + 1] = {
158 * in the initialization of randtbl) because the state table pointer is set 155 * in the initialization of randtbl) because the state table pointer is set
159 * to point to randtbl[1] (as explained below). 156 * to point to randtbl[1] (as explained below).
160 */ 157 */
161static long *fptr = &randtbl[SEP_3 + 1]; 158static int32_t *fptr = &randtbl[SEP_3 + 1];
162static long *rptr = &randtbl[1]; 159static int32_t *rptr = &randtbl[1];
163 160
164/* 161/*
165 * The following things are the pointer to the state information table, the 162 * The following things are the pointer to the state information table, the
@@ -171,11 +168,11 @@ static long *rptr = &randtbl[1];
171 * this is more efficient than indexing every time to find the address of 168 * this is more efficient than indexing every time to find the address of
172 * the last element to see if the front and rear pointers have wrapped. 169 * the last element to see if the front and rear pointers have wrapped.
173 */ 170 */
174static long *state = &randtbl[1]; 171static int32_t *state = &randtbl[1];
172static int32_t *end_ptr = &randtbl[DEG_3 + 1];
175static int rand_type = TYPE_3; 173static int rand_type = TYPE_3;
176static int rand_deg = DEG_3; 174static int rand_deg = DEG_3;
177static int rand_sep = SEP_3; 175static int rand_sep = SEP_3;
178static long *end_ptr = &randtbl[DEG_3 + 1];
179 176
180/* 177/*
181 * srandom: 178 * srandom:
@@ -190,18 +187,28 @@ static long *end_ptr = &randtbl[DEG_3 + 1];
190 * for default usage relies on values produced by this routine. 187 * for default usage relies on values produced by this routine.
191 */ 188 */
192void 189void
193srandom(x) 190srandom(unsigned int x)
194 u_int x;
195{ 191{
196 register int i, j; 192 int i;
193 int32_t test;
194 div_t val;
197 195
198 if (rand_type == TYPE_0) 196 if (rand_type == TYPE_0)
199 state[0] = x; 197 state[0] = x;
200 else { 198 else {
201 j = 1;
202 state[0] = x; 199 state[0] = x;
203 for (i = 1; i < rand_deg; i++) 200 for (i = 1; i < rand_deg; i++) {
204 state[i] = 1103515245 * state[i - 1] + 12345; 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 }
205 fptr = &state[rand_sep]; 212 fptr = &state[rand_sep];
206 rptr = &state[0]; 213 rptr = &state[0];
207 for (i = 0; i < 10 * rand_deg; i++) 214 for (i = 0; i < 10 * rand_deg; i++)
@@ -210,6 +217,38 @@ srandom(x)
210} 217}
211 218
212/* 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/*
213 * initstate: 252 * initstate:
214 * 253 *
215 * Initialize the state information in the given array of n bytes for future 254 * Initialize the state information in the given array of n bytes for future
@@ -229,22 +268,16 @@ srandom(x)
229 * Returns a pointer to the old state. 268 * Returns a pointer to the old state.
230 */ 269 */
231char * 270char *
232initstate(seed, arg_state, n) 271initstate(u_int seed, char *arg_state, size_t n)
233 u_int seed; /* seed for R.N.G. */
234 char *arg_state; /* pointer to state array */
235 int n; /* # bytes of state info */
236{ 272{
237 register char *ostate = (char *)(&state[-1]); 273 char *ostate = (char *)(&state[-1]);
238 274
239 if (rand_type == TYPE_0) 275 if (rand_type == TYPE_0)
240 state[-1] = rand_type; 276 state[-1] = rand_type;
241 else 277 else
242 state[-1] = MAX_TYPES * (rptr - state) + rand_type; 278 state[-1] = MAX_TYPES * (rptr - state) + rand_type;
243 if (n < BREAK_0) { 279 if (n < BREAK_0)
244 (void)fprintf(stderr, 280 return(NULL);
245 "random: not enough state (%d bytes); ignored.\n", n);
246 return(0);
247 }
248 if (n < BREAK_1) { 281 if (n < BREAK_1) {
249 rand_type = TYPE_0; 282 rand_type = TYPE_0;
250 rand_deg = DEG_0; 283 rand_deg = DEG_0;
@@ -266,7 +299,7 @@ initstate(seed, arg_state, n)
266 rand_deg = DEG_4; 299 rand_deg = DEG_4;
267 rand_sep = SEP_4; 300 rand_sep = SEP_4;
268 } 301 }
269 state = &(((long *)arg_state)[1]); /* first location */ 302 state = &(((int32_t *)arg_state)[1]); /* first location */
270 end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */ 303 end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */
271 srandom(seed); 304 srandom(seed);
272 if (rand_type == TYPE_0) 305 if (rand_type == TYPE_0)
@@ -292,12 +325,11 @@ initstate(seed, arg_state, n)
292 * Returns a pointer to the old state information. 325 * Returns a pointer to the old state information.
293 */ 326 */
294char * 327char *
295setstate(arg_state) 328setstate(const char *arg_state)
296 char *arg_state;
297{ 329{
298 register long *new_state = (long *)arg_state; 330 int32_t *new_state = (int32_t *)arg_state;
299 register int type = new_state[0] % MAX_TYPES; 331 int32_t type = new_state[0] % MAX_TYPES;
300 register int rear = new_state[0] / MAX_TYPES; 332 int32_t rear = new_state[0] / MAX_TYPES;
301 char *ostate = (char *)(&state[-1]); 333 char *ostate = (char *)(&state[-1]);
302 334
303 if (rand_type == TYPE_0) 335 if (rand_type == TYPE_0)
@@ -315,8 +347,7 @@ setstate(arg_state)
315 rand_sep = seps[type]; 347 rand_sep = seps[type];
316 break; 348 break;
317 default: 349 default:
318 (void)fprintf(stderr, 350 return(NULL);
319 "random: state info corrupted; not changed.\n");
320 } 351 }
321 state = &new_state[1]; 352 state = &new_state[1];
322 if (rand_type != TYPE_0) { 353 if (rand_type != TYPE_0) {
@@ -345,9 +376,9 @@ setstate(arg_state)
345 * Returns a 31-bit random number. 376 * Returns a 31-bit random number.
346 */ 377 */
347long 378long
348random() 379random(void)
349{ 380{
350 long i; 381 int32_t i;
351 382
352 if (rand_type == TYPE_0) 383 if (rand_type == TYPE_0)
353 i = state[0] = (state[0] * 1103515245 + 12345) & 0x7fffffff; 384 i = state[0] = (state[0] * 1103515245 + 12345) & 0x7fffffff;
@@ -360,5 +391,5 @@ random()
360 } else if (++rptr >= end_ptr) 391 } else if (++rptr >= end_ptr)
361 rptr = state; 392 rptr = state;
362 } 393 }
363 return(i); 394 return((long)i);
364} 395}
diff --git a/src/lib/libc/stdlib/realloc.3 b/src/lib/libc/stdlib/realloc.3
deleted file mode 100644
index 66f09b2081..0000000000
--- a/src/lib/libc/stdlib/realloc.3
+++ /dev/null
@@ -1,100 +0,0 @@
1.\" Copyright (c) 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. All advertising materials mentioning features or use of this software
13.\" must display the following acknowledgement:
14.\" This product includes software developed by the University of
15.\" California, Berkeley and its contributors.
16.\" 4. 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.\" from: @(#)realloc.3 5.1 (Berkeley) 5/2/91
33.\" $Id: realloc.3,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $
34.\"
35.Dd May 2, 1991
36.Dt REALLOC 3
37.Os
38.Sh NAME
39.Nm realloc
40.Nd reallocation of memory function
41.Sh SYNOPSIS
42.Fd #include <stdlib.h>
43.Ft void *
44.Fn realloc "void *ptr" "size_t size"
45.Sh DESCRIPTION
46The
47.Fn realloc
48function changes the size of the object pointed to by
49.Fa ptr
50to the size specified by
51.Fa size .
52The contents of the object are unchanged up to the lesser
53of the new and old sizes.
54If the new size is larger, the value of the newly allocated portion
55of the object is indeterminate.
56If
57.Fa ptr
58is a null pointer, the
59.Fn realloc
60function behaves like the
61.Xr malloc 3
62function for the specified size.
63Otherwise, if
64.Fa ptr
65does not match a pointer earlier returned by the
66.Xr calloc 3 ,
67.Xr malloc 3 ,
68or
69.Fn realloc
70function, or if the space has been deallocated
71by a call to the
72.Xr free
73or
74.Fn realloc
75function, unpredictable and usually detrimental
76behavior will occur.
77If the space cannot be allocated, the object
78pointed to by
79.Fa ptr
80is unchanged.
81If
82.Fa size
83is zero and
84.Fa ptr
85is not a null pointer, the object it points to is freed.
86.Pp
87The
88.Fn realloc
89function returns either a null pointer or a pointer
90to the possibly moved allocated space.
91.Sh SEE ALSO
92.Xr alloca 3 ,
93.Xr calloc 3 ,
94.Xr free 3 ,
95.Xr malloc 3 ,
96.Sh STANDARDS
97The
98.Fn realloc
99function conforms to
100.St -ansiC .
diff --git a/src/lib/libc/stdlib/realpath.3 b/src/lib/libc/stdlib/realpath.3
index 9d8b1ff2ce..68ed088161 100644
--- a/src/lib/libc/stdlib/realpath.3
+++ b/src/lib/libc/stdlib/realpath.3
@@ -12,11 +12,7 @@
12.\" 2. Redistributions in binary form must reproduce the above copyright 12.\" 2. Redistributions in binary form must reproduce the above copyright
13.\" notice, this list of conditions and the following disclaimer in the 13.\" notice, this list of conditions and the following disclaimer in the
14.\" documentation and/or other materials provided with the distribution. 14.\" documentation and/or other materials provided with the distribution.
15.\" 3. All advertising materials mentioning features or use of this software 15.\" 3. Neither the name of the University nor the names of its contributors
16.\" must display the following acknowledgement:
17.\" This product includes software developed by the University of
18.\" California, Berkeley and its contributors.
19.\" 4. Neither the name of the University nor the names of its contributors
20.\" may be used to endorse or promote products derived from this software 16.\" may be used to endorse or promote products derived from this software
21.\" without specific prior written permission. 17.\" without specific prior written permission.
22.\" 18.\"
@@ -32,20 +28,19 @@
32.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33.\" SUCH DAMAGE. 29.\" SUCH DAMAGE.
34.\" 30.\"
35.\" from: @(#)realpath.3 8.2 (Berkeley) 2/16/94 31.\" $OpenBSD: realpath.3,v 1.17 2011/07/24 22:29:05 jmc Exp $
36.\" $Id: realpath.3,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $
37.\" 32.\"
38.Dd "February 16, 1994" 33.Dd $Mdocdate: July 24 2011 $
39.Dt REALPATH 3 34.Dt REALPATH 3
40.Os 35.Os
41.Sh NAME 36.Sh NAME
42.Nm realpath 37.Nm realpath
43.Nd returns the canonicalized absolute pathname 38.Nd returns the canonicalized absolute pathname
44.Sh SYNOPSIS 39.Sh SYNOPSIS
45.Fd #include <sys/param.h> 40.Fd #include <limits.h>
46.Fd #include <stdlib.h> 41.Fd #include <stdlib.h>
47.Ft "char *" 42.Ft "char *"
48.Fn realpath "const char *pathname" "char resolvedname[MAXPATHLEN]" 43.Fn realpath "const char *pathname" "char *resolved"
49.Sh DESCRIPTION 44.Sh DESCRIPTION
50The 45The
51.Fn realpath 46.Fn realpath
@@ -57,18 +52,18 @@ and
57.Pa /../ 52.Pa /../
58in 53in
59.Fa pathname , 54.Fa pathname ,
60and copies the resulting absolute pathname into 55and copies the resulting absolute pathname into the memory referenced by
61the memory referenced by 56.Fa resolved .
62.Fa resolvedname .
63The 57The
64.Fa resolvedname 58.Fa resolved
65argument 59argument
66.Em must 60.Em must
67refer to a buffer capable of storing at least 61refer to a buffer capable of storing at least
68.Dv MAXPATHLEN 62.Dv PATH_MAX
69characters. 63characters, or be
64.Dv NULL .
70.Pp 65.Pp
71The 66The
72.Fn realpath 67.Fn realpath
73function will resolve both absolute and relative paths 68function will resolve both absolute and relative paths
74and return the absolute pathname corresponding to 69and return the absolute pathname corresponding to
@@ -78,33 +73,49 @@ All but the last component of
78must exist when 73must exist when
79.Fn realpath 74.Fn realpath
80is called. 75is called.
81.Sh "RETURN VALUES" 76.Sh RETURN VALUES
82The 77The
83.Fn realpath 78.Fn realpath
84function returns 79function returns
85.Fa resolved_name 80.Fa resolved
86on success. 81on success.
82If
83.Fa resolved
84is
85.Dv NULL
86and no error occurred, then
87.Fa realpath
88returns a NUL-terminated string in a newly allocated buffer.
87If an error occurs, 89If an error occurs,
88.Fn realpath 90.Fn realpath
89returns 91returns
90.Dv NULL , 92.Dv NULL
91and 93and the contents of
92.Fa resolved_name 94.Fa resolved
93contains the pathname which caused the problem. 95are undefined.
94.Sh ERRORS 96.Sh ERRORS
95The function 97The function
96.Fn realpath 98.Fn realpath
97may fail and set the external variable 99may fail and set the external variable
98.Va errno 100.Va errno
99for any of the errors specified for the library functions 101for any of the errors specified for the library functions
100.Xr chdir 2 ,
101.Xr close 2 ,
102.Xr fchdir 2 ,
103.Xr lstat 2 , 102.Xr lstat 2 ,
104.Xr open 2 , 103.Xr readlink 2 ,
105.Xr readlink 2
106and 104and
107.Xr getcwd 3 . 105.Xr getcwd 3 .
106.Sh SEE ALSO
107.Xr readlink 1 ,
108.Xr getcwd 3
109.Sh STANDARDS
110The
111.Fn realpath
112function conforms to
113.St -p1003.1-2008 .
114.Sh HISTORY
115The
116.Fn realpath
117function call first appeared in
118.Bx 4.4 .
108.Sh CAVEATS 119.Sh CAVEATS
109This implementation of 120This implementation of
110.Fn realpath 121.Fn realpath
@@ -114,13 +125,6 @@ The
114version always returns absolute pathnames, 125version always returns absolute pathnames,
115whereas the Solaris implementation will, 126whereas the Solaris implementation will,
116under certain circumstances, return a relative 127under certain circumstances, return a relative
117.Fa resolved_path 128.Fa resolved
118when given a relative 129when given a relative
119.Fa pathname . 130.Fa pathname .
120.Sh "SEE ALSO"
121.Xr getcwd 3
122.Sh HISTORY
123The
124.Fn realpath
125function call first appeared in
126.Bx 4.4 .
diff --git a/src/lib/libc/stdlib/realpath.c b/src/lib/libc/stdlib/realpath.c
index e349b7e068..21af4cf005 100644
--- a/src/lib/libc/stdlib/realpath.c
+++ b/src/lib/libc/stdlib/realpath.c
@@ -1,9 +1,6 @@
1/* $OpenBSD: realpath.c,v 1.14 2011/07/24 21:03:00 miod Exp $ */
1/* 2/*
2 * Copyright (c) 1994 3 * Copyright (c) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru>
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Jan-Simon Pendry.
7 * 4 *
8 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
@@ -13,18 +10,14 @@
13 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 11 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution. 12 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software 13 * 3. The names of the authors may not be used to endorse or promote
17 * must display the following acknowledgement: 14 * products derived from this software without specific prior written
18 * This product includes software developed by the University of 15 * permission.
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 * 16 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@@ -34,126 +27,186 @@
34 * SUCH DAMAGE. 27 * SUCH DAMAGE.
35 */ 28 */
36 29
37#if defined(LIBC_SCCS) && !defined(lint)
38/*static char sccsid[] = "from: @(#)realpath.c 8.1 (Berkeley) 2/16/94";*/
39static char *rcsid = "$Id: realpath.c,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $";
40#endif /* LIBC_SCCS and not lint */
41
42#include <sys/param.h> 30#include <sys/param.h>
43#include <sys/stat.h> 31#include <sys/stat.h>
44 32
45#include <errno.h> 33#include <errno.h>
46#include <fcntl.h>
47#include <stdlib.h> 34#include <stdlib.h>
48#include <string.h> 35#include <string.h>
49#include <unistd.h> 36#include <unistd.h>
50 37
51/* 38/*
52 * char *realpath(const char *path, char resolved_path[MAXPATHLEN]); 39 * char *realpath(const char *path, char resolved[PATH_MAX]);
53 * 40 *
54 * Find the real name of path, by removing all ".", ".." and symlink 41 * Find the real name of path, by removing all ".", ".." and symlink
55 * components. Returns (resolved) on success, or (NULL) on failure, 42 * components. Returns (resolved) on success, or (NULL) on failure,
56 * in which case the path which caused trouble is left in (resolved). 43 * in which case the path which caused trouble is left in (resolved).
57 */ 44 */
58char * 45char *
59realpath(path, resolved) 46realpath(const char *path, char *resolved)
60 const char *path;
61 char *resolved;
62{ 47{
63 struct stat sb; 48 struct stat sb;
64 int fd, n, rootd, serrno; 49 char *p, *q, *s;
65 char *p, *q, wbuf[MAXPATHLEN]; 50 size_t left_len, resolved_len;
51 unsigned symlinks;
52 int serrno, slen, mem_allocated;
53 char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
66 54
67 /* Save the starting point. */ 55 if (path[0] == '\0') {
68 if ((fd = open(".", O_RDONLY)) < 0) { 56 errno = ENOENT;
69 (void)strcpy(resolved, ".");
70 return (NULL); 57 return (NULL);
71 } 58 }
72 59
73 /* 60 serrno = errno;
74 * Find the dirname and basename from the path to be resolved. 61
75 * Change directory to the dirname component. 62 if (resolved == NULL) {
76 * lstat the basename part. 63 resolved = malloc(PATH_MAX);
77 * if it is a symlink, read in the value and loop. 64 if (resolved == NULL)
78 * if it is a directory, then change to that directory. 65 return (NULL);
79 * get the current directory name and append the basename. 66 mem_allocated = 1;
80 */
81 (void)strncpy(resolved, path, MAXPATHLEN - 1);
82 resolved[MAXPATHLEN - 1] = '\0';
83loop:
84 q = strrchr(resolved, '/');
85 if (q != NULL) {
86 p = q + 1;
87 if (q == resolved)
88 q = "/";
89 else {
90 do {
91 --q;
92 } while (q > resolved && *q == '/');
93 q[1] = '\0';
94 q = resolved;
95 }
96 if (chdir(q) < 0)
97 goto err1;
98 } else 67 } else
99 p = resolved; 68 mem_allocated = 0;
100 69
101 /* Deal with the last component. */ 70 symlinks = 0;
102 if (lstat(p, &sb) == 0) { 71 if (path[0] == '/') {
103 if (S_ISLNK(sb.st_mode)) { 72 resolved[0] = '/';
104 n = readlink(p, resolved, MAXPATHLEN); 73 resolved[1] = '\0';
105 if (n < 0) 74 if (path[1] == '\0')
106 goto err1; 75 return (resolved);
107 resolved[n] = '\0'; 76 resolved_len = 1;
108 goto loop; 77 left_len = strlcpy(left, path + 1, sizeof(left));
109 } 78 } else {
110 if (S_ISDIR(sb.st_mode)) { 79 if (getcwd(resolved, PATH_MAX) == NULL) {
111 if (chdir(p) < 0) 80 if (mem_allocated)
112 goto err1; 81 free(resolved);
113 p = ""; 82 else
83 strlcpy(resolved, ".", PATH_MAX);
84 return (NULL);
114 } 85 }
86 resolved_len = strlen(resolved);
87 left_len = strlcpy(left, path, sizeof(left));
88 }
89 if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
90 errno = ENAMETOOLONG;
91 goto err;
115 } 92 }
116 93
117 /* 94 /*
118 * Save the last component name and get the full pathname of 95 * Iterate over path components in `left'.
119 * the current directory.
120 */
121 (void)strcpy(wbuf, p);
122 if (getcwd(resolved, MAXPATHLEN) == 0)
123 goto err1;
124
125 /*
126 * Join the two strings together, ensuring that the right thing
127 * happens if the last component is empty, or the dirname is root.
128 */ 96 */
129 if (resolved[0] == '/' && resolved[1] == '\0') 97 while (left_len != 0) {
130 rootd = 1; 98 /*
131 else 99 * Extract the next path component and adjust `left'
132 rootd = 0; 100 * and its length.
101 */
102 p = strchr(left, '/');
103 s = p ? p : left + left_len;
104 if (s - left >= sizeof(next_token)) {
105 errno = ENAMETOOLONG;
106 goto err;
107 }
108 memcpy(next_token, left, s - left);
109 next_token[s - left] = '\0';
110 left_len -= s - left;
111 if (p != NULL)
112 memmove(left, s + 1, left_len + 1);
113 if (resolved[resolved_len - 1] != '/') {
114 if (resolved_len + 1 >= PATH_MAX) {
115 errno = ENAMETOOLONG;
116 goto err;
117 }
118 resolved[resolved_len++] = '/';
119 resolved[resolved_len] = '\0';
120 }
121 if (next_token[0] == '\0')
122 continue;
123 else if (strcmp(next_token, ".") == 0)
124 continue;
125 else if (strcmp(next_token, "..") == 0) {
126 /*
127 * Strip the last path component except when we have
128 * single "/"
129 */
130 if (resolved_len > 1) {
131 resolved[resolved_len - 1] = '\0';
132 q = strrchr(resolved, '/') + 1;
133 *q = '\0';
134 resolved_len = q - resolved;
135 }
136 continue;
137 }
133 138
134 if (*wbuf) { 139 /*
135 if (strlen(resolved) + strlen(wbuf) + rootd + 1 > MAXPATHLEN) { 140 * Append the next path component and lstat() it. If
141 * lstat() fails we still can return successfully if
142 * there are no more path components left.
143 */
144 resolved_len = strlcat(resolved, next_token, PATH_MAX);
145 if (resolved_len >= PATH_MAX) {
136 errno = ENAMETOOLONG; 146 errno = ENAMETOOLONG;
137 goto err1; 147 goto err;
138 } 148 }
139 if (rootd == 0) 149 if (lstat(resolved, &sb) != 0) {
140 (void)strcat(resolved, "/"); 150 if (errno == ENOENT && p == NULL) {
141 (void)strcat(resolved, wbuf); 151 errno = serrno;
142 } 152 return (resolved);
153 }
154 goto err;
155 }
156 if (S_ISLNK(sb.st_mode)) {
157 if (symlinks++ > MAXSYMLINKS) {
158 errno = ELOOP;
159 goto err;
160 }
161 slen = readlink(resolved, symlink, sizeof(symlink) - 1);
162 if (slen < 0)
163 goto err;
164 symlink[slen] = '\0';
165 if (symlink[0] == '/') {
166 resolved[1] = 0;
167 resolved_len = 1;
168 } else if (resolved_len > 1) {
169 /* Strip the last path component. */
170 resolved[resolved_len - 1] = '\0';
171 q = strrchr(resolved, '/') + 1;
172 *q = '\0';
173 resolved_len = q - resolved;
174 }
143 175
144 /* Go back to where we came from. */ 176 /*
145 if (fchdir(fd) < 0) { 177 * If there are any path components left, then
146 serrno = errno; 178 * append them to symlink. The result is placed
147 goto err2; 179 * in `left'.
180 */
181 if (p != NULL) {
182 if (symlink[slen - 1] != '/') {
183 if (slen + 1 >= sizeof(symlink)) {
184 errno = ENAMETOOLONG;
185 goto err;
186 }
187 symlink[slen] = '/';
188 symlink[slen + 1] = 0;
189 }
190 left_len = strlcat(symlink, left, sizeof(left));
191 if (left_len >= sizeof(left)) {
192 errno = ENAMETOOLONG;
193 goto err;
194 }
195 }
196 left_len = strlcpy(left, symlink, sizeof(left));
197 }
148 } 198 }
149 199
150 /* It's okay if the close fails, what's an fd more or less? */ 200 /*
151 (void)close(fd); 201 * Remove trailing slash except when the resolved pathname
202 * is a single "/".
203 */
204 if (resolved_len > 1 && resolved[resolved_len - 1] == '/')
205 resolved[resolved_len - 1] = '\0';
152 return (resolved); 206 return (resolved);
153 207
154err1: serrno = errno; 208err:
155 (void)fchdir(fd); 209 if (mem_allocated)
156err2: (void)close(fd); 210 free(resolved);
157 errno = serrno;
158 return (NULL); 211 return (NULL);
159} 212}
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
index e3d31901dd..583262f2d5 100644
--- a/src/lib/libc/stdlib/seed48.c
+++ b/src/lib/libc/stdlib/seed48.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: seed48.c,v 1.3 2005/08/08 08:05:37 espie Exp $ */
1/* 2/*
2 * Copyright (c) 1993 Martin Birgmeier 3 * Copyright (c) 1993 Martin Birgmeier
3 * All rights reserved. 4 * All rights reserved.
diff --git a/src/lib/libc/stdlib/setenv.c b/src/lib/libc/stdlib/setenv.c
index a36669888d..089ab92d38 100644
--- a/src/lib/libc/stdlib/setenv.c
+++ b/src/lib/libc/stdlib/setenv.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: setenv.c,v 1.13 2010/08/23 22:31:50 millert Exp $ */
1/* 2/*
2 * Copyright (c) 1987 Regents of the University of California. 3 * Copyright (c) 1987 Regents of the University of California.
3 * All rights reserved. 4 * All rights reserved.
@@ -10,11 +11,7 @@
10 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. 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 15 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission. 16 * without specific prior written permission.
20 * 17 *
@@ -31,71 +28,120 @@
31 * SUCH DAMAGE. 28 * SUCH DAMAGE.
32 */ 29 */
33 30
34#if defined(LIBC_SCCS) && !defined(lint) 31#include <errno.h>
35/*static char *sccsid = "from: @(#)setenv.c 5.6 (Berkeley) 6/4/91";*/
36static char *rcsid = "$Id: setenv.c,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */
38
39#include <stdlib.h> 32#include <stdlib.h>
40#include <string.h> 33#include <string.h>
41 34
35char *__findenv(const char *name, int len, int *offset);
36
37extern char **environ;
38static char **lastenv; /* last value of environ */
39
40/*
41 * putenv --
42 * Add a name=value string directly to the environmental, replacing
43 * any current value.
44 */
45int
46putenv(char *str)
47{
48 char **P, *cp;
49 size_t cnt;
50 int offset = 0;
51
52 for (cp = str; *cp && *cp != '='; ++cp)
53 ;
54 if (*cp != '=') {
55 errno = EINVAL;
56 return (-1); /* missing `=' in string */
57 }
58
59 if (__findenv(str, (int)(cp - str), &offset) != NULL) {
60 environ[offset++] = str;
61 /* could be set multiple times */
62 while (__findenv(str, (int)(cp - str), &offset)) {
63 for (P = &environ[offset];; ++P)
64 if (!(*P = *(P + 1)))
65 break;
66 }
67 return (0);
68 }
69
70 /* create new slot for string */
71 for (P = environ; *P != NULL; P++)
72 ;
73 cnt = P - environ;
74 P = (char **)realloc(lastenv, sizeof(char *) * (cnt + 2));
75 if (!P)
76 return (-1);
77 if (lastenv != environ)
78 memcpy(P, environ, cnt * sizeof(char *));
79 lastenv = environ = P;
80 environ[cnt] = str;
81 environ[cnt + 1] = NULL;
82 return (0);
83}
84
42/* 85/*
43 * setenv -- 86 * setenv --
44 * Set the value of the environmental variable "name" to be 87 * Set the value of the environmental variable "name" to be
45 * "value". If rewrite is set, replace any current value. 88 * "value". If rewrite is set, replace any current value.
46 */ 89 */
47int 90int
48setenv(name, value, rewrite) 91setenv(const char *name, const char *value, int rewrite)
49 register const char *name;
50 register const char *value;
51 int rewrite;
52{ 92{
53 extern char **environ; 93 char *C, **P;
54 static int alloced; /* if allocated space before */ 94 const char *np;
55 register char *C; 95 int l_value, offset = 0;
56 int l_value, offset; 96
57 char *__findenv(); 97 for (np = name; *np && *np != '='; ++np)
98 ;
99#ifdef notyet
100 if (*np) {
101 errno = EINVAL;
102 return (-1); /* has `=' in name */
103 }
104#endif
58 105
59 if (*value == '=') /* no `=' in value */
60 ++value;
61 l_value = strlen(value); 106 l_value = strlen(value);
62 if ((C = __findenv(name, &offset))) { /* find if already exists */ 107 if ((C = __findenv(name, (int)(np - name), &offset)) != NULL) {
108 int tmpoff = offset + 1;
63 if (!rewrite) 109 if (!rewrite)
64 return (0); 110 return (0);
111#if 0 /* XXX - existing entry may not be writable */
65 if (strlen(C) >= l_value) { /* old larger; copy over */ 112 if (strlen(C) >= l_value) { /* old larger; copy over */
66 while (*C++ = *value++); 113 while ((*C++ = *value++))
114 ;
67 return (0); 115 return (0);
68 } 116 }
117#endif
118 /* could be set multiple times */
119 while (__findenv(name, (int)(np - name), &tmpoff)) {
120 for (P = &environ[tmpoff];; ++P)
121 if (!(*P = *(P + 1)))
122 break;
123 }
69 } else { /* create new slot */ 124 } else { /* create new slot */
70 register int cnt; 125 size_t cnt;
71 register char **P;
72 126
73 for (P = environ, cnt = 0; *P; ++P, ++cnt); 127 for (P = environ; *P != NULL; P++)
74 if (alloced) { /* just increase size */ 128 ;
75 environ = (char **)realloc((char *)environ, 129 cnt = P - environ;
76 (size_t)(sizeof(char *) * (cnt + 2))); 130 P = (char **)realloc(lastenv, sizeof(char *) * (cnt + 2));
77 if (!environ) 131 if (!P)
78 return (-1); 132 return (-1);
79 } 133 if (lastenv != environ)
80 else { /* get new space */ 134 memcpy(P, environ, cnt * sizeof(char *));
81 alloced = 1; /* copy old entries into it */ 135 lastenv = environ = P;
82 P = (char **)malloc((size_t)(sizeof(char *) *
83 (cnt + 2)));
84 if (!P)
85 return (-1);
86 bcopy(environ, P, cnt * sizeof(char *));
87 environ = P;
88 }
89 environ[cnt + 1] = NULL;
90 offset = cnt; 136 offset = cnt;
137 environ[cnt + 1] = NULL;
91 } 138 }
92 for (C = (char *)name; *C && *C != '='; ++C); /* no `=' in name */
93 if (!(environ[offset] = /* name + `=' + value */ 139 if (!(environ[offset] = /* name + `=' + value */
94 malloc((size_t)((int)(C - name) + l_value + 2)))) 140 malloc((size_t)((int)(np - name) + l_value + 2))))
95 return (-1); 141 return (-1);
96 for (C = environ[offset]; (*C = *name++) && *C != '='; ++C) 142 for (C = environ[offset]; (*C = *name++) && *C != '='; ++C)
97 ; 143 ;
98 for (*C++ = '='; *C++ = *value++; ) 144 for (*C++ = '='; (*C++ = *value++); )
99 ; 145 ;
100 return (0); 146 return (0);
101} 147}
@@ -104,17 +150,29 @@ setenv(name, value, rewrite)
104 * unsetenv(name) -- 150 * unsetenv(name) --
105 * Delete environmental variable "name". 151 * Delete environmental variable "name".
106 */ 152 */
107void 153int
108unsetenv(name) 154unsetenv(const char *name)
109 const char *name;
110{ 155{
111 extern char **environ; 156 char **P;
112 register char **P; 157 const char *np;
113 int offset; 158 int offset = 0;
114 char *__findenv(); 159
160 if (!name || !*name) {
161 errno = EINVAL;
162 return (-1);
163 }
164 for (np = name; *np && *np != '='; ++np)
165 ;
166 if (*np) {
167 errno = EINVAL;
168 return (-1); /* has `=' in name */
169 }
115 170
116 while (__findenv(name, &offset)) /* if set multiple times */ 171 /* could be set multiple times */
172 while (__findenv(name, (int)(np - name), &offset)) {
117 for (P = &environ[offset];; ++P) 173 for (P = &environ[offset];; ++P)
118 if (!(*P = *(P + 1))) 174 if (!(*P = *(P + 1)))
119 break; 175 break;
176 }
177 return (0);
120} 178}
diff --git a/src/lib/libc/stdlib/srand48.c b/src/lib/libc/stdlib/srand48.c
index daf733f93e..f76b6cca86 100644
--- a/src/lib/libc/stdlib/srand48.c
+++ b/src/lib/libc/stdlib/srand48.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: srand48.c,v 1.3 2005/08/08 08:05:37 espie Exp $ */
1/* 2/*
2 * Copyright (c) 1993 Martin Birgmeier 3 * Copyright (c) 1993 Martin Birgmeier
3 * All rights reserved. 4 * All rights reserved.
diff --git a/src/lib/libc/stdlib/strtod.3 b/src/lib/libc/stdlib/strtod.3
index 0b7f973857..f1fc781f7d 100644
--- a/src/lib/libc/stdlib/strtod.3
+++ b/src/lib/libc/stdlib/strtod.3
@@ -13,11 +13,7 @@
13.\" 2. Redistributions in binary form must reproduce the above copyright 13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the 14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution. 15.\" documentation and/or other materials provided with the distribution.
16.\" 3. All advertising materials mentioning features or use of this software 16.\" 3. Neither the name of the University nor the names of its contributors
17.\" must display the following acknowledgement:
18.\" This product includes software developed by the University of
19.\" California, Berkeley and its contributors.
20.\" 4. Neither the name of the University nor the names of its contributors
21.\" may be used to endorse or promote products derived from this software 17.\" may be used to endorse or promote products derived from this software
22.\" without specific prior written permission. 18.\" without specific prior written permission.
23.\" 19.\"
@@ -33,44 +29,74 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
35.\" 31.\"
36.\" from: @(#)strtod.3 5.3 (Berkeley) 6/29/91 32.\" $OpenBSD: strtod.3,v 1.14 2008/09/13 22:48:45 martynas Exp $
37.\" $Id: strtod.3,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $
38.\" 33.\"
39.Dd June 29, 1991 34.Dd $Mdocdate: September 13 2008 $
40.Dt STRTOD 3 35.Dt STRTOD 3
41.Os 36.Os
42.Sh NAME 37.Sh NAME
43.Nm strtod 38.Nm strtod ,
39.Nm strtof ,
40.Nm strtold
44.Nd convert 41.Nd convert
45.Tn ASCII 42.Tn ASCII
46string to double 43string to double, float or long double
47.Sh SYNOPSIS 44.Sh SYNOPSIS
45.Fd #include <math.h>
48.Fd #include <stdlib.h> 46.Fd #include <stdlib.h>
49.Ft double 47.Ft double
50.Fn strtod "const char *nptr" "char **endptr" 48.Fn strtod "const char *nptr" "char **endptr"
49.Pp
50.Ft float
51.Fn strtof "const char *nptr" "char **endptr"
52.Pp
53.Ft long double
54.Fn strtold "const char *nptr" "char **endptr"
51.Sh DESCRIPTION 55.Sh DESCRIPTION
52The 56The
53.Fn strtod 57.Fn strtod
54function converts the initial portion of the string 58function converts the initial portion of the string pointed to by
55pointed to by
56.Fa nptr 59.Fa nptr
57to 60to
58.Em double 61.Li double
62representation.
63The
64.Fn strtof
65function converts the initial portion of the string pointed to by
66.Fa nptr
67to
68.Li float
69representation.
70The
71.Fn strtold
72function converts the initial portion of the string pointed to by
73.Fa nptr
74to
75.Li long double
59representation. 76representation.
60.Pp 77.Pp
61The expected form of the string is an optional plus (``+'') or minus 78The expected form of the string is an optional plus
62sign (``-'') followed by a sequence of digits optionally containing 79.Pq Ql +
80or minus sign
81.Pq Ql -
82followed by a sequence of digits optionally containing
63a decimal-point character, optionally followed by an exponent. 83a decimal-point character, optionally followed by an exponent.
64An exponent consists of an ``E'' or ``e'', followed by an optional plus 84An exponent consists of an
65or minus sign, followed by a sequence of digits. 85.Sq E
86or
87.Sq e ,
88followed by an optional plus or minus sign, followed by a sequence of digits.
66.Pp 89.Pp
67Leading white-space characters in the string (as defined by the 90Leading whitespace characters in the string (as defined by the
68.Xr isspace 3 91.Xr isspace 3
69function) are skipped. 92function) are skipped.
70.Sh RETURN VALUES 93.Sh RETURN VALUES
71The 94The
72.Fn strtod 95.Fn strtod ,
73function returns the converted value, if any. 96.Fn strtof
97and
98.Fn strtold
99functions return the converted value, if any.
74.Pp 100.Pp
75If 101If
76.Fa endptr 102.Fa endptr
@@ -88,18 +114,18 @@ is stored in the location referenced by
88If the correct value would cause overflow, plus or minus 114If the correct value would cause overflow, plus or minus
89.Dv HUGE_VAL 115.Dv HUGE_VAL
90is returned (according to the sign of the value), and 116is returned (according to the sign of the value), and
91.Dv ERANGE 117.Er ERANGE
92is stored in 118is stored in
93.Va errno . 119.Va errno .
94If the correct value would cause underflow, zero is 120If the correct value would cause underflow, zero is returned and
95returned and 121.Er ERANGE
96.Dv ERANGE 122is stored in
97is stored in
98.Va errno . 123.Va errno .
99.Sh ERRORS 124.Sh ERRORS
100.Bl -tag -width Er 125.Bl -tag -width Er
101.It Bq Er ERANGE 126.It Bq Er ERANGE
102Overflow or underflow occurred. 127Overflow or underflow occurred.
128.El
103.Sh SEE ALSO 129.Sh SEE ALSO
104.Xr atof 3 , 130.Xr atof 3 ,
105.Xr atoi 3 , 131.Xr atoi 3 ,
@@ -109,6 +135,11 @@ Overflow or underflow occurred.
109.Sh STANDARDS 135.Sh STANDARDS
110The 136The
111.Fn strtod 137.Fn strtod
112function 138function conforms to
113conforms to 139.St -ansiC-89 .
114.St -ansiC . 140The
141.Fn strtof
142and
143.Fn strtold
144functions conform to
145.St -ansiC-99 .
diff --git a/src/lib/libc/stdlib/strtod.c b/src/lib/libc/stdlib/strtod.c
deleted file mode 100644
index b13fa128f5..0000000000
--- a/src/lib/libc/stdlib/strtod.c
+++ /dev/null
@@ -1,2499 +0,0 @@
1/****************************************************************
2 *
3 * The author of this software is David M. Gay.
4 *
5 * Copyright (c) 1991 by AT&T.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose without fee is hereby granted, provided that this entire notice
9 * is included in all copies of any software which is or includes a copy
10 * or modification of this software and in all copies of the supporting
11 * documentation for such software.
12 *
13 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
14 * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY
15 * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
16 * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
17 *
18 ***************************************************************/
19
20/* Please send bug reports to
21 David M. Gay
22 AT&T Bell Laboratories, Room 2C-463
23 600 Mountain Avenue
24 Murray Hill, NJ 07974-2070
25 U.S.A.
26 dmg@research.att.com or research!dmg
27 */
28
29/* strtod for IEEE-, VAX-, and IBM-arithmetic machines.
30 *
31 * This strtod returns a nearest machine number to the input decimal
32 * string (or sets errno to ERANGE). With IEEE arithmetic, ties are
33 * broken by the IEEE round-even rule. Otherwise ties are broken by
34 * biased rounding (add half and chop).
35 *
36 * Inspired loosely by William D. Clinger's paper "How to Read Floating
37 * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101].
38 *
39 * Modifications:
40 *
41 * 1. We only require IEEE, IBM, or VAX double-precision
42 * arithmetic (not IEEE double-extended).
43 * 2. We get by with floating-point arithmetic in a case that
44 * Clinger missed -- when we're computing d * 10^n
45 * for a small integer d and the integer n is not too
46 * much larger than 22 (the maximum integer k for which
47 * we can represent 10^k exactly), we may be able to
48 * compute (d*10^k) * 10^(e-k) with just one roundoff.
49 * 3. Rather than a bit-at-a-time adjustment of the binary
50 * result in the hard case, we use floating-point
51 * arithmetic to determine the adjustment to within
52 * one bit; only in really hard cases do we need to
53 * compute a second residual.
54 * 4. Because of 3., we don't need a large table of powers of 10
55 * for ten-to-e (just some small tables, e.g. of 10^k
56 * for 0 <= k <= 22).
57 */
58
59/*
60 * #define IEEE_LITTLE_ENDIAN for IEEE-arithmetic machines where the least
61 * significant byte has the lowest address.
62 * #define IEEE_BIG_ENDIAN for IEEE-arithmetic machines where the most
63 * significant byte has the lowest address.
64 * #define Long int on machines with 32-bit ints and 64-bit longs.
65 * #define Sudden_Underflow for IEEE-format machines without gradual
66 * underflow (i.e., that flush to zero on underflow).
67 * #define IBM for IBM mainframe-style floating-point arithmetic.
68 * #define VAX for VAX-style floating-point arithmetic.
69 * #define Unsigned_Shifts if >> does treats its left operand as unsigned.
70 * #define No_leftright to omit left-right logic in fast floating-point
71 * computation of dtoa.
72 * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3.
73 * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines
74 * that use extended-precision instructions to compute rounded
75 * products and quotients) with IBM.
76 * #define ROUND_BIASED for IEEE-format with biased rounding.
77 * #define Inaccurate_Divide for IEEE-format with correctly rounded
78 * products but inaccurate quotients, e.g., for Intel i860.
79 * #define Just_16 to store 16 bits per 32-bit Long when doing high-precision
80 * integer arithmetic. Whether this speeds things up or slows things
81 * down depends on the machine and the number being converted.
82 * #define KR_headers for old-style C function headers.
83 * #define Bad_float_h if your system lacks a float.h or if it does not
84 * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP,
85 * FLT_RADIX, FLT_ROUNDS, and DBL_MAX.
86 * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n)
87 * if memory is available and otherwise does something you deem
88 * appropriate. If MALLOC is undefined, malloc will be invoked
89 * directly -- and assumed always to succeed.
90 */
91
92#if defined(LIBC_SCCS) && !defined(lint)
93static char *rcsid = "$Id: strtod.c,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $";
94#endif /* LIBC_SCCS and not lint */
95
96#if defined(__m68k__) || defined(__sparc__) || defined(__i386__) || \
97 defined(__mips__) || defined(__ns32k__) || defined(__alpha__)
98#include <machine/endian.h>
99#if BYTE_ORDER == BIG_ENDIAN
100#define IEEE_BIG_ENDIAN
101#else
102#define IEEE_LITTLE_ENDIAN
103#endif
104#endif
105
106#ifdef vax
107#define VAX
108#endif
109
110#define Long int32_t
111#define ULong u_int32_t
112
113#ifdef DEBUG
114#include "stdio.h"
115#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);}
116#endif
117
118#ifdef __cplusplus
119#include "malloc.h"
120#include "memory.h"
121#else
122#ifndef KR_headers
123#include "stdlib.h"
124#include "string.h"
125#include "locale.h"
126#else
127#include "malloc.h"
128#include "memory.h"
129#endif
130#endif
131
132#ifdef MALLOC
133#ifdef KR_headers
134extern char *MALLOC();
135#else
136extern void *MALLOC(size_t);
137#endif
138#else
139#define MALLOC malloc
140#endif
141
142#include "ctype.h"
143#include "errno.h"
144
145#ifdef Bad_float_h
146#undef __STDC__
147#ifdef IEEE_BIG_ENDIAN
148#define IEEE_ARITHMETIC
149#endif
150#ifdef IEEE_LITTLE_ENDIAN
151#define IEEE_ARITHMETIC
152#endif
153
154#ifdef IEEE_ARITHMETIC
155#define DBL_DIG 15
156#define DBL_MAX_10_EXP 308
157#define DBL_MAX_EXP 1024
158#define FLT_RADIX 2
159#define FLT_ROUNDS 1
160#define DBL_MAX 1.7976931348623157e+308
161#endif
162
163#ifdef IBM
164#define DBL_DIG 16
165#define DBL_MAX_10_EXP 75
166#define DBL_MAX_EXP 63
167#define FLT_RADIX 16
168#define FLT_ROUNDS 0
169#define DBL_MAX 7.2370055773322621e+75
170#endif
171
172#ifdef VAX
173#define DBL_DIG 16
174#define DBL_MAX_10_EXP 38
175#define DBL_MAX_EXP 127
176#define FLT_RADIX 2
177#define FLT_ROUNDS 1
178#define DBL_MAX 1.7014118346046923e+38
179#endif
180
181#ifndef LONG_MAX
182#define LONG_MAX 2147483647
183#endif
184#else
185#include "float.h"
186#endif
187#ifndef __MATH_H__
188#include "math.h"
189#endif
190
191#ifdef __cplusplus
192extern "C" {
193#endif
194
195#ifndef CONST
196#ifdef KR_headers
197#define CONST /* blank */
198#else
199#define CONST const
200#endif
201#endif
202
203#ifdef Unsigned_Shifts
204#define Sign_Extend(a,b) if (b < 0) a |= 0xffff0000;
205#else
206#define Sign_Extend(a,b) /*no-op*/
207#endif
208
209#if defined(IEEE_LITTLE_ENDIAN) + defined(IEEE_BIG_ENDIAN) + defined(VAX) + \
210 defined(IBM) != 1
211Exactly one of IEEE_LITTLE_ENDIAN IEEE_BIG_ENDIAN, VAX, or
212IBM should be defined.
213#endif
214
215#ifdef IEEE_LITTLE_ENDIAN
216#define word0(x) ((ULong *)&x)[1]
217#define word1(x) ((ULong *)&x)[0]
218#else
219#define word0(x) ((ULong *)&x)[0]
220#define word1(x) ((ULong *)&x)[1]
221#endif
222
223/* The following definition of Storeinc is appropriate for MIPS processors.
224 * An alternative that might be better on some machines is
225 * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff)
226 */
227#if defined(IEEE_LITTLE_ENDIAN) + defined(VAX)
228#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \
229((unsigned short *)a)[0] = (unsigned short)c, a++)
230#else
231#define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \
232((unsigned short *)a)[1] = (unsigned short)c, a++)
233#endif
234
235/* #define P DBL_MANT_DIG */
236/* Ten_pmax = floor(P*log(2)/log(5)) */
237/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */
238/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */
239/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */
240
241#if defined(IEEE_LITTLE_ENDIAN) + defined(IEEE_BIG_ENDIAN)
242#define Exp_shift 20
243#define Exp_shift1 20
244#define Exp_msk1 0x100000
245#define Exp_msk11 0x100000
246#define Exp_mask 0x7ff00000
247#define P 53
248#define Bias 1023
249#define IEEE_Arith
250#define Emin (-1022)
251#define Exp_1 0x3ff00000
252#define Exp_11 0x3ff00000
253#define Ebits 11
254#define Frac_mask 0xfffff
255#define Frac_mask1 0xfffff
256#define Ten_pmax 22
257#define Bletch 0x10
258#define Bndry_mask 0xfffff
259#define Bndry_mask1 0xfffff
260#define LSB 1
261#define Sign_bit 0x80000000
262#define Log2P 1
263#define Tiny0 0
264#define Tiny1 1
265#define Quick_max 14
266#define Int_max 14
267#define Infinite(x) (word0(x) == 0x7ff00000) /* sufficient test for here */
268#else
269#undef Sudden_Underflow
270#define Sudden_Underflow
271#ifdef IBM
272#define Exp_shift 24
273#define Exp_shift1 24
274#define Exp_msk1 0x1000000
275#define Exp_msk11 0x1000000
276#define Exp_mask 0x7f000000
277#define P 14
278#define Bias 65
279#define Exp_1 0x41000000
280#define Exp_11 0x41000000
281#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */
282#define Frac_mask 0xffffff
283#define Frac_mask1 0xffffff
284#define Bletch 4
285#define Ten_pmax 22
286#define Bndry_mask 0xefffff
287#define Bndry_mask1 0xffffff
288#define LSB 1
289#define Sign_bit 0x80000000
290#define Log2P 4
291#define Tiny0 0x100000
292#define Tiny1 0
293#define Quick_max 14
294#define Int_max 15
295#else /* VAX */
296#define Exp_shift 23
297#define Exp_shift1 7
298#define Exp_msk1 0x80
299#define Exp_msk11 0x800000
300#define Exp_mask 0x7f80
301#define P 56
302#define Bias 129
303#define Exp_1 0x40800000
304#define Exp_11 0x4080
305#define Ebits 8
306#define Frac_mask 0x7fffff
307#define Frac_mask1 0xffff007f
308#define Ten_pmax 24
309#define Bletch 2
310#define Bndry_mask 0xffff007f
311#define Bndry_mask1 0xffff007f
312#define LSB 0x10000
313#define Sign_bit 0x8000
314#define Log2P 1
315#define Tiny0 0x80
316#define Tiny1 0
317#define Quick_max 15
318#define Int_max 15
319#endif
320#endif
321
322#ifndef IEEE_Arith
323#define ROUND_BIASED
324#endif
325
326#ifdef RND_PRODQUOT
327#define rounded_product(a,b) a = rnd_prod(a, b)
328#define rounded_quotient(a,b) a = rnd_quot(a, b)
329#ifdef KR_headers
330extern double rnd_prod(), rnd_quot();
331#else
332extern double rnd_prod(double, double), rnd_quot(double, double);
333#endif
334#else
335#define rounded_product(a,b) a *= b
336#define rounded_quotient(a,b) a /= b
337#endif
338
339#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1))
340#define Big1 0xffffffff
341
342#ifndef Just_16
343/* When Pack_32 is not defined, we store 16 bits per 32-bit Long.
344 * This makes some inner loops simpler and sometimes saves work
345 * during multiplications, but it often seems to make things slightly
346 * slower. Hence the default is now to store 32 bits per Long.
347 */
348#ifndef Pack_32
349#define Pack_32
350#endif
351#endif
352
353#define Kmax 15
354
355#ifdef __cplusplus
356extern "C" double strtod(const char *s00, char **se);
357extern "C" char *__dtoa(double d, int mode, int ndigits,
358 int *decpt, int *sign, char **rve);
359#endif
360
361 struct
362Bigint {
363 struct Bigint *next;
364 int k, maxwds, sign, wds;
365 ULong x[1];
366 };
367
368 typedef struct Bigint Bigint;
369
370 static Bigint *freelist[Kmax+1];
371
372 static Bigint *
373Balloc
374#ifdef KR_headers
375 (k) int k;
376#else
377 (int k)
378#endif
379{
380 int x;
381 Bigint *rv;
382
383 if (rv = freelist[k]) {
384 freelist[k] = rv->next;
385 }
386 else {
387 x = 1 << k;
388 rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(Long));
389 rv->k = k;
390 rv->maxwds = x;
391 }
392 rv->sign = rv->wds = 0;
393 return rv;
394 }
395
396 static void
397Bfree
398#ifdef KR_headers
399 (v) Bigint *v;
400#else
401 (Bigint *v)
402#endif
403{
404 if (v) {
405 v->next = freelist[v->k];
406 freelist[v->k] = v;
407 }
408 }
409
410#define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \
411y->wds*sizeof(Long) + 2*sizeof(int))
412
413 static Bigint *
414multadd
415#ifdef KR_headers
416 (b, m, a) Bigint *b; int m, a;
417#else
418 (Bigint *b, int m, int a) /* multiply by m and add a */
419#endif
420{
421 int i, wds;
422 ULong *x, y;
423#ifdef Pack_32
424 ULong xi, z;
425#endif
426 Bigint *b1;
427
428 wds = b->wds;
429 x = b->x;
430 i = 0;
431 do {
432#ifdef Pack_32
433 xi = *x;
434 y = (xi & 0xffff) * m + a;
435 z = (xi >> 16) * m + (y >> 16);
436 a = (int)(z >> 16);
437 *x++ = (z << 16) + (y & 0xffff);
438#else
439 y = *x * m + a;
440 a = (int)(y >> 16);
441 *x++ = y & 0xffff;
442#endif
443 }
444 while(++i < wds);
445 if (a) {
446 if (wds >= b->maxwds) {
447 b1 = Balloc(b->k+1);
448 Bcopy(b1, b);
449 Bfree(b);
450 b = b1;
451 }
452 b->x[wds++] = a;
453 b->wds = wds;
454 }
455 return b;
456 }
457
458 static Bigint *
459s2b
460#ifdef KR_headers
461 (s, nd0, nd, y9) CONST char *s; int nd0, nd; ULong y9;
462#else
463 (CONST char *s, int nd0, int nd, ULong y9)
464#endif
465{
466 Bigint *b;
467 int i, k;
468 Long x, y;
469
470 x = (nd + 8) / 9;
471 for(k = 0, y = 1; x > y; y <<= 1, k++) ;
472#ifdef Pack_32
473 b = Balloc(k);
474 b->x[0] = y9;
475 b->wds = 1;
476#else
477 b = Balloc(k+1);
478 b->x[0] = y9 & 0xffff;
479 b->wds = (b->x[1] = y9 >> 16) ? 2 : 1;
480#endif
481
482 i = 9;
483 if (9 < nd0) {
484 s += 9;
485 do b = multadd(b, 10, *s++ - '0');
486 while(++i < nd0);
487 s++;
488 }
489 else
490 s += 10;
491 for(; i < nd; i++)
492 b = multadd(b, 10, *s++ - '0');
493 return b;
494 }
495
496 static int
497hi0bits
498#ifdef KR_headers
499 (x) register ULong x;
500#else
501 (register ULong x)
502#endif
503{
504 register int k = 0;
505
506 if (!(x & 0xffff0000)) {
507 k = 16;
508 x <<= 16;
509 }
510 if (!(x & 0xff000000)) {
511 k += 8;
512 x <<= 8;
513 }
514 if (!(x & 0xf0000000)) {
515 k += 4;
516 x <<= 4;
517 }
518 if (!(x & 0xc0000000)) {
519 k += 2;
520 x <<= 2;
521 }
522 if (!(x & 0x80000000)) {
523 k++;
524 if (!(x & 0x40000000))
525 return 32;
526 }
527 return k;
528 }
529
530 static int
531lo0bits
532#ifdef KR_headers
533 (y) ULong *y;
534#else
535 (ULong *y)
536#endif
537{
538 register int k;
539 register ULong x = *y;
540
541 if (x & 7) {
542 if (x & 1)
543 return 0;
544 if (x & 2) {
545 *y = x >> 1;
546 return 1;
547 }
548 *y = x >> 2;
549 return 2;
550 }
551 k = 0;
552 if (!(x & 0xffff)) {
553 k = 16;
554 x >>= 16;
555 }
556 if (!(x & 0xff)) {
557 k += 8;
558 x >>= 8;
559 }
560 if (!(x & 0xf)) {
561 k += 4;
562 x >>= 4;
563 }
564 if (!(x & 0x3)) {
565 k += 2;
566 x >>= 2;
567 }
568 if (!(x & 1)) {
569 k++;
570 x >>= 1;
571 if (!x & 1)
572 return 32;
573 }
574 *y = x;
575 return k;
576 }
577
578 static Bigint *
579i2b
580#ifdef KR_headers
581 (i) int i;
582#else
583 (int i)
584#endif
585{
586 Bigint *b;
587
588 b = Balloc(1);
589 b->x[0] = i;
590 b->wds = 1;
591 return b;
592 }
593
594 static Bigint *
595mult
596#ifdef KR_headers
597 (a, b) Bigint *a, *b;
598#else
599 (Bigint *a, Bigint *b)
600#endif
601{
602 Bigint *c;
603 int k, wa, wb, wc;
604 ULong carry, y, z;
605 ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
606#ifdef Pack_32
607 ULong z2;
608#endif
609
610 if (a->wds < b->wds) {
611 c = a;
612 a = b;
613 b = c;
614 }
615 k = a->k;
616 wa = a->wds;
617 wb = b->wds;
618 wc = wa + wb;
619 if (wc > a->maxwds)
620 k++;
621 c = Balloc(k);
622 for(x = c->x, xa = x + wc; x < xa; x++)
623 *x = 0;
624 xa = a->x;
625 xae = xa + wa;
626 xb = b->x;
627 xbe = xb + wb;
628 xc0 = c->x;
629#ifdef Pack_32
630 for(; xb < xbe; xb++, xc0++) {
631 if (y = *xb & 0xffff) {
632 x = xa;
633 xc = xc0;
634 carry = 0;
635 do {
636 z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
637 carry = z >> 16;
638 z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
639 carry = z2 >> 16;
640 Storeinc(xc, z2, z);
641 }
642 while(x < xae);
643 *xc = carry;
644 }
645 if (y = *xb >> 16) {
646 x = xa;
647 xc = xc0;
648 carry = 0;
649 z2 = *xc;
650 do {
651 z = (*x & 0xffff) * y + (*xc >> 16) + carry;
652 carry = z >> 16;
653 Storeinc(xc, z, z2);
654 z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
655 carry = z2 >> 16;
656 }
657 while(x < xae);
658 *xc = z2;
659 }
660 }
661#else
662 for(; xb < xbe; xc0++) {
663 if (y = *xb++) {
664 x = xa;
665 xc = xc0;
666 carry = 0;
667 do {
668 z = *x++ * y + *xc + carry;
669 carry = z >> 16;
670 *xc++ = z & 0xffff;
671 }
672 while(x < xae);
673 *xc = carry;
674 }
675 }
676#endif
677 for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
678 c->wds = wc;
679 return c;
680 }
681
682 static Bigint *p5s;
683
684 static Bigint *
685pow5mult
686#ifdef KR_headers
687 (b, k) Bigint *b; int k;
688#else
689 (Bigint *b, int k)
690#endif
691{
692 Bigint *b1, *p5, *p51;
693 int i;
694 static int p05[3] = { 5, 25, 125 };
695
696 if (i = k & 3)
697 b = multadd(b, p05[i-1], 0);
698
699 if (!(k >>= 2))
700 return b;
701 if (!(p5 = p5s)) {
702 /* first time */
703 p5 = p5s = i2b(625);
704 p5->next = 0;
705 }
706 for(;;) {
707 if (k & 1) {
708 b1 = mult(b, p5);
709 Bfree(b);
710 b = b1;
711 }
712 if (!(k >>= 1))
713 break;
714 if (!(p51 = p5->next)) {
715 p51 = p5->next = mult(p5,p5);
716 p51->next = 0;
717 }
718 p5 = p51;
719 }
720 return b;
721 }
722
723 static Bigint *
724lshift
725#ifdef KR_headers
726 (b, k) Bigint *b; int k;
727#else
728 (Bigint *b, int k)
729#endif
730{
731 int i, k1, n, n1;
732 Bigint *b1;
733 ULong *x, *x1, *xe, z;
734
735#ifdef Pack_32
736 n = k >> 5;
737#else
738 n = k >> 4;
739#endif
740 k1 = b->k;
741 n1 = n + b->wds + 1;
742 for(i = b->maxwds; n1 > i; i <<= 1)
743 k1++;
744 b1 = Balloc(k1);
745 x1 = b1->x;
746 for(i = 0; i < n; i++)
747 *x1++ = 0;
748 x = b->x;
749 xe = x + b->wds;
750#ifdef Pack_32
751 if (k &= 0x1f) {
752 k1 = 32 - k;
753 z = 0;
754 do {
755 *x1++ = *x << k | z;
756 z = *x++ >> k1;
757 }
758 while(x < xe);
759 if (*x1 = z)
760 ++n1;
761 }
762#else
763 if (k &= 0xf) {
764 k1 = 16 - k;
765 z = 0;
766 do {
767 *x1++ = *x << k & 0xffff | z;
768 z = *x++ >> k1;
769 }
770 while(x < xe);
771 if (*x1 = z)
772 ++n1;
773 }
774#endif
775 else do
776 *x1++ = *x++;
777 while(x < xe);
778 b1->wds = n1 - 1;
779 Bfree(b);
780 return b1;
781 }
782
783 static int
784cmp
785#ifdef KR_headers
786 (a, b) Bigint *a, *b;
787#else
788 (Bigint *a, Bigint *b)
789#endif
790{
791 ULong *xa, *xa0, *xb, *xb0;
792 int i, j;
793
794 i = a->wds;
795 j = b->wds;
796#ifdef DEBUG
797 if (i > 1 && !a->x[i-1])
798 Bug("cmp called with a->x[a->wds-1] == 0");
799 if (j > 1 && !b->x[j-1])
800 Bug("cmp called with b->x[b->wds-1] == 0");
801#endif
802 if (i -= j)
803 return i;
804 xa0 = a->x;
805 xa = xa0 + j;
806 xb0 = b->x;
807 xb = xb0 + j;
808 for(;;) {
809 if (*--xa != *--xb)
810 return *xa < *xb ? -1 : 1;
811 if (xa <= xa0)
812 break;
813 }
814 return 0;
815 }
816
817 static Bigint *
818diff
819#ifdef KR_headers
820 (a, b) Bigint *a, *b;
821#else
822 (Bigint *a, Bigint *b)
823#endif
824{
825 Bigint *c;
826 int i, wa, wb;
827 Long borrow, y; /* We need signed shifts here. */
828 ULong *xa, *xae, *xb, *xbe, *xc;
829#ifdef Pack_32
830 Long z;
831#endif
832
833 i = cmp(a,b);
834 if (!i) {
835 c = Balloc(0);
836 c->wds = 1;
837 c->x[0] = 0;
838 return c;
839 }
840 if (i < 0) {
841 c = a;
842 a = b;
843 b = c;
844 i = 1;
845 }
846 else
847 i = 0;
848 c = Balloc(a->k);
849 c->sign = i;
850 wa = a->wds;
851 xa = a->x;
852 xae = xa + wa;
853 wb = b->wds;
854 xb = b->x;
855 xbe = xb + wb;
856 xc = c->x;
857 borrow = 0;
858#ifdef Pack_32
859 do {
860 y = (*xa & 0xffff) - (*xb & 0xffff) + borrow;
861 borrow = y >> 16;
862 Sign_Extend(borrow, y);
863 z = (*xa++ >> 16) - (*xb++ >> 16) + borrow;
864 borrow = z >> 16;
865 Sign_Extend(borrow, z);
866 Storeinc(xc, z, y);
867 }
868 while(xb < xbe);
869 while(xa < xae) {
870 y = (*xa & 0xffff) + borrow;
871 borrow = y >> 16;
872 Sign_Extend(borrow, y);
873 z = (*xa++ >> 16) + borrow;
874 borrow = z >> 16;
875 Sign_Extend(borrow, z);
876 Storeinc(xc, z, y);
877 }
878#else
879 do {
880 y = *xa++ - *xb++ + borrow;
881 borrow = y >> 16;
882 Sign_Extend(borrow, y);
883 *xc++ = y & 0xffff;
884 }
885 while(xb < xbe);
886 while(xa < xae) {
887 y = *xa++ + borrow;
888 borrow = y >> 16;
889 Sign_Extend(borrow, y);
890 *xc++ = y & 0xffff;
891 }
892#endif
893 while(!*--xc)
894 wa--;
895 c->wds = wa;
896 return c;
897 }
898
899 static double
900ulp
901#ifdef KR_headers
902 (x) double x;
903#else
904 (double x)
905#endif
906{
907 register Long L;
908 double a;
909
910 L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1;
911#ifndef Sudden_Underflow
912 if (L > 0) {
913#endif
914#ifdef IBM
915 L |= Exp_msk1 >> 4;
916#endif
917 word0(a) = L;
918 word1(a) = 0;
919#ifndef Sudden_Underflow
920 }
921 else {
922 L = -L >> Exp_shift;
923 if (L < Exp_shift) {
924 word0(a) = 0x80000 >> L;
925 word1(a) = 0;
926 }
927 else {
928 word0(a) = 0;
929 L -= Exp_shift;
930 word1(a) = L >= 31 ? 1 : 1 << 31 - L;
931 }
932 }
933#endif
934 return a;
935 }
936
937 static double
938b2d
939#ifdef KR_headers
940 (a, e) Bigint *a; int *e;
941#else
942 (Bigint *a, int *e)
943#endif
944{
945 ULong *xa, *xa0, w, y, z;
946 int k;
947 double d;
948#ifdef VAX
949 ULong d0, d1;
950#else
951#define d0 word0(d)
952#define d1 word1(d)
953#endif
954
955 xa0 = a->x;
956 xa = xa0 + a->wds;
957 y = *--xa;
958#ifdef DEBUG
959 if (!y) Bug("zero y in b2d");
960#endif
961 k = hi0bits(y);
962 *e = 32 - k;
963#ifdef Pack_32
964 if (k < Ebits) {
965 d0 = Exp_1 | y >> Ebits - k;
966 w = xa > xa0 ? *--xa : 0;
967 d1 = y << (32-Ebits) + k | w >> Ebits - k;
968 goto ret_d;
969 }
970 z = xa > xa0 ? *--xa : 0;
971 if (k -= Ebits) {
972 d0 = Exp_1 | y << k | z >> 32 - k;
973 y = xa > xa0 ? *--xa : 0;
974 d1 = z << k | y >> 32 - k;
975 }
976 else {
977 d0 = Exp_1 | y;
978 d1 = z;
979 }
980#else
981 if (k < Ebits + 16) {
982 z = xa > xa0 ? *--xa : 0;
983 d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
984 w = xa > xa0 ? *--xa : 0;
985 y = xa > xa0 ? *--xa : 0;
986 d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
987 goto ret_d;
988 }
989 z = xa > xa0 ? *--xa : 0;
990 w = xa > xa0 ? *--xa : 0;
991 k -= Ebits + 16;
992 d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
993 y = xa > xa0 ? *--xa : 0;
994 d1 = w << k + 16 | y << k;
995#endif
996 ret_d:
997#ifdef VAX
998 word0(d) = d0 >> 16 | d0 << 16;
999 word1(d) = d1 >> 16 | d1 << 16;
1000#else
1001#undef d0
1002#undef d1
1003#endif
1004 return d;
1005 }
1006
1007 static Bigint *
1008d2b
1009#ifdef KR_headers
1010 (d, e, bits) double d; int *e, *bits;
1011#else
1012 (double d, int *e, int *bits)
1013#endif
1014{
1015 Bigint *b;
1016 int de, i, k;
1017 ULong *x, y, z;
1018#ifdef VAX
1019 ULong d0, d1;
1020 d0 = word0(d) >> 16 | word0(d) << 16;
1021 d1 = word1(d) >> 16 | word1(d) << 16;
1022#else
1023#define d0 word0(d)
1024#define d1 word1(d)
1025#endif
1026
1027#ifdef Pack_32
1028 b = Balloc(1);
1029#else
1030 b = Balloc(2);
1031#endif
1032 x = b->x;
1033
1034 z = d0 & Frac_mask;
1035 d0 &= 0x7fffffff; /* clear sign bit, which we ignore */
1036#ifdef Sudden_Underflow
1037 de = (int)(d0 >> Exp_shift);
1038#ifndef IBM
1039 z |= Exp_msk11;
1040#endif
1041#else
1042 if (de = (int)(d0 >> Exp_shift))
1043 z |= Exp_msk1;
1044#endif
1045#ifdef Pack_32
1046 if (y = d1) {
1047 if (k = lo0bits(&y)) {
1048 x[0] = y | z << 32 - k;
1049 z >>= k;
1050 }
1051 else
1052 x[0] = y;
1053 i = b->wds = (x[1] = z) ? 2 : 1;
1054 }
1055 else {
1056#ifdef DEBUG
1057 if (!z)
1058 Bug("Zero passed to d2b");
1059#endif
1060 k = lo0bits(&z);
1061 x[0] = z;
1062 i = b->wds = 1;
1063 k += 32;
1064 }
1065#else
1066 if (y = d1) {
1067 if (k = lo0bits(&y))
1068 if (k >= 16) {
1069 x[0] = y | z << 32 - k & 0xffff;
1070 x[1] = z >> k - 16 & 0xffff;
1071 x[2] = z >> k;
1072 i = 2;
1073 }
1074 else {
1075 x[0] = y & 0xffff;
1076 x[1] = y >> 16 | z << 16 - k & 0xffff;
1077 x[2] = z >> k & 0xffff;
1078 x[3] = z >> k+16;
1079 i = 3;
1080 }
1081 else {
1082 x[0] = y & 0xffff;
1083 x[1] = y >> 16;
1084 x[2] = z & 0xffff;
1085 x[3] = z >> 16;
1086 i = 3;
1087 }
1088 }
1089 else {
1090#ifdef DEBUG
1091 if (!z)
1092 Bug("Zero passed to d2b");
1093#endif
1094 k = lo0bits(&z);
1095 if (k >= 16) {
1096 x[0] = z;
1097 i = 0;
1098 }
1099 else {
1100 x[0] = z & 0xffff;
1101 x[1] = z >> 16;
1102 i = 1;
1103 }
1104 k += 32;
1105 }
1106 while(!x[i])
1107 --i;
1108 b->wds = i + 1;
1109#endif
1110#ifndef Sudden_Underflow
1111 if (de) {
1112#endif
1113#ifdef IBM
1114 *e = (de - Bias - (P-1) << 2) + k;
1115 *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask);
1116#else
1117 *e = de - Bias - (P-1) + k;
1118 *bits = P - k;
1119#endif
1120#ifndef Sudden_Underflow
1121 }
1122 else {
1123 *e = de - Bias - (P-1) + 1 + k;
1124#ifdef Pack_32
1125 *bits = 32*i - hi0bits(x[i-1]);
1126#else
1127 *bits = (i+2)*16 - hi0bits(x[i]);
1128#endif
1129 }
1130#endif
1131 return b;
1132 }
1133#undef d0
1134#undef d1
1135
1136 static double
1137ratio
1138#ifdef KR_headers
1139 (a, b) Bigint *a, *b;
1140#else
1141 (Bigint *a, Bigint *b)
1142#endif
1143{
1144 double da, db;
1145 int k, ka, kb;
1146
1147 da = b2d(a, &ka);
1148 db = b2d(b, &kb);
1149#ifdef Pack_32
1150 k = ka - kb + 32*(a->wds - b->wds);
1151#else
1152 k = ka - kb + 16*(a->wds - b->wds);
1153#endif
1154#ifdef IBM
1155 if (k > 0) {
1156 word0(da) += (k >> 2)*Exp_msk1;
1157 if (k &= 3)
1158 da *= 1 << k;
1159 }
1160 else {
1161 k = -k;
1162 word0(db) += (k >> 2)*Exp_msk1;
1163 if (k &= 3)
1164 db *= 1 << k;
1165 }
1166#else
1167 if (k > 0)
1168 word0(da) += k*Exp_msk1;
1169 else {
1170 k = -k;
1171 word0(db) += k*Exp_msk1;
1172 }
1173#endif
1174 return da / db;
1175 }
1176
1177static CONST double
1178tens[] = {
1179 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
1180 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
1181 1e20, 1e21, 1e22
1182#ifdef VAX
1183 , 1e23, 1e24
1184#endif
1185 };
1186
1187#ifdef IEEE_Arith
1188static CONST double bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
1189static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
1190#define n_bigtens 5
1191#else
1192#ifdef IBM
1193static CONST double bigtens[] = { 1e16, 1e32, 1e64 };
1194static CONST double tinytens[] = { 1e-16, 1e-32, 1e-64 };
1195#define n_bigtens 3
1196#else
1197static CONST double bigtens[] = { 1e16, 1e32 };
1198static CONST double tinytens[] = { 1e-16, 1e-32 };
1199#define n_bigtens 2
1200#endif
1201#endif
1202
1203 double
1204strtod
1205#ifdef KR_headers
1206 (s00, se) CONST char *s00; char **se;
1207#else
1208 (CONST char *s00, char **se)
1209#endif
1210{
1211 int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
1212 e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
1213 CONST char *s, *s0, *s1;
1214 double aadj, aadj1, adj, rv, rv0;
1215 Long L;
1216 ULong y, z;
1217 Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
1218
1219#ifndef KR_headers
1220 CONST char decimal_point = localeconv()->decimal_point[0];
1221#else
1222 CONST char decimal_point = '.';
1223#endif
1224
1225 sign = nz0 = nz = 0;
1226 rv = 0.;
1227
1228
1229 for(s = s00; isspace(*s); s++)
1230 ;
1231
1232 if (*s == '-') {
1233 sign = 1;
1234 s++;
1235 } else if (*s == '+') {
1236 s++;
1237 }
1238
1239 if (*s == '\0') {
1240 s = s00;
1241 goto ret;
1242 }
1243
1244 if (*s == '0') {
1245 nz0 = 1;
1246 while(*++s == '0') ;
1247 if (!*s)
1248 goto ret;
1249 }
1250 s0 = s;
1251 y = z = 0;
1252 for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
1253 if (nd < 9)
1254 y = 10*y + c - '0';
1255 else if (nd < 16)
1256 z = 10*z + c - '0';
1257 nd0 = nd;
1258 if (c == decimal_point) {
1259 c = *++s;
1260 if (!nd) {
1261 for(; c == '0'; c = *++s)
1262 nz++;
1263 if (c > '0' && c <= '9') {
1264 s0 = s;
1265 nf += nz;
1266 nz = 0;
1267 goto have_dig;
1268 }
1269 goto dig_done;
1270 }
1271 for(; c >= '0' && c <= '9'; c = *++s) {
1272 have_dig:
1273 nz++;
1274 if (c -= '0') {
1275 nf += nz;
1276 for(i = 1; i < nz; i++)
1277 if (nd++ < 9)
1278 y *= 10;
1279 else if (nd <= DBL_DIG + 1)
1280 z *= 10;
1281 if (nd++ < 9)
1282 y = 10*y + c;
1283 else if (nd <= DBL_DIG + 1)
1284 z = 10*z + c;
1285 nz = 0;
1286 }
1287 }
1288 }
1289 dig_done:
1290 e = 0;
1291 if (c == 'e' || c == 'E') {
1292 if (!nd && !nz && !nz0) {
1293 s = s00;
1294 goto ret;
1295 }
1296 s00 = s;
1297 esign = 0;
1298 switch(c = *++s) {
1299 case '-':
1300 esign = 1;
1301 case '+':
1302 c = *++s;
1303 }
1304 if (c >= '0' && c <= '9') {
1305 while(c == '0')
1306 c = *++s;
1307 if (c > '0' && c <= '9') {
1308 L = c - '0';
1309 s1 = s;
1310 while((c = *++s) >= '0' && c <= '9')
1311 L = 10*L + c - '0';
1312 if (s - s1 > 8 || L > 19999)
1313 /* Avoid confusion from exponents
1314 * so large that e might overflow.
1315 */
1316 e = 19999; /* safe for 16 bit ints */
1317 else
1318 e = (int)L;
1319 if (esign)
1320 e = -e;
1321 }
1322 else
1323 e = 0;
1324 }
1325 else
1326 s = s00;
1327 }
1328 if (!nd) {
1329 if (!nz && !nz0)
1330 s = s00;
1331 goto ret;
1332 }
1333 e1 = e -= nf;
1334
1335 /* Now we have nd0 digits, starting at s0, followed by a
1336 * decimal point, followed by nd-nd0 digits. The number we're
1337 * after is the integer represented by those digits times
1338 * 10**e */
1339
1340 if (!nd0)
1341 nd0 = nd;
1342 k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
1343 rv = y;
1344 if (k > 9)
1345 rv = tens[k - 9] * rv + z;
1346 bd0 = 0;
1347 if (nd <= DBL_DIG
1348#ifndef RND_PRODQUOT
1349 && FLT_ROUNDS == 1
1350#endif
1351 ) {
1352 if (!e)
1353 goto ret;
1354 if (e > 0) {
1355 if (e <= Ten_pmax) {
1356#ifdef VAX
1357 goto vax_ovfl_check;
1358#else
1359 /* rv = */ rounded_product(rv, tens[e]);
1360 goto ret;
1361#endif
1362 }
1363 i = DBL_DIG - nd;
1364 if (e <= Ten_pmax + i) {
1365 /* A fancier test would sometimes let us do
1366 * this for larger i values.
1367 */
1368 e -= i;
1369 rv *= tens[i];
1370#ifdef VAX
1371 /* VAX exponent range is so narrow we must
1372 * worry about overflow here...
1373 */
1374 vax_ovfl_check:
1375 word0(rv) -= P*Exp_msk1;
1376 /* rv = */ rounded_product(rv, tens[e]);
1377 if ((word0(rv) & Exp_mask)
1378 > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
1379 goto ovfl;
1380 word0(rv) += P*Exp_msk1;
1381#else
1382 /* rv = */ rounded_product(rv, tens[e]);
1383#endif
1384 goto ret;
1385 }
1386 }
1387#ifndef Inaccurate_Divide
1388 else if (e >= -Ten_pmax) {
1389 /* rv = */ rounded_quotient(rv, tens[-e]);
1390 goto ret;
1391 }
1392#endif
1393 }
1394 e1 += nd - k;
1395
1396 /* Get starting approximation = rv * 10**e1 */
1397
1398 if (e1 > 0) {
1399 if (i = e1 & 15)
1400 rv *= tens[i];
1401 if (e1 &= ~15) {
1402 if (e1 > DBL_MAX_10_EXP) {
1403 ovfl:
1404 errno = ERANGE;
1405#ifdef __STDC__
1406 rv = HUGE_VAL;
1407#else
1408 /* Can't trust HUGE_VAL */
1409#ifdef IEEE_Arith
1410 word0(rv) = Exp_mask;
1411 word1(rv) = 0;
1412#else
1413 word0(rv) = Big0;
1414 word1(rv) = Big1;
1415#endif
1416#endif
1417 if (bd0)
1418 goto retfree;
1419 goto ret;
1420 }
1421 if (e1 >>= 4) {
1422 for(j = 0; e1 > 1; j++, e1 >>= 1)
1423 if (e1 & 1)
1424 rv *= bigtens[j];
1425 /* The last multiplication could overflow. */
1426 word0(rv) -= P*Exp_msk1;
1427 rv *= bigtens[j];
1428 if ((z = word0(rv) & Exp_mask)
1429 > Exp_msk1*(DBL_MAX_EXP+Bias-P))
1430 goto ovfl;
1431 if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {
1432 /* set to largest number */
1433 /* (Can't trust DBL_MAX) */
1434 word0(rv) = Big0;
1435 word1(rv) = Big1;
1436 }
1437 else
1438 word0(rv) += P*Exp_msk1;
1439 }
1440
1441 }
1442 }
1443 else if (e1 < 0) {
1444 e1 = -e1;
1445 if (i = e1 & 15)
1446 rv /= tens[i];
1447 if (e1 &= ~15) {
1448 e1 >>= 4;
1449 if (e1 >= 1 << n_bigtens)
1450 goto undfl;
1451 for(j = 0; e1 > 1; j++, e1 >>= 1)
1452 if (e1 & 1)
1453 rv *= tinytens[j];
1454 /* The last multiplication could underflow. */
1455 rv0 = rv;
1456 rv *= tinytens[j];
1457 if (!rv) {
1458 rv = 2.*rv0;
1459 rv *= tinytens[j];
1460 if (!rv) {
1461 undfl:
1462 rv = 0.;
1463 errno = ERANGE;
1464 if (bd0)
1465 goto retfree;
1466 goto ret;
1467 }
1468 word0(rv) = Tiny0;
1469 word1(rv) = Tiny1;
1470 /* The refinement below will clean
1471 * this approximation up.
1472 */
1473 }
1474 }
1475 }
1476
1477 /* Now the hard part -- adjusting rv to the correct value.*/
1478
1479 /* Put digits into bd: true value = bd * 10^e */
1480
1481 bd0 = s2b(s0, nd0, nd, y);
1482
1483 for(;;) {
1484 bd = Balloc(bd0->k);
1485 Bcopy(bd, bd0);
1486 bb = d2b(rv, &bbe, &bbbits); /* rv = bb * 2^bbe */
1487 bs = i2b(1);
1488
1489 if (e >= 0) {
1490 bb2 = bb5 = 0;
1491 bd2 = bd5 = e;
1492 }
1493 else {
1494 bb2 = bb5 = -e;
1495 bd2 = bd5 = 0;
1496 }
1497 if (bbe >= 0)
1498 bb2 += bbe;
1499 else
1500 bd2 -= bbe;
1501 bs2 = bb2;
1502#ifdef Sudden_Underflow
1503#ifdef IBM
1504 j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3);
1505#else
1506 j = P + 1 - bbbits;
1507#endif
1508#else
1509 i = bbe + bbbits - 1; /* logb(rv) */
1510 if (i < Emin) /* denormal */
1511 j = bbe + (P-Emin);
1512 else
1513 j = P + 1 - bbbits;
1514#endif
1515 bb2 += j;
1516 bd2 += j;
1517 i = bb2 < bd2 ? bb2 : bd2;
1518 if (i > bs2)
1519 i = bs2;
1520 if (i > 0) {
1521 bb2 -= i;
1522 bd2 -= i;
1523 bs2 -= i;
1524 }
1525 if (bb5 > 0) {
1526 bs = pow5mult(bs, bb5);
1527 bb1 = mult(bs, bb);
1528 Bfree(bb);
1529 bb = bb1;
1530 }
1531 if (bb2 > 0)
1532 bb = lshift(bb, bb2);
1533 if (bd5 > 0)
1534 bd = pow5mult(bd, bd5);
1535 if (bd2 > 0)
1536 bd = lshift(bd, bd2);
1537 if (bs2 > 0)
1538 bs = lshift(bs, bs2);
1539 delta = diff(bb, bd);
1540 dsign = delta->sign;
1541 delta->sign = 0;
1542 i = cmp(delta, bs);
1543 if (i < 0) {
1544 /* Error is less than half an ulp -- check for
1545 * special case of mantissa a power of two.
1546 */
1547 if (dsign || word1(rv) || word0(rv) & Bndry_mask)
1548 break;
1549 delta = lshift(delta,Log2P);
1550 if (cmp(delta, bs) > 0)
1551 goto drop_down;
1552 break;
1553 }
1554 if (i == 0) {
1555 /* exactly half-way between */
1556 if (dsign) {
1557 if ((word0(rv) & Bndry_mask1) == Bndry_mask1
1558 && word1(rv) == 0xffffffff) {
1559 /*boundary case -- increment exponent*/
1560 word0(rv) = (word0(rv) & Exp_mask)
1561 + Exp_msk1
1562#ifdef IBM
1563 | Exp_msk1 >> 4
1564#endif
1565 ;
1566 word1(rv) = 0;
1567 break;
1568 }
1569 }
1570 else if (!(word0(rv) & Bndry_mask) && !word1(rv)) {
1571 drop_down:
1572 /* boundary case -- decrement exponent */
1573#ifdef Sudden_Underflow
1574 L = word0(rv) & Exp_mask;
1575#ifdef IBM
1576 if (L < Exp_msk1)
1577#else
1578 if (L <= Exp_msk1)
1579#endif
1580 goto undfl;
1581 L -= Exp_msk1;
1582#else
1583 L = (word0(rv) & Exp_mask) - Exp_msk1;
1584#endif
1585 word0(rv) = L | Bndry_mask1;
1586 word1(rv) = 0xffffffff;
1587#ifdef IBM
1588 goto cont;
1589#else
1590 break;
1591#endif
1592 }
1593#ifndef ROUND_BIASED
1594 if (!(word1(rv) & LSB))
1595 break;
1596#endif
1597 if (dsign)
1598 rv += ulp(rv);
1599#ifndef ROUND_BIASED
1600 else {
1601 rv -= ulp(rv);
1602#ifndef Sudden_Underflow
1603 if (!rv)
1604 goto undfl;
1605#endif
1606 }
1607#endif
1608 break;
1609 }
1610 if ((aadj = ratio(delta, bs)) <= 2.) {
1611 if (dsign)
1612 aadj = aadj1 = 1.;
1613 else if (word1(rv) || word0(rv) & Bndry_mask) {
1614#ifndef Sudden_Underflow
1615 if (word1(rv) == Tiny1 && !word0(rv))
1616 goto undfl;
1617#endif
1618 aadj = 1.;
1619 aadj1 = -1.;
1620 }
1621 else {
1622 /* special case -- power of FLT_RADIX to be */
1623 /* rounded down... */
1624
1625 if (aadj < 2./FLT_RADIX)
1626 aadj = 1./FLT_RADIX;
1627 else
1628 aadj *= 0.5;
1629 aadj1 = -aadj;
1630 }
1631 }
1632 else {
1633 aadj *= 0.5;
1634 aadj1 = dsign ? aadj : -aadj;
1635#ifdef Check_FLT_ROUNDS
1636 switch(FLT_ROUNDS) {
1637 case 2: /* towards +infinity */
1638 aadj1 -= 0.5;
1639 break;
1640 case 0: /* towards 0 */
1641 case 3: /* towards -infinity */
1642 aadj1 += 0.5;
1643 }
1644#else
1645 if (FLT_ROUNDS == 0)
1646 aadj1 += 0.5;
1647#endif
1648 }
1649 y = word0(rv) & Exp_mask;
1650
1651 /* Check for overflow */
1652
1653 if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
1654 rv0 = rv;
1655 word0(rv) -= P*Exp_msk1;
1656 adj = aadj1 * ulp(rv);
1657 rv += adj;
1658 if ((word0(rv) & Exp_mask) >=
1659 Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
1660 if (word0(rv0) == Big0 && word1(rv0) == Big1)
1661 goto ovfl;
1662 word0(rv) = Big0;
1663 word1(rv) = Big1;
1664 goto cont;
1665 }
1666 else
1667 word0(rv) += P*Exp_msk1;
1668 }
1669 else {
1670#ifdef Sudden_Underflow
1671 if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
1672 rv0 = rv;
1673 word0(rv) += P*Exp_msk1;
1674 adj = aadj1 * ulp(rv);
1675 rv += adj;
1676#ifdef IBM
1677 if ((word0(rv) & Exp_mask) < P*Exp_msk1)
1678#else
1679 if ((word0(rv) & Exp_mask) <= P*Exp_msk1)
1680#endif
1681 {
1682 if (word0(rv0) == Tiny0
1683 && word1(rv0) == Tiny1)
1684 goto undfl;
1685 word0(rv) = Tiny0;
1686 word1(rv) = Tiny1;
1687 goto cont;
1688 }
1689 else
1690 word0(rv) -= P*Exp_msk1;
1691 }
1692 else {
1693 adj = aadj1 * ulp(rv);
1694 rv += adj;
1695 }
1696#else
1697 /* Compute adj so that the IEEE rounding rules will
1698 * correctly round rv + adj in some half-way cases.
1699 * If rv * ulp(rv) is denormalized (i.e.,
1700 * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid
1701 * trouble from bits lost to denormalization;
1702 * example: 1.2e-307 .
1703 */
1704 if (y <= (P-1)*Exp_msk1 && aadj >= 1.) {
1705 aadj1 = (double)(int)(aadj + 0.5);
1706 if (!dsign)
1707 aadj1 = -aadj1;
1708 }
1709 adj = aadj1 * ulp(rv);
1710 rv += adj;
1711#endif
1712 }
1713 z = word0(rv) & Exp_mask;
1714 if (y == z) {
1715 /* Can we stop now? */
1716 L = aadj;
1717 aadj -= L;
1718 /* The tolerances below are conservative. */
1719 if (dsign || word1(rv) || word0(rv) & Bndry_mask) {
1720 if (aadj < .4999999 || aadj > .5000001)
1721 break;
1722 }
1723 else if (aadj < .4999999/FLT_RADIX)
1724 break;
1725 }
1726 cont:
1727 Bfree(bb);
1728 Bfree(bd);
1729 Bfree(bs);
1730 Bfree(delta);
1731 }
1732 retfree:
1733 Bfree(bb);
1734 Bfree(bd);
1735 Bfree(bs);
1736 Bfree(bd0);
1737 Bfree(delta);
1738 ret:
1739 if (se)
1740 *se = (char *)s;
1741 return sign ? -rv : rv;
1742 }
1743
1744 static int
1745quorem
1746#ifdef KR_headers
1747 (b, S) Bigint *b, *S;
1748#else
1749 (Bigint *b, Bigint *S)
1750#endif
1751{
1752 int n;
1753 Long borrow, y;
1754 ULong carry, q, ys;
1755 ULong *bx, *bxe, *sx, *sxe;
1756#ifdef Pack_32
1757 Long z;
1758 ULong si, zs;
1759#endif
1760
1761 n = S->wds;
1762#ifdef DEBUG
1763 /*debug*/ if (b->wds > n)
1764 /*debug*/ Bug("oversize b in quorem");
1765#endif
1766 if (b->wds < n)
1767 return 0;
1768 sx = S->x;
1769 sxe = sx + --n;
1770 bx = b->x;
1771 bxe = bx + n;
1772 q = *bxe / (*sxe + 1); /* ensure q <= true quotient */
1773#ifdef DEBUG
1774 /*debug*/ if (q > 9)
1775 /*debug*/ Bug("oversized quotient in quorem");
1776#endif
1777 if (q) {
1778 borrow = 0;
1779 carry = 0;
1780 do {
1781#ifdef Pack_32
1782 si = *sx++;
1783 ys = (si & 0xffff) * q + carry;
1784 zs = (si >> 16) * q + (ys >> 16);
1785 carry = zs >> 16;
1786 y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
1787 borrow = y >> 16;
1788 Sign_Extend(borrow, y);
1789 z = (*bx >> 16) - (zs & 0xffff) + borrow;
1790 borrow = z >> 16;
1791 Sign_Extend(borrow, z);
1792 Storeinc(bx, z, y);
1793#else
1794 ys = *sx++ * q + carry;
1795 carry = ys >> 16;
1796 y = *bx - (ys & 0xffff) + borrow;
1797 borrow = y >> 16;
1798 Sign_Extend(borrow, y);
1799 *bx++ = y & 0xffff;
1800#endif
1801 }
1802 while(sx <= sxe);
1803 if (!*bxe) {
1804 bx = b->x;
1805 while(--bxe > bx && !*bxe)
1806 --n;
1807 b->wds = n;
1808 }
1809 }
1810 if (cmp(b, S) >= 0) {
1811 q++;
1812 borrow = 0;
1813 carry = 0;
1814 bx = b->x;
1815 sx = S->x;
1816 do {
1817#ifdef Pack_32
1818 si = *sx++;
1819 ys = (si & 0xffff) + carry;
1820 zs = (si >> 16) + (ys >> 16);
1821 carry = zs >> 16;
1822 y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
1823 borrow = y >> 16;
1824 Sign_Extend(borrow, y);
1825 z = (*bx >> 16) - (zs & 0xffff) + borrow;
1826 borrow = z >> 16;
1827 Sign_Extend(borrow, z);
1828 Storeinc(bx, z, y);
1829#else
1830 ys = *sx++ + carry;
1831 carry = ys >> 16;
1832 y = *bx - (ys & 0xffff) + borrow;
1833 borrow = y >> 16;
1834 Sign_Extend(borrow, y);
1835 *bx++ = y & 0xffff;
1836#endif
1837 }
1838 while(sx <= sxe);
1839 bx = b->x;
1840 bxe = bx + n;
1841 if (!*bxe) {
1842 while(--bxe > bx && !*bxe)
1843 --n;
1844 b->wds = n;
1845 }
1846 }
1847 return q;
1848 }
1849
1850/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string.
1851 *
1852 * Inspired by "How to Print Floating-Point Numbers Accurately" by
1853 * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 92-101].
1854 *
1855 * Modifications:
1856 * 1. Rather than iterating, we use a simple numeric overestimate
1857 * to determine k = floor(log10(d)). We scale relevant
1858 * quantities using O(log2(k)) rather than O(k) multiplications.
1859 * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't
1860 * try to generate digits strictly left to right. Instead, we
1861 * compute with fewer bits and propagate the carry if necessary
1862 * when rounding the final digit up. This is often faster.
1863 * 3. Under the assumption that input will be rounded nearest,
1864 * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22.
1865 * That is, we allow equality in stopping tests when the
1866 * round-nearest rule will give the same floating-point value
1867 * as would satisfaction of the stopping test with strict
1868 * inequality.
1869 * 4. We remove common factors of powers of 2 from relevant
1870 * quantities.
1871 * 5. When converting floating-point integers less than 1e16,
1872 * we use floating-point arithmetic rather than resorting
1873 * to multiple-precision integers.
1874 * 6. When asked to produce fewer than 15 digits, we first try
1875 * to get by with floating-point arithmetic; we resort to
1876 * multiple-precision integer arithmetic only if we cannot
1877 * guarantee that the floating-point calculation has given
1878 * the correctly rounded result. For k requested digits and
1879 * "uniformly" distributed input, the probability is
1880 * something like 10^(k-15) that we must resort to the Long
1881 * calculation.
1882 */
1883
1884 char *
1885__dtoa
1886#ifdef KR_headers
1887 (d, mode, ndigits, decpt, sign, rve)
1888 double d; int mode, ndigits, *decpt, *sign; char **rve;
1889#else
1890 (double d, int mode, int ndigits, int *decpt, int *sign, char **rve)
1891#endif
1892{
1893 /* Arguments ndigits, decpt, sign are similar to those
1894 of ecvt and fcvt; trailing zeros are suppressed from
1895 the returned string. If not null, *rve is set to point
1896 to the end of the return value. If d is +-Infinity or NaN,
1897 then *decpt is set to 9999.
1898
1899 mode:
1900 0 ==> shortest string that yields d when read in
1901 and rounded to nearest.
1902 1 ==> like 0, but with Steele & White stopping rule;
1903 e.g. with IEEE P754 arithmetic , mode 0 gives
1904 1e23 whereas mode 1 gives 9.999999999999999e22.
1905 2 ==> max(1,ndigits) significant digits. This gives a
1906 return value similar to that of ecvt, except
1907 that trailing zeros are suppressed.
1908 3 ==> through ndigits past the decimal point. This
1909 gives a return value similar to that from fcvt,
1910 except that trailing zeros are suppressed, and
1911 ndigits can be negative.
1912 4-9 should give the same return values as 2-3, i.e.,
1913 4 <= mode <= 9 ==> same return as mode
1914 2 + (mode & 1). These modes are mainly for
1915 debugging; often they run slower but sometimes
1916 faster than modes 2-3.
1917 4,5,8,9 ==> left-to-right digit generation.
1918 6-9 ==> don't try fast floating-point estimate
1919 (if applicable).
1920
1921 Values of mode other than 0-9 are treated as mode 0.
1922
1923 Sufficient space is allocated to the return value
1924 to hold the suppressed trailing zeros.
1925 */
1926
1927 int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1,
1928 j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
1929 spec_case, try_quick;
1930 Long L;
1931#ifndef Sudden_Underflow
1932 int denorm;
1933 ULong x;
1934#endif
1935 Bigint *b, *b1, *delta, *mlo, *mhi, *S;
1936 double d2, ds, eps;
1937 char *s, *s0;
1938 static Bigint *result;
1939 static int result_k;
1940
1941 if (result) {
1942 result->k = result_k;
1943 result->maxwds = 1 << result_k;
1944 Bfree(result);
1945 result = 0;
1946 }
1947
1948 if (word0(d) & Sign_bit) {
1949 /* set sign for everything, including 0's and NaNs */
1950 *sign = 1;
1951 word0(d) &= ~Sign_bit; /* clear sign bit */
1952 }
1953 else
1954 *sign = 0;
1955
1956#if defined(IEEE_Arith) + defined(VAX)
1957#ifdef IEEE_Arith
1958 if ((word0(d) & Exp_mask) == Exp_mask)
1959#else
1960 if (word0(d) == 0x8000)
1961#endif
1962 {
1963 /* Infinity or NaN */
1964 *decpt = 9999;
1965 s =
1966#ifdef IEEE_Arith
1967 !word1(d) && !(word0(d) & 0xfffff) ? "Infinity" :
1968#endif
1969 "NaN";
1970 if (rve)
1971 *rve =
1972#ifdef IEEE_Arith
1973 s[3] ? s + 8 :
1974#endif
1975 s + 3;
1976 return s;
1977 }
1978#endif
1979#ifdef IBM
1980 d += 0; /* normalize */
1981#endif
1982 if (!d) {
1983 *decpt = 1;
1984 s = "0";
1985 if (rve)
1986 *rve = s + 1;
1987 return s;
1988 }
1989
1990 b = d2b(d, &be, &bbits);
1991#ifdef Sudden_Underflow
1992 i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
1993#else
1994 if (i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) {
1995#endif
1996 d2 = d;
1997 word0(d2) &= Frac_mask1;
1998 word0(d2) |= Exp_11;
1999#ifdef IBM
2000 if (j = 11 - hi0bits(word0(d2) & Frac_mask))
2001 d2 /= 1 << j;
2002#endif
2003
2004 /* log(x) ~=~ log(1.5) + (x-1.5)/1.5
2005 * log10(x) = log(x) / log(10)
2006 * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
2007 * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2)
2008 *
2009 * This suggests computing an approximation k to log10(d) by
2010 *
2011 * k = (i - Bias)*0.301029995663981
2012 * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 );
2013 *
2014 * We want k to be too large rather than too small.
2015 * The error in the first-order Taylor series approximation
2016 * is in our favor, so we just round up the constant enough
2017 * to compensate for any error in the multiplication of
2018 * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077,
2019 * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
2020 * adding 1e-13 to the constant term more than suffices.
2021 * Hence we adjust the constant term to 0.1760912590558.
2022 * (We could get a more accurate k by invoking log10,
2023 * but this is probably not worthwhile.)
2024 */
2025
2026 i -= Bias;
2027#ifdef IBM
2028 i <<= 2;
2029 i += j;
2030#endif
2031#ifndef Sudden_Underflow
2032 denorm = 0;
2033 }
2034 else {
2035 /* d is denormalized */
2036
2037 i = bbits + be + (Bias + (P-1) - 1);
2038 x = i > 32 ? word0(d) << 64 - i | word1(d) >> i - 32
2039 : word1(d) << 32 - i;
2040 d2 = x;
2041 word0(d2) -= 31*Exp_msk1; /* adjust exponent */
2042 i -= (Bias + (P-1) - 1) + 1;
2043 denorm = 1;
2044 }
2045#endif
2046 ds = (d2-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
2047 k = (int)ds;
2048 if (ds < 0. && ds != k)
2049 k--; /* want k = floor(ds) */
2050 k_check = 1;
2051 if (k >= 0 && k <= Ten_pmax) {
2052 if (d < tens[k])
2053 k--;
2054 k_check = 0;
2055 }
2056 j = bbits - i - 1;
2057 if (j >= 0) {
2058 b2 = 0;
2059 s2 = j;
2060 }
2061 else {
2062 b2 = -j;
2063 s2 = 0;
2064 }
2065 if (k >= 0) {
2066 b5 = 0;
2067 s5 = k;
2068 s2 += k;
2069 }
2070 else {
2071 b2 -= k;
2072 b5 = -k;
2073 s5 = 0;
2074 }
2075 if (mode < 0 || mode > 9)
2076 mode = 0;
2077 try_quick = 1;
2078 if (mode > 5) {
2079 mode -= 4;
2080 try_quick = 0;
2081 }
2082 leftright = 1;
2083 switch(mode) {
2084 case 0:
2085 case 1:
2086 ilim = ilim1 = -1;
2087 i = 18;
2088 ndigits = 0;
2089 break;
2090 case 2:
2091 leftright = 0;
2092 /* no break */
2093 case 4:
2094 if (ndigits <= 0)
2095 ndigits = 1;
2096 ilim = ilim1 = i = ndigits;
2097 break;
2098 case 3:
2099 leftright = 0;
2100 /* no break */
2101 case 5:
2102 i = ndigits + k + 1;
2103 ilim = i;
2104 ilim1 = i - 1;
2105 if (i <= 0)
2106 i = 1;
2107 }
2108 j = sizeof(ULong);
2109 for(result_k = 0; sizeof(Bigint) - sizeof(ULong) + j <= i;
2110 j <<= 1) result_k++;
2111 result = Balloc(result_k);
2112 s = s0 = (char *)result;
2113
2114 if (ilim >= 0 && ilim <= Quick_max && try_quick) {
2115
2116 /* Try to get by with floating-point arithmetic. */
2117
2118 i = 0;
2119 d2 = d;
2120 k0 = k;
2121 ilim0 = ilim;
2122 ieps = 2; /* conservative */
2123 if (k > 0) {
2124 ds = tens[k&0xf];
2125 j = k >> 4;
2126 if (j & Bletch) {
2127 /* prevent overflows */
2128 j &= Bletch - 1;
2129 d /= bigtens[n_bigtens-1];
2130 ieps++;
2131 }
2132 for(; j; j >>= 1, i++)
2133 if (j & 1) {
2134 ieps++;
2135 ds *= bigtens[i];
2136 }
2137 d /= ds;
2138 }
2139 else if (j1 = -k) {
2140 d *= tens[j1 & 0xf];
2141 for(j = j1 >> 4; j; j >>= 1, i++)
2142 if (j & 1) {
2143 ieps++;
2144 d *= bigtens[i];
2145 }
2146 }
2147 if (k_check && d < 1. && ilim > 0) {
2148 if (ilim1 <= 0)
2149 goto fast_failed;
2150 ilim = ilim1;
2151 k--;
2152 d *= 10.;
2153 ieps++;
2154 }
2155 eps = ieps*d + 7.;
2156 word0(eps) -= (P-1)*Exp_msk1;
2157 if (ilim == 0) {
2158 S = mhi = 0;
2159 d -= 5.;
2160 if (d > eps)
2161 goto one_digit;
2162 if (d < -eps)
2163 goto no_digits;
2164 goto fast_failed;
2165 }
2166#ifndef No_leftright
2167 if (leftright) {
2168 /* Use Steele & White method of only
2169 * generating digits needed.
2170 */
2171 eps = 0.5/tens[ilim-1] - eps;
2172 for(i = 0;;) {
2173 L = d;
2174 d -= L;
2175 *s++ = '0' + (int)L;
2176 if (d < eps)
2177 goto ret1;
2178 if (1. - d < eps)
2179 goto bump_up;
2180 if (++i >= ilim)
2181 break;
2182 eps *= 10.;
2183 d *= 10.;
2184 }
2185 }
2186 else {
2187#endif
2188 /* Generate ilim digits, then fix them up. */
2189 eps *= tens[ilim-1];
2190 for(i = 1;; i++, d *= 10.) {
2191 L = d;
2192 d -= L;
2193 *s++ = '0' + (int)L;
2194 if (i == ilim) {
2195 if (d > 0.5 + eps)
2196 goto bump_up;
2197 else if (d < 0.5 - eps) {
2198 while(*--s == '0');
2199 s++;
2200 goto ret1;
2201 }
2202 break;
2203 }
2204 }
2205#ifndef No_leftright
2206 }
2207#endif
2208 fast_failed:
2209 s = s0;
2210 d = d2;
2211 k = k0;
2212 ilim = ilim0;
2213 }
2214
2215 /* Do we have a "small" integer? */
2216
2217 if (be >= 0 && k <= Int_max) {
2218 /* Yes. */
2219 ds = tens[k];
2220 if (ndigits < 0 && ilim <= 0) {
2221 S = mhi = 0;
2222 if (ilim < 0 || d <= 5*ds)
2223 goto no_digits;
2224 goto one_digit;
2225 }
2226 for(i = 1;; i++) {
2227 L = d / ds;
2228 d -= L*ds;
2229#ifdef Check_FLT_ROUNDS
2230 /* If FLT_ROUNDS == 2, L will usually be high by 1 */
2231 if (d < 0) {
2232 L--;
2233 d += ds;
2234 }
2235#endif
2236 *s++ = '0' + (int)L;
2237 if (i == ilim) {
2238 d += d;
2239 if (d > ds || d == ds && L & 1) {
2240 bump_up:
2241 while(*--s == '9')
2242 if (s == s0) {
2243 k++;
2244 *s = '0';
2245 break;
2246 }
2247 ++*s++;
2248 }
2249 break;
2250 }
2251 if (!(d *= 10.))
2252 break;
2253 }
2254 goto ret1;
2255 }
2256
2257 m2 = b2;
2258 m5 = b5;
2259 mhi = mlo = 0;
2260 if (leftright) {
2261 if (mode < 2) {
2262 i =
2263#ifndef Sudden_Underflow
2264 denorm ? be + (Bias + (P-1) - 1 + 1) :
2265#endif
2266#ifdef IBM
2267 1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3);
2268#else
2269 1 + P - bbits;
2270#endif
2271 }
2272 else {
2273 j = ilim - 1;
2274 if (m5 >= j)
2275 m5 -= j;
2276 else {
2277 s5 += j -= m5;
2278 b5 += j;
2279 m5 = 0;
2280 }
2281 if ((i = ilim) < 0) {
2282 m2 -= i;
2283 i = 0;
2284 }
2285 }
2286 b2 += i;
2287 s2 += i;
2288 mhi = i2b(1);
2289 }
2290 if (m2 > 0 && s2 > 0) {
2291 i = m2 < s2 ? m2 : s2;
2292 b2 -= i;
2293 m2 -= i;
2294 s2 -= i;
2295 }
2296 if (b5 > 0) {
2297 if (leftright) {
2298 if (m5 > 0) {
2299 mhi = pow5mult(mhi, m5);
2300 b1 = mult(mhi, b);
2301 Bfree(b);
2302 b = b1;
2303 }
2304 if (j = b5 - m5)
2305 b = pow5mult(b, j);
2306 }
2307 else
2308 b = pow5mult(b, b5);
2309 }
2310 S = i2b(1);
2311 if (s5 > 0)
2312 S = pow5mult(S, s5);
2313
2314 /* Check for special case that d is a normalized power of 2. */
2315
2316 if (mode < 2) {
2317 if (!word1(d) && !(word0(d) & Bndry_mask)
2318#ifndef Sudden_Underflow
2319 && word0(d) & Exp_mask
2320#endif
2321 ) {
2322 /* The special case */
2323 b2 += Log2P;
2324 s2 += Log2P;
2325 spec_case = 1;
2326 }
2327 else
2328 spec_case = 0;
2329 }
2330
2331 /* Arrange for convenient computation of quotients:
2332 * shift left if necessary so divisor has 4 leading 0 bits.
2333 *
2334 * Perhaps we should just compute leading 28 bits of S once
2335 * and for all and pass them and a shift to quorem, so it
2336 * can do shifts and ors to compute the numerator for q.
2337 */
2338#ifdef Pack_32
2339 if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f)
2340 i = 32 - i;
2341#else
2342 if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf)
2343 i = 16 - i;
2344#endif
2345 if (i > 4) {
2346 i -= 4;
2347 b2 += i;
2348 m2 += i;
2349 s2 += i;
2350 }
2351 else if (i < 4) {
2352 i += 28;
2353 b2 += i;
2354 m2 += i;
2355 s2 += i;
2356 }
2357 if (b2 > 0)
2358 b = lshift(b, b2);
2359 if (s2 > 0)
2360 S = lshift(S, s2);
2361 if (k_check) {
2362 if (cmp(b,S) < 0) {
2363 k--;
2364 b = multadd(b, 10, 0); /* we botched the k estimate */
2365 if (leftright)
2366 mhi = multadd(mhi, 10, 0);
2367 ilim = ilim1;
2368 }
2369 }
2370 if (ilim <= 0 && mode > 2) {
2371 if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) {
2372 /* no digits, fcvt style */
2373 no_digits:
2374 k = -1 - ndigits;
2375 goto ret;
2376 }
2377 one_digit:
2378 *s++ = '1';
2379 k++;
2380 goto ret;
2381 }
2382 if (leftright) {
2383 if (m2 > 0)
2384 mhi = lshift(mhi, m2);
2385
2386 /* Compute mlo -- check for special case
2387 * that d is a normalized power of 2.
2388 */
2389
2390 mlo = mhi;
2391 if (spec_case) {
2392 mhi = Balloc(mhi->k);
2393 Bcopy(mhi, mlo);
2394 mhi = lshift(mhi, Log2P);
2395 }
2396
2397 for(i = 1;;i++) {
2398 dig = quorem(b,S) + '0';
2399 /* Do we yet have the shortest decimal string
2400 * that will round to d?
2401 */
2402 j = cmp(b, mlo);
2403 delta = diff(S, mhi);
2404 j1 = delta->sign ? 1 : cmp(b, delta);
2405 Bfree(delta);
2406#ifndef ROUND_BIASED
2407 if (j1 == 0 && !mode && !(word1(d) & 1)) {
2408 if (dig == '9')
2409 goto round_9_up;
2410 if (j > 0)
2411 dig++;
2412 *s++ = dig;
2413 goto ret;
2414 }
2415#endif
2416 if (j < 0 || j == 0 && !mode
2417#ifndef ROUND_BIASED
2418 && !(word1(d) & 1)
2419#endif
2420 ) {
2421 if (j1 > 0) {
2422 b = lshift(b, 1);
2423 j1 = cmp(b, S);
2424 if ((j1 > 0 || j1 == 0 && dig & 1)
2425 && dig++ == '9')
2426 goto round_9_up;
2427 }
2428 *s++ = dig;
2429 goto ret;
2430 }
2431 if (j1 > 0) {
2432 if (dig == '9') { /* possible if i == 1 */
2433 round_9_up:
2434 *s++ = '9';
2435 goto roundoff;
2436 }
2437 *s++ = dig + 1;
2438 goto ret;
2439 }
2440 *s++ = dig;
2441 if (i == ilim)
2442 break;
2443 b = multadd(b, 10, 0);
2444 if (mlo == mhi)
2445 mlo = mhi = multadd(mhi, 10, 0);
2446 else {
2447 mlo = multadd(mlo, 10, 0);
2448 mhi = multadd(mhi, 10, 0);
2449 }
2450 }
2451 }
2452 else
2453 for(i = 1;; i++) {
2454 *s++ = dig = quorem(b,S) + '0';
2455 if (i >= ilim)
2456 break;
2457 b = multadd(b, 10, 0);
2458 }
2459
2460 /* Round off last digit */
2461
2462 b = lshift(b, 1);
2463 j = cmp(b, S);
2464 if (j > 0 || j == 0 && dig & 1) {
2465 roundoff:
2466 while(*--s == '9')
2467 if (s == s0) {
2468 k++;
2469 *s++ = '1';
2470 goto ret;
2471 }
2472 ++*s++;
2473 }
2474 else {
2475 while(*--s == '0');
2476 s++;
2477 }
2478 ret:
2479 Bfree(S);
2480 if (mhi) {
2481 if (mlo && mlo != mhi)
2482 Bfree(mlo);
2483 Bfree(mhi);
2484 }
2485 ret1:
2486 Bfree(b);
2487 if (s == s0) { /* don't return empty string */
2488 *s++ = '0';
2489 k = 0;
2490 }
2491 *s = 0;
2492 *decpt = k + 1;
2493 if (rve)
2494 *rve = s;
2495 return s0;
2496 }
2497#ifdef __cplusplus
2498}
2499#endif
diff --git a/src/lib/libc/stdlib/strtoimax.c b/src/lib/libc/stdlib/strtoimax.c
new file mode 100644
index 0000000000..2c77f41650
--- /dev/null
+++ b/src/lib/libc/stdlib/strtoimax.c
@@ -0,0 +1,140 @@
1/* $OpenBSD: strtoimax.c,v 1.1 2006/01/13 17:58:09 millert Exp $ */
2
3/*-
4 * Copyright (c) 1992 The Regents of the University of California.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <ctype.h>
33#include <errno.h>
34#include <inttypes.h>
35
36/*
37 * Convert a string to an intmax_t
38 *
39 * Ignores `locale' stuff. Assumes that the upper and lower case
40 * alphabets and digits are each contiguous.
41 */
42intmax_t
43strtoimax(const char *nptr, char **endptr, int base)
44{
45 const char *s;
46 intmax_t acc, cutoff;
47 int c;
48 int neg, any, cutlim;
49
50 /*
51 * Skip white space and pick up leading +/- sign if any.
52 * If base is 0, allow 0x for hex and 0 for octal, else
53 * assume decimal; if base is already 16, allow 0x.
54 */
55 s = nptr;
56 do {
57 c = (unsigned char) *s++;
58 } while (isspace(c));
59 if (c == '-') {
60 neg = 1;
61 c = *s++;
62 } else {
63 neg = 0;
64 if (c == '+')
65 c = *s++;
66 }
67 if ((base == 0 || base == 16) &&
68 c == '0' && (*s == 'x' || *s == 'X')) {
69 c = s[1];
70 s += 2;
71 base = 16;
72 }
73 if (base == 0)
74 base = c == '0' ? 8 : 10;
75
76 /*
77 * Compute the cutoff value between legal numbers and illegal
78 * numbers. That is the largest legal value, divided by the
79 * base. An input number that is greater than this value, if
80 * followed by a legal input character, is too big. One that
81 * is equal to this value may be valid or not; the limit
82 * between valid and invalid numbers is then based on the last
83 * digit. For instance, if the range for intmax_t is
84 * [-9223372036854775808..9223372036854775807] and the input base
85 * is 10, cutoff will be set to 922337203685477580 and cutlim to
86 * either 7 (neg==0) or 8 (neg==1), meaning that if we have
87 * accumulated a value > 922337203685477580, or equal but the
88 * next digit is > 7 (or 8), the number is too big, and we will
89 * return a range error.
90 *
91 * Set any if any `digits' consumed; make it negative to indicate
92 * overflow.
93 */
94 cutoff = neg ? INTMAX_MIN : INTMAX_MAX;
95 cutlim = cutoff % base;
96 cutoff /= base;
97 if (neg) {
98 if (cutlim > 0) {
99 cutlim -= base;
100 cutoff += 1;
101 }
102 cutlim = -cutlim;
103 }
104 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
105 if (isdigit(c))
106 c -= '0';
107 else if (isalpha(c))
108 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
109 else
110 break;
111 if (c >= base)
112 break;
113 if (any < 0)
114 continue;
115 if (neg) {
116 if (acc < cutoff || (acc == cutoff && c > cutlim)) {
117 any = -1;
118 acc = INTMAX_MIN;
119 errno = ERANGE;
120 } else {
121 any = 1;
122 acc *= base;
123 acc -= c;
124 }
125 } else {
126 if (acc > cutoff || (acc == cutoff && c > cutlim)) {
127 any = -1;
128 acc = INTMAX_MAX;
129 errno = ERANGE;
130 } else {
131 any = 1;
132 acc *= base;
133 acc += c;
134 }
135 }
136 }
137 if (endptr != 0)
138 *endptr = (char *) (any ? s - 1 : nptr);
139 return (acc);
140}
diff --git a/src/lib/libc/stdlib/strtol.3 b/src/lib/libc/stdlib/strtol.3
index 808ba90165..6f9037a645 100644
--- a/src/lib/libc/stdlib/strtol.3
+++ b/src/lib/libc/stdlib/strtol.3
@@ -13,11 +13,7 @@
13.\" 2. Redistributions in binary form must reproduce the above copyright 13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the 14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution. 15.\" documentation and/or other materials provided with the distribution.
16.\" 3. All advertising materials mentioning features or use of this software 16.\" 3. Neither the name of the University nor the names of its contributors
17.\" must display the following acknowledgement:
18.\" This product includes software developed by the University of
19.\" California, Berkeley and its contributors.
20.\" 4. Neither the name of the University nor the names of its contributors
21.\" may be used to endorse or promote products derived from this software 17.\" may be used to endorse or promote products derived from this software
22.\" without specific prior written permission. 18.\" without specific prior written permission.
23.\" 19.\"
@@ -33,49 +29,67 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
35.\" 31.\"
36.\" from: @(#)strtol.3 5.4 (Berkeley) 6/25/92 32.\" $OpenBSD: strtol.3,v 1.22 2011/09/03 23:24:51 jmc Exp $
37.\" $Id: strtol.3,v 1.1.1.1 1995/10/18 08:42:19 deraadt Exp $
38.\" 33.\"
39.Dd June 25, 1992 34.Dd $Mdocdate: September 3 2011 $
40.Dt STRTOL 3 35.Dt STRTOL 3
41.Os 36.Os
42.Sh NAME 37.Sh NAME
43.Nm strtol, strtoq 38.Nm strtol ,
44.Nd convert string value to a long or quad_t integer 39.Nm strtoll ,
40.Nm strtoimax ,
41.Nm strtoq ,
42.Nd "convert string value to a long, long long or intmax_t integer"
45.Sh SYNOPSIS 43.Sh SYNOPSIS
46.Fd #include <stdlib.h>
47.Fd #include <limits.h> 44.Fd #include <limits.h>
45.Fd #include <stdlib.h>
48.Ft long 46.Ft long
49.Fn strtol "char *nptr" "char **endptr" "int base" 47.Fn strtol "const char *nptr" "char **endptr" "int base"
50 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
51.Fd #include <sys/types.h> 56.Fd #include <sys/types.h>
52.Fd #include <stdlib.h>
53.Fd #include <limits.h> 57.Fd #include <limits.h>
58.Fd #include <stdlib.h>
54.Ft quad_t 59.Ft quad_t
55.Fn strtoq "char *nptr" "char **endptr" "int base" 60.Fn strtoq "const char *nptr" "char **endptr" "int base"
56.Sh DESCRIPTION 61.Sh DESCRIPTION
57The 62The
58.Fn strtol 63.Fn strtol
59function 64function converts the string in
60converts the string in
61.Fa nptr 65.Fa nptr
62to a 66to a
63.Em long 67.Li long
64value. 68value.
65The 69The
66.Fn strtoq 70.Fn strtoll
67function 71function converts the string in
68converts the string in
69.Fa nptr 72.Fa nptr
70to a 73to a
71.Em quad_t 74.Li long long
72value. 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.
73The conversion is done according to the given 88The conversion is done according to the given
74.Fa base , 89.Fa base ,
75which must be between 2 and 36 inclusive, 90which must be a number between 2 and 36 inclusive or the special value 0.
76or be the special value 0.
77.Pp 91.Pp
78The string may begin with an arbitrary amount of white space 92The string may begin with an arbitrary amount of whitespace
79(as determined by 93(as determined by
80.Xr isspace 3 ) 94.Xr isspace 3 )
81followed by a single optional 95followed by a single optional
@@ -85,25 +99,25 @@ or
85sign. 99sign.
86If 100If
87.Fa base 101.Fa base
88is zero or 16, 102is zero or 16, the string may then include a
89the string may then include a
90.Ql 0x 103.Ql 0x
91prefix, 104prefix, and the number will be read in base 16; otherwise, a zero
92and the number will be read in base 16; otherwise, a zero
93.Fa base 105.Fa base
94is taken as 10 (decimal) unless the next character is 106is taken as 10 (decimal) unless the next character is
95.Ql 0 , 107.Ql 0 ,
96in which case it is taken as 8 (octal). 108in which case it is taken as 8 (octal).
97.Pp 109.Pp
98The remainder of the string is converted to a 110The remainder of the string is converted to a
99.Em long 111.Li long ,
112.Li long long ,
113or
114.Li intmax_t ,
100value in the obvious manner, 115value in the obvious manner,
101stopping at the first character which is not a valid digit 116stopping at the first character which is not a valid digit
102in the given base. 117in the given base.
103(In bases above 10, the letter 118(In bases above 10, the letter
104.Ql A 119.Ql A
105in either upper or lower case 120in either upper or lower case represents 10,
106represents 10,
107.Ql B 121.Ql B
108represents 11, and so forth, with 122represents 11, and so forth, with
109.Ql Z 123.Ql Z
@@ -111,7 +125,7 @@ representing 35.)
111.Pp 125.Pp
112If 126If
113.Fa endptr 127.Fa endptr
114is non nil, 128is non-null,
115.Fn strtol 129.Fn strtol
116stores the address of the first invalid character in 130stores the address of the first invalid character in
117.Fa *endptr . 131.Fa *endptr .
@@ -132,22 +146,93 @@ is
132on return, the entire string was valid.) 146on return, the entire string was valid.)
133.Sh RETURN VALUES 147.Sh RETURN VALUES
134The 148The
135.Fn strtol 149.Fn strtol ,
136function 150.Fn strtoll ,
137returns the result of the conversion, 151.Fn strtoimax ,
152and
153.Fn strtoq
154functions return the result of the conversion,
138unless the value would underflow or overflow. 155unless the value would underflow or overflow.
139If an underflow occurs, 156If no conversion could be performed, 0 is returned;
140.Fn strtol 157the global variable
141returns 158.Va errno
142.Dv LONG_MIN . 159is also set to
143If an overflow occurs, 160.Er EINVAL ,
144.Fn strtol 161though this is not portable across all platforms.
145returns 162If overflow or underflow occurs,
146.Dv LONG_MAX .
147In both cases,
148.Va errno 163.Va errno
149is set to 164is set to
150.Er ERANGE . 165.Er ERANGE
166and the function return value is as follows:
167.Bl -column "strtoimaxXX" "INTMAX_MIN" "INTMAX_MAX" -offset indent
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
151.Sh ERRORS 236.Sh ERRORS
152.Bl -tag -width Er 237.Bl -tag -width Er
153.It Bq Er ERANGE 238.It Bq Er ERANGE
@@ -157,13 +242,23 @@ The given string was out of range; the value converted has been clamped.
157.Xr atof 3 , 242.Xr atof 3 ,
158.Xr atoi 3 , 243.Xr atoi 3 ,
159.Xr atol 3 , 244.Xr atol 3 ,
245.Xr atoll 3 ,
246.Xr sscanf 3 ,
160.Xr strtod 3 , 247.Xr strtod 3 ,
248.Xr strtonum 3 ,
161.Xr strtoul 3 249.Xr strtoul 3
162.Sh STANDARDS 250.Sh STANDARDS
163The 251The
164.Fn strtol 252.Fn strtol ,
165function 253.Fn strtoll ,
166conforms to 254and
167.St -ansiC . 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.
168.Sh BUGS 263.Sh BUGS
169Ignores the current locale. 264Ignores the current locale.
diff --git a/src/lib/libc/stdlib/strtol.c b/src/lib/libc/stdlib/strtol.c
index 6f374abd5f..5a244766db 100644
--- a/src/lib/libc/stdlib/strtol.c
+++ b/src/lib/libc/stdlib/strtol.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: strtol.c,v 1.7 2005/08/08 08:05:37 espie Exp $ */
1/*- 2/*-
2 * Copyright (c) 1990 The Regents of the University of California. 3 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved. 4 * All rights reserved.
@@ -10,11 +11,7 @@
10 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. 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 15 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission. 16 * without specific prior written permission.
20 * 17 *
@@ -31,14 +28,9 @@
31 * SUCH DAMAGE. 28 * SUCH DAMAGE.
32 */ 29 */
33 30
34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)strtol.c 5.4 (Berkeley) 2/23/91";*/
36static char *rcsid = "$Id: strtol.c,v 1.1.1.1 1995/10/18 08:42:20 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */
38
39#include <limits.h>
40#include <ctype.h> 31#include <ctype.h>
41#include <errno.h> 32#include <errno.h>
33#include <limits.h>
42#include <stdlib.h> 34#include <stdlib.h>
43 35
44 36
@@ -49,30 +41,30 @@ static char *rcsid = "$Id: strtol.c,v 1.1.1.1 1995/10/18 08:42:20 deraadt Exp $"
49 * alphabets and digits are each contiguous. 41 * alphabets and digits are each contiguous.
50 */ 42 */
51long 43long
52strtol(nptr, endptr, base) 44strtol(const char *nptr, char **endptr, int base)
53 const char *nptr;
54 char **endptr;
55 register int base;
56{ 45{
57 register const char *s = nptr; 46 const char *s;
58 register unsigned long acc; 47 long acc, cutoff;
59 register int c; 48 int c;
60 register unsigned long cutoff; 49 int neg, any, cutlim;
61 register int neg = 0, any, cutlim;
62 50
63 /* 51 /*
64 * Skip white space and pick up leading +/- sign if any. 52 * Skip white space and pick up leading +/- sign if any.
65 * If base is 0, allow 0x for hex and 0 for octal, else 53 * If base is 0, allow 0x for hex and 0 for octal, else
66 * assume decimal; if base is already 16, allow 0x. 54 * assume decimal; if base is already 16, allow 0x.
67 */ 55 */
56 s = nptr;
68 do { 57 do {
69 c = *s++; 58 c = (unsigned char) *s++;
70 } while (isspace(c)); 59 } while (isspace(c));
71 if (c == '-') { 60 if (c == '-') {
72 neg = 1; 61 neg = 1;
73 c = *s++; 62 c = *s++;
74 } else if (c == '+') 63 } else {
75 c = *s++; 64 neg = 0;
65 if (c == '+')
66 c = *s++;
67 }
76 if ((base == 0 || base == 16) && 68 if ((base == 0 || base == 16) &&
77 c == '0' && (*s == 'x' || *s == 'X')) { 69 c == '0' && (*s == 'x' || *s == 'X')) {
78 c = s[1]; 70 c = s[1];
@@ -99,10 +91,17 @@ strtol(nptr, endptr, base)
99 * Set any if any `digits' consumed; make it negative to indicate 91 * Set any if any `digits' consumed; make it negative to indicate
100 * overflow. 92 * overflow.
101 */ 93 */
102 cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; 94 cutoff = neg ? LONG_MIN : LONG_MAX;
103 cutlim = cutoff % (unsigned long)base; 95 cutlim = cutoff % base;
104 cutoff /= (unsigned long)base; 96 cutoff /= base;
105 for (acc = 0, any = 0;; c = *s++) { 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++) {
106 if (isdigit(c)) 105 if (isdigit(c))
107 c -= '0'; 106 c -= '0';
108 else if (isalpha(c)) 107 else if (isalpha(c))
@@ -111,19 +110,30 @@ strtol(nptr, endptr, base)
111 break; 110 break;
112 if (c >= base) 111 if (c >= base)
113 break; 112 break;
114 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) 113 if (any < 0)
115 any = -1; 114 continue;
116 else { 115 if (neg) {
117 any = 1; 116 if (acc < cutoff || acc == cutoff && c > cutlim) {
118 acc *= base; 117 any = -1;
119 acc += c; 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 }
120 } 135 }
121 } 136 }
122 if (any < 0) {
123 acc = neg ? LONG_MIN : LONG_MAX;
124 errno = ERANGE;
125 } else if (neg)
126 acc = -acc;
127 if (endptr != 0) 137 if (endptr != 0)
128 *endptr = (char *) (any ? s - 1 : nptr); 138 *endptr = (char *) (any ? s - 1 : nptr);
129 return (acc); 139 return (acc);
diff --git a/src/lib/libc/stdlib/strtoq.c b/src/lib/libc/stdlib/strtoll.c
index fc559e9d7f..37379252e3 100644
--- a/src/lib/libc/stdlib/strtoq.c
+++ b/src/lib/libc/stdlib/strtoll.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: strtoll.c,v 1.6 2005/11/10 10:00:17 espie Exp $ */
1/*- 2/*-
2 * Copyright (c) 1992 The Regents of the University of California. 3 * Copyright (c) 1992 The Regents of the University of California.
3 * All rights reserved. 4 * All rights reserved.
@@ -10,11 +11,7 @@
10 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. 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 15 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission. 16 * without specific prior written permission.
20 * 17 *
@@ -31,34 +28,26 @@
31 * SUCH DAMAGE. 28 * SUCH DAMAGE.
32 */ 29 */
33 30
34#if defined(LIBC_SCCS) && !defined(lint)
35static char sccsid[] = "@(#)strtoq.c 5.1 (Berkeley) 6/26/92";
36#endif /* LIBC_SCCS and not lint */
37
38#include <sys/types.h> 31#include <sys/types.h>
39 32
40#include <limits.h>
41#include <errno.h>
42#include <ctype.h> 33#include <ctype.h>
34#include <errno.h>
35#include <limits.h>
43#include <stdlib.h> 36#include <stdlib.h>
44 37
45/* 38/*
46 * Convert a string to a quad integer. 39 * Convert a string to a long long.
47 * 40 *
48 * Ignores `locale' stuff. Assumes that the upper and lower case 41 * Ignores `locale' stuff. Assumes that the upper and lower case
49 * alphabets and digits are each contiguous. 42 * alphabets and digits are each contiguous.
50 */ 43 */
51quad_t 44long long
52strtoq(nptr, endptr, base) 45strtoll(const char *nptr, char **endptr, int base)
53 const char *nptr;
54 char **endptr;
55 register int base;
56{ 46{
57 register const char *s; 47 const char *s;
58 register u_quad_t acc; 48 long long acc, cutoff;
59 register int c; 49 int c;
60 register u_quad_t qbase, cutoff; 50 int neg, any, cutlim;
61 register int neg, any, cutlim;
62 51
63 /* 52 /*
64 * Skip white space and pick up leading +/- sign if any. 53 * Skip white space and pick up leading +/- sign if any.
@@ -67,7 +56,7 @@ strtoq(nptr, endptr, base)
67 */ 56 */
68 s = nptr; 57 s = nptr;
69 do { 58 do {
70 c = *s++; 59 c = (unsigned char) *s++;
71 } while (isspace(c)); 60 } while (isspace(c));
72 if (c == '-') { 61 if (c == '-') {
73 neg = 1; 62 neg = 1;
@@ -93,7 +82,7 @@ strtoq(nptr, endptr, base)
93 * followed by a legal input character, is too big. One that 82 * followed by a legal input character, is too big. One that
94 * is equal to this value may be valid or not; the limit 83 * is equal to this value may be valid or not; the limit
95 * between valid and invalid numbers is then based on the last 84 * between valid and invalid numbers is then based on the last
96 * digit. For instance, if the range for quads is 85 * digit. For instance, if the range for long longs is
97 * [-9223372036854775808..9223372036854775807] and the input base 86 * [-9223372036854775808..9223372036854775807] and the input base
98 * is 10, cutoff will be set to 922337203685477580 and cutlim to 87 * is 10, cutoff will be set to 922337203685477580 and cutlim to
99 * either 7 (neg==0) or 8 (neg==1), meaning that if we have 88 * either 7 (neg==0) or 8 (neg==1), meaning that if we have
@@ -104,11 +93,17 @@ strtoq(nptr, endptr, base)
104 * Set any if any `digits' consumed; make it negative to indicate 93 * Set any if any `digits' consumed; make it negative to indicate
105 * overflow. 94 * overflow.
106 */ 95 */
107 qbase = (unsigned)base; 96 cutoff = neg ? LLONG_MIN : LLONG_MAX;
108 cutoff = neg ? -(u_quad_t)QUAD_MIN : QUAD_MAX; 97 cutlim = cutoff % base;
109 cutlim = cutoff % qbase; 98 cutoff /= base;
110 cutoff /= qbase; 99 if (neg) {
111 for (acc = 0, any = 0;; c = *s++) { 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++) {
112 if (isdigit(c)) 107 if (isdigit(c))
113 c -= '0'; 108 c -= '0';
114 else if (isalpha(c)) 109 else if (isalpha(c))
@@ -117,20 +112,42 @@ strtoq(nptr, endptr, base)
117 break; 112 break;
118 if (c >= base) 113 if (c >= base)
119 break; 114 break;
120 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) 115 if (any < 0)
121 any = -1; 116 continue;
122 else { 117 if (neg) {
123 any = 1; 118 if (acc < cutoff || (acc == cutoff && c > cutlim)) {
124 acc *= qbase; 119 any = -1;
125 acc += c; 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 }
126 } 137 }
127 } 138 }
128 if (any < 0) {
129 acc = neg ? QUAD_MIN : QUAD_MAX;
130 errno = ERANGE;
131 } else if (neg)
132 acc = -acc;
133 if (endptr != 0) 139 if (endptr != 0)
134 *endptr = (char *) (any ? s - 1 : nptr); 140 *endptr = (char *) (any ? s - 1 : nptr);
135 return (acc); 141 return (acc);
136} 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
index db551b0141..5e86772ef0 100644
--- a/src/lib/libc/stdlib/strtoul.3
+++ b/src/lib/libc/stdlib/strtoul.3
@@ -13,11 +13,7 @@
13.\" 2. Redistributions in binary form must reproduce the above copyright 13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the 14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution. 15.\" documentation and/or other materials provided with the distribution.
16.\" 3. All advertising materials mentioning features or use of this software 16.\" 3. Neither the name of the University nor the names of its contributors
17.\" must display the following acknowledgement:
18.\" This product includes software developed by the University of
19.\" California, Berkeley and its contributors.
20.\" 4. Neither the name of the University nor the names of its contributors
21.\" may be used to endorse or promote products derived from this software 17.\" may be used to endorse or promote products derived from this software
22.\" without specific prior written permission. 18.\" without specific prior written permission.
23.\" 19.\"
@@ -33,49 +29,70 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
35.\" 31.\"
36.\" from: @(#)strtoul.3 5.4 (Berkeley) 6/25/92 32.\" $OpenBSD: strtoul.3,v 1.20 2010/04/07 18:32:53 jmc Exp $
37.\" $Id: strtoul.3,v 1.1.1.1 1995/10/18 08:42:20 deraadt Exp $
38.\" 33.\"
39.Dd June 25, 1992 34.Dd $Mdocdate: April 7 2010 $
40.Dt STRTOUL 3 35.Dt STRTOUL 3
41.Os 36.Os
42.Sh NAME 37.Sh NAME
43.Nm strtoul, strtouq 38.Nm strtoul ,
44.Nd convert a string to an unsigned long or uquad_t integer 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"
45.Sh SYNOPSIS 43.Sh SYNOPSIS
46.Fd #include <stdlib.h>
47.Fd #include <limits.h> 44.Fd #include <limits.h>
45.Fd #include <stdlib.h>
48.Ft unsigned long 46.Ft unsigned long
49.Fn strtoul "const char *nptr" "char **endptr" "int base" 47.Fn strtoul "const char *nptr" "char **endptr" "int base"
50 48.Ft unsigned long long
49.Fn strtoull "const char *nptr" "char **endptr" "int base"
50.Fd #include <inttypes.h>
51.Ft uintmax_t
52.Fn strtoumax "const char *nptr" "char **endptr" "int base"
51.Fd #include <sys/types.h> 53.Fd #include <sys/types.h>
52.Fd #include <stdlib.h>
53.Fd #include <limits.h> 54.Fd #include <limits.h>
55.Fd #include <stdlib.h>
54.Ft u_quad_t 56.Ft u_quad_t
55.Fn strtouq "const char *nptr" "char **endptr" "int base" 57.Fn strtouq "const char *nptr" "char **endptr" "int base"
56.Sh DESCRIPTION 58.Sh DESCRIPTION
57The 59The
58.Fn strtoul 60.Fn strtoul
59function 61function converts the string in
60converts the string in
61.Fa nptr 62.Fa nptr
62to an 63to an
63.Em unsigned long 64.Li unsigned long
64value. 65value.
65The 66The
66.Fn strtouq 67.Fn strtoull
67function 68function converts the string in
68converts the string in 69.Fa nptr
70to an
71.Li unsigned long long
72value.
73The
74.Fn strtoumax
75function converts the string in
69.Fa nptr 76.Fa nptr
70to a 77to a
71.Em u_quad_t 78.Li umaxint_t
72value. 79value.
80The
81.Fn strtouq
82function is a deprecated equivalent of
83.Fn strtoull
84and is provided for backwards compatibility with legacy programs.
73The conversion is done according to the given 85The conversion is done according to the given
74.Fa base , 86.Fa base ,
75which must be between 2 and 36 inclusive, 87which must be a number between 2 and 36 inclusive
76or be the special value 0. 88or the special value 0.
89If the string in
90.Fa nptr
91represents a negative number, it will be converted to its unsigned equivalent.
92This behavior is consistent with what happens when a signed integer type is
93cast to its unsigned counterpart.
77.Pp 94.Pp
78The string may begin with an arbitrary amount of white space 95The string may begin with an arbitrary amount of whitespace
79(as determined by 96(as determined by
80.Xr isspace 3 ) 97.Xr isspace 3 )
81followed by a single optional 98followed by a single optional
@@ -85,26 +102,22 @@ or
85sign. 102sign.
86If 103If
87.Fa base 104.Fa base
88is zero or 16, 105is zero or 16, the string may then include a
89the string may then include a
90.Ql 0x 106.Ql 0x
91prefix, 107prefix, and the number will be read in base 16; otherwise, a zero
92and the number will be read in base 16; otherwise, a zero
93.Fa base 108.Fa base
94is taken as 10 (decimal) unless the next character is 109is taken as 10 (decimal) unless the next character is
95.Ql 0 , 110.Ql 0 ,
96in which case it is taken as 8 (octal). 111in which case it is taken as 8 (octal).
97.Pp 112.Pp
98The remainder of the string is converted to an 113The remainder of the string is converted to an
99.Em unsigned long 114.Li unsigned long
100value in the obvious manner, 115value in the obvious manner, stopping at the end of the string
101stopping at the end of the string
102or at the first character that does not produce a valid digit 116or at the first character that does not produce a valid digit
103in the given base. 117in the given base.
104(In bases above 10, the letter 118(In bases above 10, the letter
105.Ql A 119.Ql A
106in either upper or lower case 120in either upper or lower case represents 10,
107represents 10,
108.Ql B 121.Ql B
109represents 11, and so forth, with 122represents 11, and so forth, with
110.Ql Z 123.Ql Z
@@ -112,7 +125,7 @@ representing 35.)
112.Pp 125.Pp
113If 126If
114.Fa endptr 127.Fa endptr
115is non nil, 128is non-null,
116.Fn strtoul 129.Fn strtoul
117stores the address of the first invalid character in 130stores the address of the first invalid character in
118.Fa *endptr . 131.Fa *endptr .
@@ -133,32 +146,100 @@ is
133on return, the entire string was valid.) 146on return, the entire string was valid.)
134.Sh RETURN VALUES 147.Sh RETURN VALUES
135The 148The
136.Fn strtoul 149.Fn strtoul ,
137function 150.Fn strtoull ,
138returns either the result of the conversion 151.Fn strtoumax
139or, if there was a leading minus sign, 152and
153.Fn strtouq
154functions return either the result of the conversion or,
155if there was a leading minus sign,
140the negation of the result of the conversion, 156the negation of the result of the conversion,
141unless the original (non-negated) value would overflow; 157unless the original (non-negated) value would overflow.
142in the latter case, 158If overflow occurs,
143.Fn strtoul 159.Fn strtoul
144returns 160returns
145.Dv ULONG_MAX 161.Dv ULONG_MAX ,
146and sets the global variable 162.Fn strtoull
163returns
164.Dv ULLONG_MAX ,
165.Fn strtoumax
166returns
167.Dv UINTMAX_MAX ,
168.Fn strtouq
169returns
170.Dv ULLONG_MAX
171and the global variable
147.Va errno 172.Va errno
148to 173is set to
149.Er ERANGE . 174.Er ERANGE .
175If no conversion could be performed, 0 is returned;
176the global variable
177.Va errno
178is also set to
179.Er EINVAL ,
180though this is not portable across all platforms.
181.Pp
182There is no way to determine if
183.Fn strtoul
184has processed a negative number (and returned an unsigned value) short of
185examining the string in
186.Fa nptr
187directly.
188.Sh EXAMPLES
189Ensuring that a string is a valid number (i.e., in range and containing no
190trailing characters) requires clearing
191.Va errno
192beforehand explicitly since
193.Va errno
194is not changed on a successful call to
195.Fn strtoul ,
196and the return value of
197.Fn strtoul
198cannot be used unambiguously to signal an error:
199.Bd -literal -offset indent
200char *ep;
201unsigned long ulval;
202
203\&...
204
205errno = 0;
206ulval = strtoul(buf, &ep, 10);
207if (buf[0] == '\e0' || *ep != '\e0')
208 goto not_a_number;
209if (errno == ERANGE && ulval == ULONG_MAX)
210 goto out_of_range;
211.Ed
212.Pp
213This example will accept
214.Dq 12
215but not
216.Dq 12foo
217or
218.Dq 12\en .
219If trailing whitespace is acceptable, further checks must be done on
220.Va *ep ;
221alternately, use
222.Xr sscanf 3 .
150.Sh ERRORS 223.Sh ERRORS
151.Bl -tag -width Er 224.Bl -tag -width Er
152.It Bq Er ERANGE 225.It Bq Er ERANGE
153The given string was out of range; the value converted has been clamped. 226The given string was out of range; the value converted has been clamped.
154.El 227.El
155.Sh SEE ALSO 228.Sh SEE ALSO
229.Xr sscanf 3 ,
156.Xr strtol 3 230.Xr strtol 3
157.Sh STANDARDS 231.Sh STANDARDS
158The 232The
159.Fn strtoul 233.Fn strtoul ,
160function 234.Fn strtoull ,
161conforms to 235and
162.St -ansiC . 236.Fn strtoumax
237functions conform to
238.St -ansiC-99 .
239The
240.Fn strtouq
241function is a
242.Bx
243extension and is provided for backwards compatibility with legacy programs.
163.Sh BUGS 244.Sh BUGS
164Ignores the current locale. 245Ignores the current locale.
diff --git a/src/lib/libc/stdlib/strtoul.c b/src/lib/libc/stdlib/strtoul.c
index 00f7210fa1..d7dddab778 100644
--- a/src/lib/libc/stdlib/strtoul.c
+++ b/src/lib/libc/stdlib/strtoul.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: strtoul.c,v 1.7 2005/08/08 08:05:37 espie Exp $ */
1/* 2/*
2 * Copyright (c) 1990 Regents of the University of California. 3 * Copyright (c) 1990 Regents of the University of California.
3 * All rights reserved. 4 * All rights reserved.
@@ -10,11 +11,7 @@
10 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. 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 15 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission. 16 * without specific prior written permission.
20 * 17 *
@@ -31,14 +28,9 @@
31 * SUCH DAMAGE. 28 * SUCH DAMAGE.
32 */ 29 */
33 30
34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)strtoul.c 5.3 (Berkeley) 2/23/91";*/
36static char *rcsid = "$Id: strtoul.c,v 1.1.1.1 1995/10/18 08:42:20 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */
38
39#include <limits.h>
40#include <ctype.h> 31#include <ctype.h>
41#include <errno.h> 32#include <errno.h>
33#include <limits.h>
42#include <stdlib.h> 34#include <stdlib.h>
43 35
44/* 36/*
@@ -48,28 +40,28 @@ static char *rcsid = "$Id: strtoul.c,v 1.1.1.1 1995/10/18 08:42:20 deraadt Exp $
48 * alphabets and digits are each contiguous. 40 * alphabets and digits are each contiguous.
49 */ 41 */
50unsigned long 42unsigned long
51strtoul(nptr, endptr, base) 43strtoul(const char *nptr, char **endptr, int base)
52 const char *nptr;
53 char **endptr;
54 register int base;
55{ 44{
56 register const char *s = nptr; 45 const char *s;
57 register unsigned long acc; 46 unsigned long acc, cutoff;
58 register int c; 47 int c;
59 register unsigned long cutoff; 48 int neg, any, cutlim;
60 register int neg = 0, any, cutlim;
61 49
62 /* 50 /*
63 * See strtol for comments as to the logic used. 51 * See strtol for comments as to the logic used.
64 */ 52 */
53 s = nptr;
65 do { 54 do {
66 c = *s++; 55 c = (unsigned char) *s++;
67 } while (isspace(c)); 56 } while (isspace(c));
68 if (c == '-') { 57 if (c == '-') {
69 neg = 1; 58 neg = 1;
70 c = *s++; 59 c = *s++;
71 } else if (c == '+') 60 } else {
72 c = *s++; 61 neg = 0;
62 if (c == '+')
63 c = *s++;
64 }
73 if ((base == 0 || base == 16) && 65 if ((base == 0 || base == 16) &&
74 c == '0' && (*s == 'x' || *s == 'X')) { 66 c == '0' && (*s == 'x' || *s == 'X')) {
75 c = s[1]; 67 c = s[1];
@@ -78,9 +70,10 @@ strtoul(nptr, endptr, base)
78 } 70 }
79 if (base == 0) 71 if (base == 0)
80 base = c == '0' ? 8 : 10; 72 base = c == '0' ? 8 : 10;
81 cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; 73
82 cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; 74 cutoff = ULONG_MAX / (unsigned long)base;
83 for (acc = 0, any = 0;; c = *s++) { 75 cutlim = ULONG_MAX % (unsigned long)base;
76 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
84 if (isdigit(c)) 77 if (isdigit(c))
85 c -= '0'; 78 c -= '0';
86 else if (isalpha(c)) 79 else if (isalpha(c))
@@ -89,18 +82,19 @@ strtoul(nptr, endptr, base)
89 break; 82 break;
90 if (c >= base) 83 if (c >= base)
91 break; 84 break;
92 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) 85 if (any < 0)
86 continue;
87 if (acc > cutoff || acc == cutoff && c > cutlim) {
93 any = -1; 88 any = -1;
94 else { 89 acc = ULONG_MAX;
90 errno = ERANGE;
91 } else {
95 any = 1; 92 any = 1;
96 acc *= base; 93 acc *= (unsigned long)base;
97 acc += c; 94 acc += c;
98 } 95 }
99 } 96 }
100 if (any < 0) { 97 if (neg && any > 0)
101 acc = ULONG_MAX;
102 errno = ERANGE;
103 } else if (neg)
104 acc = -acc; 98 acc = -acc;
105 if (endptr != 0) 99 if (endptr != 0)
106 *endptr = (char *) (any ? s - 1 : nptr); 100 *endptr = (char *) (any ? s - 1 : nptr);
diff --git a/src/lib/libc/stdlib/strtouq.c b/src/lib/libc/stdlib/strtoull.c
index cc647d8d28..37859776f9 100644
--- a/src/lib/libc/stdlib/strtouq.c
+++ b/src/lib/libc/stdlib/strtoull.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: strtoull.c,v 1.5 2005/08/08 08:05:37 espie Exp $ */
1/*- 2/*-
2 * Copyright (c) 1992 The Regents of the University of California. 3 * Copyright (c) 1992 The Regents of the University of California.
3 * All rights reserved. 4 * All rights reserved.
@@ -10,11 +11,7 @@
10 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. 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 15 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission. 16 * without specific prior written permission.
20 * 17 *
@@ -31,41 +28,33 @@
31 * SUCH DAMAGE. 28 * SUCH DAMAGE.
32 */ 29 */
33 30
34#if defined(LIBC_SCCS) && !defined(lint)
35static char sccsid[] = "@(#)strtouq.c 5.1 (Berkeley) 6/26/92";
36#endif /* LIBC_SCCS and not lint */
37
38#include <sys/types.h> 31#include <sys/types.h>
39 32
40#include <limits.h>
41#include <errno.h>
42#include <ctype.h> 33#include <ctype.h>
34#include <errno.h>
35#include <limits.h>
43#include <stdlib.h> 36#include <stdlib.h>
44 37
45/* 38/*
46 * Convert a string to an unsigned quad integer. 39 * Convert a string to an unsigned long long.
47 * 40 *
48 * Ignores `locale' stuff. Assumes that the upper and lower case 41 * Ignores `locale' stuff. Assumes that the upper and lower case
49 * alphabets and digits are each contiguous. 42 * alphabets and digits are each contiguous.
50 */ 43 */
51u_quad_t 44unsigned long long
52strtouq(nptr, endptr, base) 45strtoull(const char *nptr, char **endptr, int base)
53 const char *nptr;
54 char **endptr;
55 register int base;
56{ 46{
57 register const char *s = nptr; 47 const char *s;
58 register u_quad_t acc; 48 unsigned long long acc, cutoff;
59 register int c; 49 int c;
60 register u_quad_t qbase, cutoff; 50 int neg, any, cutlim;
61 register int neg, any, cutlim;
62 51
63 /* 52 /*
64 * See strtoq for comments as to the logic used. 53 * See strtoq for comments as to the logic used.
65 */ 54 */
66 s = nptr; 55 s = nptr;
67 do { 56 do {
68 c = *s++; 57 c = (unsigned char) *s++;
69 } while (isspace(c)); 58 } while (isspace(c));
70 if (c == '-') { 59 if (c == '-') {
71 neg = 1; 60 neg = 1;
@@ -83,10 +72,10 @@ strtouq(nptr, endptr, base)
83 } 72 }
84 if (base == 0) 73 if (base == 0)
85 base = c == '0' ? 8 : 10; 74 base = c == '0' ? 8 : 10;
86 qbase = (unsigned)base; 75
87 cutoff = (u_quad_t)UQUAD_MAX / qbase; 76 cutoff = ULLONG_MAX / (unsigned long long)base;
88 cutlim = (u_quad_t)UQUAD_MAX % qbase; 77 cutlim = ULLONG_MAX % (unsigned long long)base;
89 for (acc = 0, any = 0;; c = *s++) { 78 for (acc = 0, any = 0;; c = (unsigned char) *s++) {
90 if (isdigit(c)) 79 if (isdigit(c))
91 c -= '0'; 80 c -= '0';
92 else if (isalpha(c)) 81 else if (isalpha(c))
@@ -95,20 +84,32 @@ strtouq(nptr, endptr, base)
95 break; 84 break;
96 if (c >= base) 85 if (c >= base)
97 break; 86 break;
98 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) 87 if (any < 0)
88 continue;
89 if (acc > cutoff || (acc == cutoff && c > cutlim)) {
99 any = -1; 90 any = -1;
100 else { 91 acc = ULLONG_MAX;
92 errno = ERANGE;
93 } else {
101 any = 1; 94 any = 1;
102 acc *= qbase; 95 acc *= (unsigned long long)base;
103 acc += c; 96 acc += c;
104 } 97 }
105 } 98 }
106 if (any < 0) { 99 if (neg && any > 0)
107 acc = UQUAD_MAX;
108 errno = ERANGE;
109 } else if (neg)
110 acc = -acc; 100 acc = -acc;
111 if (endptr != 0) 101 if (endptr != 0)
112 *endptr = (char *) (any ? s - 1 : nptr); 102 *endptr = (char *) (any ? s - 1 : nptr);
113 return (acc); 103 return (acc);
114} 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
index 520f51db0a..a49e595bc0 100644
--- a/src/lib/libc/stdlib/system.3
+++ b/src/lib/libc/stdlib/system.3
@@ -13,11 +13,7 @@
13.\" 2. Redistributions in binary form must reproduce the above copyright 13.\" 2. Redistributions in binary form must reproduce the above copyright
14.\" notice, this list of conditions and the following disclaimer in the 14.\" notice, this list of conditions and the following disclaimer in the
15.\" documentation and/or other materials provided with the distribution. 15.\" documentation and/or other materials provided with the distribution.
16.\" 3. All advertising materials mentioning features or use of this software 16.\" 3. Neither the name of the University nor the names of its contributors
17.\" must display the following acknowledgement:
18.\" This product includes software developed by the University of
19.\" California, Berkeley and its contributors.
20.\" 4. Neither the name of the University nor the names of its contributors
21.\" may be used to endorse or promote products derived from this software 17.\" may be used to endorse or promote products derived from this software
22.\" without specific prior written permission. 18.\" without specific prior written permission.
23.\" 19.\"
@@ -33,10 +29,9 @@
33.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34.\" SUCH DAMAGE. 30.\" SUCH DAMAGE.
35.\" 31.\"
36.\" from: @(#)system.3 6.5 (Berkeley) 6/29/91 32.\" $OpenBSD: system.3,v 1.11 2008/04/04 19:30:41 kurt Exp $
37.\" $Id: system.3,v 1.1.1.1 1995/10/18 08:42:20 deraadt Exp $
38.\" 33.\"
39.Dd June 29, 1991 34.Dd $Mdocdate: April 4 2008 $
40.Dt SYSTEM 3 35.Dt SYSTEM 3
41.Os 36.Os
42.Sh NAME 37.Sh NAME
@@ -49,8 +44,7 @@
49.Sh DESCRIPTION 44.Sh DESCRIPTION
50The 45The
51.Fn system 46.Fn system
52function 47function hands the argument
53hands the argument
54.Fa string 48.Fa string
55to the command interpreter 49to the command interpreter
56.Xr sh 1 . 50.Xr sh 1 .
@@ -64,36 +58,47 @@ and blocking
64.Pp 58.Pp
65If 59If
66.Fa string 60.Fa string
67is a 61is
68.Dv NULL 62.Dv NULL ,
69pointer,
70.Fn system 63.Fn system
71will return non-zero. 64will return non-zero.
72Otherwise, 65Otherwise,
73.Fn system 66.Fn system
74returns the termination status of the shell in the format specified by 67returns the termination status of the shell in the format specified by
75.Xr waitpid 3 . 68.Xr waitpid 2 .
76.Sh RETURN VALUES 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
77If a child process cannot be created, or the termination status of 75If a child process cannot be created, or the termination status of
78the shell cannot be obtained, 76the shell cannot be obtained,
79.Fn system 77.Fn system
80returns -1 and sets 78returns \-1 and sets
81.Va errno 79.Va errno
82to indicate the error. 80to indicate the error.
83If execution of the shell fails, 81If execution of the shell fails,
84.Fn system 82.Fn system
85returns the termination status for a program that terminates with a call of 83returns the termination status for a program that terminates with a call of
86.Fn exit 127 . 84.Fn exit 127 .
87.Sh SEE ALSO 85.Sh SEE ALSO
88.Xr sh 1 , 86.Xr sh 1 ,
89.Xr execve 2 , 87.Xr execve 2 ,
90.Xr popen 3 , 88.Xr waitpid 2 ,
91.Xr waitpid 3 , 89.Xr popen 3
92.Sh STANDARDS 90.Sh STANDARDS
93The 91The
94.Fn system 92.Fn system
95function 93function conforms to
96conforms to 94.St -ansiC
97.St -ansiC
98and 95and
99.St -1003.2-92 . 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
index c2f39325f6..14ddcae8d3 100644
--- a/src/lib/libc/stdlib/system.c
+++ b/src/lib/libc/stdlib/system.c
@@ -1,3 +1,4 @@
1/* $OpenBSD: system.c,v 1.8 2005/08/08 08:05:37 espie Exp $ */
1/* 2/*
2 * Copyright (c) 1988 The Regents of the University of California. 3 * Copyright (c) 1988 The Regents of the University of California.
3 * All rights reserved. 4 * All rights reserved.
@@ -10,11 +11,7 @@
10 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software 14 * 3. Neither the name of the University nor the names of its contributors
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. 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 15 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission. 16 * without specific prior written permission.
20 * 17 *
@@ -31,11 +28,6 @@
31 * SUCH DAMAGE. 28 * SUCH DAMAGE.
32 */ 29 */
33 30
34#if defined(LIBC_SCCS) && !defined(lint)
35/*static char *sccsid = "from: @(#)system.c 5.10 (Berkeley) 2/23/91";*/
36static char *rcsid = "$Id: system.c,v 1.1.1.1 1995/10/18 08:42:20 deraadt Exp $";
37#endif /* LIBC_SCCS and not lint */
38
39#include <sys/types.h> 31#include <sys/types.h>
40#include <sys/wait.h> 32#include <sys/wait.h>
41#include <signal.h> 33#include <signal.h>
@@ -46,25 +38,28 @@ static char *rcsid = "$Id: system.c,v 1.1.1.1 1995/10/18 08:42:20 deraadt Exp $"
46extern char **environ; 38extern char **environ;
47 39
48int 40int
49system(command) 41system(const char *command)
50 const char *command;
51{ 42{
52 pid_t pid; 43 pid_t pid;
53 sig_t intsave, quitsave; 44 sig_t intsave, quitsave;
54 int omask; 45 sigset_t mask, omask;
55 int pstat; 46 int pstat;
56 char *argp[] = {"sh", "-c", (char *) command, NULL}; 47 char *argp[] = {"sh", "-c", NULL, NULL};
57 48
58 if (!command) /* just checking... */ 49 if (!command) /* just checking... */
59 return(1); 50 return(1);
60 51
61 omask = sigblock(sigmask(SIGCHLD)); 52 argp[2] = (char *)command;
62 switch(pid = vfork()) { 53
54 sigemptyset(&mask);
55 sigaddset(&mask, SIGCHLD);
56 sigprocmask(SIG_BLOCK, &mask, &omask);
57 switch (pid = vfork()) {
63 case -1: /* error */ 58 case -1: /* error */
64 (void)sigsetmask(omask); 59 sigprocmask(SIG_SETMASK, &omask, NULL);
65 return(-1); 60 return(-1);
66 case 0: /* child */ 61 case 0: /* child */
67 (void)sigsetmask(omask); 62 sigprocmask(SIG_SETMASK, &omask, NULL);
68 execve(_PATH_BSHELL, argp, environ); 63 execve(_PATH_BSHELL, argp, environ);
69 _exit(127); 64 _exit(127);
70 } 65 }
@@ -72,8 +67,8 @@ system(command)
72 intsave = signal(SIGINT, SIG_IGN); 67 intsave = signal(SIGINT, SIG_IGN);
73 quitsave = signal(SIGQUIT, SIG_IGN); 68 quitsave = signal(SIGQUIT, SIG_IGN);
74 pid = waitpid(pid, (int *)&pstat, 0); 69 pid = waitpid(pid, (int *)&pstat, 0);
75 (void)sigsetmask(omask); 70 sigprocmask(SIG_SETMASK, &omask, NULL);
76 (void)signal(SIGINT, intsave); 71 (void)signal(SIGINT, intsave);
77 (void)signal(SIGQUIT, quitsave); 72 (void)signal(SIGQUIT, quitsave);
78 return(pid == -1 ? -1 : pstat); 73 return (pid == -1 ? -1 : pstat);
79} 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}