summaryrefslogtreecommitdiff
path: root/src/lib/libc/stdlib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libc/stdlib')
-rw-r--r--src/lib/libc/stdlib/Makefile.inc72
-rw-r--r--src/lib/libc/stdlib/_Exit.c22
-rw-r--r--src/lib/libc/stdlib/_rand48.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.345
-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.327
-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.3168
-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.375
-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.3133
-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.c2077
-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.392
-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.336
-rw-r--r--src/lib/libc/stdlib/rand.c27
-rw-r--r--src/lib/libc/stdlib/rand48.361
-rw-r--r--src/lib/libc/stdlib/rand48.h4
-rw-r--r--src/lib/libc/stdlib/random.3112
-rw-r--r--src/lib/libc/stdlib/random.c134
-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.c166
-rw-r--r--src/lib/libc/stdlib/srand48.c1
-rw-r--r--src/lib/libc/stdlib/strtod.3112
-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.3130
-rw-r--r--src/lib/libc/stdlib/tsearch.c119
108 files changed, 8059 insertions, 4954 deletions
diff --git a/src/lib/libc/stdlib/Makefile.inc b/src/lib/libc/stdlib/Makefile.inc
index 782a4ab022..652d6fb90f 100644
--- a/src/lib/libc/stdlib/Makefile.inc
+++ b/src/lib/libc/stdlib/Makefile.inc
@@ -1,45 +1,65 @@
1# from: @(#)Makefile.inc 5.6 (Berkeley) 6/4/91 1# $OpenBSD: Makefile.inc,v 1.46 2012/09/15 20:59:38 miod 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") 17.elif (${MACHINE_CPU} == "i386")
17SRCS+= abs.S div.S labs.S ldiv.S 18SRCS+= abs.S div.S labs.S ldiv.S
18.elif (${MACHINE_ARCH} == "ns32k") 19.elif (${MACHINE_CPU} == "vax")
19SRCS+= abs.S div.c labs.c ldiv.c
20.elif (${MACHINE_ARCH} == "tahoe")
21SRCS+= abs.S div.c labs.c ldiv.c
22.elif (${MACHINE_ARCH} == "vax")
23SRCS+= abs.c div.c labs.c ldiv.c 20SRCS+= abs.c div.c labs.c ldiv.c
24.elif (${MACHINE_ARCH} == "alpha") 21.elif (${MACHINE_CPU} == "alpha")
25# XXX should be .S's 22# XXX should be .S's
26SRCS+= abs.c div.c labs.c ldiv.c 23SRCS+= abs.c div.c labs.c ldiv.c
27.else 24.else
28SRCS+= abs.c div.c labs.c ldiv.c 25SRCS+= abs.c div.c labs.c ldiv.c
29.endif 26.endif
30 27
31MAN+= abort.3 abs.3 alloca.3 atexit.3 atof.3 atoi.3 atol.3 bsearch.3 \ 28.if (${MACHINE_CPU} == "vax") || (${MACHINE_CPU} == "m68k")
32 calloc.3 div.3 exit.3 free.3 getenv.3 getopt.3 labs.3 ldiv.3 \ 29SRCS+= insque.S remque.S
33 malloc.3 memory.3 qabs.3 qdiv.3 qsort.3 radixsort.3 rand48.3 \ 30.else
34 rand.3 random.3 realloc.3 realpath.3 strtod.3 strtol.3 strtoul.3 \ 31SRCS+= insque.c remque.c
35 system.3 32.endif
33
34MAN+= a64l.3 abort.3 abs.3 alloca.3 atexit.3 atof.3 atoi.3 atol.3 atoll.3 \
35 bsearch.3 div.3 ecvt.3 exit.3 getenv.3 getopt.3 getopt_long.3 \
36 getsubopt.3 hcreate.3 imaxabs.3 imaxdiv.3 insque.3 labs.3 ldiv.3 \
37 lldiv.3 lsearch.3 malloc.3 posix_memalign.3 qabs.3 qdiv.3 qsort.3 \
38 radixsort.3 rand48.3 rand.3 random.3 realpath.3 strtod.3 strtonum.3 \
39 strtol.3 strtoul.3 system.3 tsearch.3
36 40
41MLINKS+=exit.3 _Exit.3
42MLINKS+=ecvt.3 fcvt.3 ecvt.3 gcvt.3
37MLINKS+=getenv.3 setenv.3 getenv.3 unsetenv.3 getenv.3 putenv.3 43MLINKS+=getenv.3 setenv.3 getenv.3 unsetenv.3 getenv.3 putenv.3
44MLINKS+=getopt_long.3 getopt_long_only.3
45MLINKS+=hcreate.3 hdestroy.3 hcreate.3 hsearch.3
46MLINKS+=insque.3 remque.3
47MLINKS+=labs.3 llabs.3
48MLINKS+=lsearch.3 lfind.3
49MLINKS+=malloc.3 free.3 malloc.3 realloc.3 malloc.3 calloc.3
50MLINKS+=malloc.3 cfree.3 malloc.3 malloc.conf.5
38MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3 51MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3
39MLINKS+=rand.3 srand.3 52MLINKS+=radixsort.3 sradixsort.3
40MLINKS+=strtol.3 strtoq.3 53MLINKS+=rand.3 srand.3 rand.3 rand_r.3
41MLINKS+=strtoul.3 strtouq.3 54MLINKS+=random.3 initstate.3 random.3 setstate.3
42MLINKS+=random.3 initstate.3 random.3 setstate.3 random.3 srandom.3 55MLINKS+=random.3 srandom.3 random.3 srandomdev.3
43MLINKS+=rand48.3 drand48.3 rand48.3 erand48.3 rand48.3 lrand48.3 56MLINKS+=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 57MLINKS+=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 58MLINKS+=rand48.3 srand48.3 rand48.3 seed48.3 rand48.3 lcong48.3
59MLINKS+=strtod.3 strtof.3 strtod.3 strtold.3
60MLINKS+=strtol.3 strtoll.3 strtol.3 strtoq.3 strtol.3 strtoimax.3
61MLINKS+=strtoul.3 strtoull.3 strtoul.3 strtouq.3 strtoul.3 strtoumax.3
62MLINKS+=tsearch.3 tfind.3
63MLINKS+=tsearch.3 tdelete.3
64MLINKS+=tsearch.3 twalk.3
65MLINKS+=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..8cc5c42ff5 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.12 2012/04/12 15:46:57 deraadt 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: April 12 2012 $
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,37 @@
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
68The
69.Fn alloca
70function
71is machine dependent; its use is discouraged.
72.\" .Sh HISTORY 57.\" .Sh HISTORY
73.\" The 58.\" The
74.\" .Fn alloca 59.\" .Fn alloca
75.\" function appeared in 60.\" function appeared in
76.\" .Bx ?? . 61.\" .Bx ?? .
77.\" The function appeared in 32v, pwb and pwb.2 and in 3bsd 4bsd 62.\" 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 63.\" The first man page (or link to a man page that I can find at the
79.\" moment is 4.3... 64.\" moment is 4.3...
65.Sh BUGS
66The
67.Fn alloca
68function is slightly unsafe because it cannot ensure that the pointer
69returned points to a valid and usable block of memory.
70The allocation made may exceed the bounds of the stack, or even go
71further into other objects in memory, and
72.Fn alloca
73cannot determine such an error.
74Avoid
75.Fn alloca
76with 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..305dd48f50 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.8 2012/07/08 10:25:55 guenther 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: July 8 2012 $
40.Dt BSEARCH 3 35.Dt BSEARCH 3
41.Os 36.Os
42.Sh NAME 37.Sh NAME
@@ -45,18 +40,18 @@
45.Sh SYNOPSIS 40.Sh SYNOPSIS
46.Fd #include <stdlib.h> 41.Fd #include <stdlib.h>
47.Ft void * 42.Ft void *
48.Fn bsearch "const void *key" "const void *base" "size_t nmemb" "size_t size" "int (*compar) (const void *, const void *)" 43.Fn bsearch "const void *key" "const void *base" "size_t nmemb" "size_t size" "int (*compar)(const void *, const void *)"
49.Sh DESCRIPTION 44.Sh DESCRIPTION
50The 45The
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..0191a3420e
--- /dev/null
+++ b/src/lib/libc/stdlib/ecvt.3
@@ -0,0 +1,168 @@
1.\" $OpenBSD: ecvt.3,v 1.10 2012/06/01 01:01:57 guenther 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: June 1 2012 $
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 ;
152as of
153.St -p1003.1-2008
154they are no longer a part of the standard.
155.Sh CAVEATS
156The
157.Fn ecvt
158and
159.Fn fcvt
160functions return a pointer to internal storage space that will be
161overwritten by subsequent calls to either function.
162.Pp
163The maximum possible precision of the return value is limited by the
164precision of a double and may not be the same on all architectures.
165.Pp
166The
167.Xr snprintf 3
168function 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..e452d454a8 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.12 2011/11/17 14:26:14 schwarze 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: November 17 2011 $
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,57 @@ 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 .
115.Sh HISTORY
116An
117.Fn exit
118function first appeared as a system call in
119.At v1 .
120In
121.At v7 ,
122the bare system call was renamed to
123.Xr _exit 2 .
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..f987eb13a1 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.18 2012/09/23 16:08:04 jeremy 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: September 23 2012 $
40.Dt GETENV 3 35.Dt GETENV 3
41.Os 36.Os
42.Sh NAME 37.Sh NAME
@@ -52,82 +47,97 @@
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,
63the given arguments
64.Ar name
65and
66.Ar value
67may be appended and prepended,
68respectively,
69with an equal sign
70.Dq Li \&= .
71.Pp 56.Pp
72The 57The
73.Fn getenv 58.Fn getenv
74function obtains the current value of the environment variable, 59function obtains the current value of the environment variable
75.Ar name . 60.Fa name .
76If the variable 61If the variable
77.Ar name 62.Fa name
78is not in the current environment , 63is not in the current environment, a null pointer is returned.
79a null pointer is returned.
80.Pp 64.Pp
81The 65The
82.Fn setenv 66.Fn setenv
83function inserts or resets the environment variable 67function inserts or resets the environment variable
84.Ar name 68.Fa name
85in the current environment list. 69in the current environment list.
86If the variable 70If the variable
87.Ar name 71.Fa name
88does not exist in the list, 72does not exist in the list, it is inserted with the given
89it is inserted with the given 73.Fa value .
90.Ar value.
91If the variable does exist, the argument 74If the variable does exist, the argument
92.Ar overwrite 75.Fa overwrite
93is tested; if 76is tested; if
94.Ar overwrite is 77.Fa overwrite
95zero, the 78is zero, the variable is not reset, otherwise it is reset to the given
96variable is not reset, otherwise it is reset 79.Fa value .
97to the given
98.Ar value .
99.Pp 80.Pp
100The 81The
101.Fn putenv 82.Fn putenv
102function takes an argument of the form ``name=value'' and is 83function takes an argument of the form
103equivalent to: 84.Ar name Ns = Ns Ar value .
104.Bd -literal -offset indent 85The memory pointed to by
105setenv(name, value, 1); 86.Ar string
106.Ed 87becomes part of the environment and must not be deallocated by the caller.
88If the variable already exists, it will be overwritten.
89A common source of bugs is to pass a
90.Ar string
91argument that is a locally scoped string buffer.
92This will result in corruption of the environment after leaving
93the scope in which the variable is defined.
94For this reason, the
95.Fn setenv
96function is preferred over
97.Fn putenv .
107.Pp 98.Pp
108The 99The
109.Fn unsetenv 100.Fn unsetenv
110function 101function deletes all instances of the variable name pointed to by
111deletes all instances of the variable name pointed to by
112.Fa name 102.Fa name
113from the list. 103from the list.
114.Sh RETURN VALUES 104.Sh RETURN VALUES
115The functions 105These functions
116.Fn setenv
117and
118.Fn putenv
119return zero if successful; otherwise the global variable 106return zero if successful; otherwise the global variable
120.Va errno 107.Va errno
121is set to indicate the error and a 108is set to indicate the error and \-1 is returned.
122\-1 is returned. 109.Pp
110If
111.Fn getenv
112is successful, the string returned should be considered read-only.
123.Sh ERRORS 113.Sh ERRORS
124.Bl -tag -width Er 114.Bl -tag -width Er
115.It Bq Er EINVAL
116The
117.Fn setenv
118or
119.Fn unsetenv
120function was passed an empty
121.Ar name
122or a NULL pointer, or was passed a
123.Ar name
124containing an
125.Sq =
126character.
127.Pp
128The
129.Fn putenv
130function was passed a
131.Ar string
132that did not contain an
133.Sq =
134character.
125.It Bq Er ENOMEM 135.It Bq Er ENOMEM
126The function 136The
127.Fn setenv 137.Fn setenv
128or 138or
129.Fn putenv 139.Fn putenv
130failed because they were unable to allocate memory for the environment. 140function failed because it was unable to allocate memory for the environment.
131.El 141.El
132.Sh SEE ALSO 142.Sh SEE ALSO
133.Xr csh 1 , 143.Xr csh 1 ,
@@ -139,13 +149,26 @@ The
139.Fn getenv 149.Fn getenv
140function conforms to 150function conforms to
141.St -ansiC . 151.St -ansiC .
152The
153.Fn putenv ,
154.Fn setenv ,
155and
156.Fn unsetenv
157functions conform to
158.St -p1003.1-2008 .
142.Sh HISTORY 159.Sh HISTORY
160The function
161.Fn getenv
162appeared in
163.At v7
164and
165.Bx 3 .
143The functions 166The functions
144.Fn setenv 167.Fn setenv
145and 168and
146.Fn unsetenv 169.Fn unsetenv
147appeared in 170appeared in
148.At v7 . 171.Bx 4.3 Tahoe .
149The 172The
150.Fn putenv 173.Fn putenv
151function appeared in 174function 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..c69ec8316a 100644
--- a/src/lib/libc/stdlib/malloc.c
+++ b/src/lib/libc/stdlib/malloc.c
@@ -1,421 +1,1816 @@
1/* $OpenBSD: malloc.c,v 1.147 2012/09/13 10:45:41 pirofti 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 (PAGE_SHIFT)
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))
66
67#define MALLOC_MAXCHUNK (1 << MALLOC_MAXSHIFT)
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
56 72
57static void morecore(); 73/*
58static int findbucket(); 74 * When the P option is active, we move allocations between half a page
75 * and a whole page towards the end, subject to alignment constraints.
76 * This is the extra headroom we allow. Set to zero to be the most
77 * strict.
78 */
79#define MALLOC_LEEWAY 0
80
81#define PAGEROUND(x) (((x) + (MALLOC_PAGEMASK)) & ~MALLOC_PAGEMASK)
59 82
60/* 83/*
61 * The overhead on a block is at least 4 bytes. When free, this space 84 * What to use for Junk. This is the byte value we use to fill with
62 * contains a pointer to the next free block, and the bottom two bits must 85 * when the 'J' option is enabled. Use SOME_JUNK right after alloc,
63 * be zero. When in use, the first byte is set to MAGIC, and the second 86 * and SOME_FREEJUNK right before free.
64 * byte is the size index. The remaining bytes are for alignment.
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 */ 87 */
70union overhead { 88#define SOME_JUNK 0xd0 /* as in "Duh" :-) */
71 union overhead *ov_next; /* when free */ 89#define SOME_FREEJUNK 0xdf
72 struct { 90
73 u_char ovu_magic; /* magic number */ 91#define MMAP(sz) mmap(NULL, (size_t)(sz), PROT_READ | PROT_WRITE, \
74 u_char ovu_index; /* bucket # */ 92 MAP_ANON | MAP_PRIVATE, -1, (off_t) 0)
75#ifdef RCHECK 93
76 u_short ovu_rmagic; /* range magic number */ 94#define MMAPA(a,sz) mmap((a), (size_t)(sz), PROT_READ | PROT_WRITE, \
77 u_long ovu_size; /* actual block size */ 95 MAP_ANON | MAP_PRIVATE, -1, (off_t) 0)
96
97#define MQUERY(a, sz) mquery((a), (size_t)(sz), PROT_READ | PROT_WRITE, \
98 MAP_ANON | MAP_PRIVATE | MAP_FIXED, -1, (off_t)0)
99
100struct region_info {
101 void *p; /* page; low bits used to mark chunks */
102 uintptr_t size; /* size for pages, or chunk_info pointer */
103#ifdef MALLOC_STATS
104 void *f; /* where allocated from */
78#endif 105#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}; 106};
85 107
86#define MAGIC 0xef /* magic # on accounting info */ 108LIST_HEAD(chunk_head, chunk_info);
87#define RMAGIC 0x5555 /* magic # on range info */
88 109
89#ifdef RCHECK 110struct dir_info {
90#define RSLOP sizeof (u_short) 111 u_int32_t canary1;
112 struct region_info *r; /* region slots */
113 size_t regions_total; /* number of region slots */
114 size_t regions_free; /* number of free slots */
115 /* lists of free chunk info structs */
116 struct chunk_head chunk_info_list[MALLOC_MAXSHIFT + 1];
117 /* lists of chunks with free slots */
118 struct chunk_head chunk_dir[MALLOC_MAXSHIFT + 1];
119 size_t free_regions_size; /* free pages cached */
120 /* free pages cache */
121 struct region_info free_regions[MALLOC_MAXCACHE];
122 /* delayed free chunk slots */
123 void *delayed_chunks[MALLOC_DELAYED_CHUNKS + 1];
124 u_short chunk_start;
125#ifdef MALLOC_STATS
126 size_t inserts;
127 size_t insert_collisions;
128 size_t finds;
129 size_t find_collisions;
130 size_t deletes;
131 size_t delete_moves;
132 size_t cheap_realloc_tries;
133 size_t cheap_reallocs;
134#define STATS_INC(x) ((x)++)
135#define STATS_ZERO(x) ((x) = 0)
136#define STATS_SETF(x,y) ((x)->f = (y))
91#else 137#else
92#define RSLOP 0 138#define STATS_INC(x) /* nothing */
93#endif 139#define STATS_ZERO(x) /* nothing */
140#define STATS_SETF(x,y) /* nothing */
141#endif /* MALLOC_STATS */
142 u_int32_t canary2;
143};
144#define DIR_INFO_RSZ ((sizeof(struct dir_info) + MALLOC_PAGEMASK) & \
145 ~MALLOC_PAGEMASK)
94 146
95/* 147/*
96 * nextf[i] is the pointer to the next free block of size 2^(i+3). The 148 * This structure describes a page worth of chunks.
97 * smallest allocatable block is 8 bytes. The overhead information 149 *
98 * precedes the data area returned to the user. 150 * How many bits per u_short in the bitmap
99 */ 151 */
100#define NBUCKETS 30 152#define MALLOC_BITS (NBBY * sizeof(u_short))
101static union overhead *nextf[NBUCKETS]; 153struct chunk_info {
102extern char *sbrk(); 154 LIST_ENTRY(chunk_info) entries;
155 void *page; /* pointer to the page */
156 u_int32_t canary;
157 u_short size; /* size of this page's chunks */
158 u_short shift; /* how far to shift for this size */
159 u_short free; /* how many free chunks */
160 u_short total; /* how many chunk */
161 /* which chunks are free */
162 u_short bits[1];
163};
164
165struct malloc_readonly {
166 struct dir_info *g_pool; /* Main bookkeeping information */
167 int malloc_abort; /* abort() on error */
168 int malloc_freeprot; /* mprotect free pages PROT_NONE? */
169 int malloc_hint; /* call madvice on free pages? */
170 int malloc_junk; /* junk fill? */
171 int malloc_move; /* move allocations to end of page? */
172 int malloc_realloc; /* always realloc? */
173 int malloc_xmalloc; /* xmalloc behaviour? */
174 int malloc_zero; /* zero fill? */
175 size_t malloc_guard; /* use guard pages after allocations? */
176 u_int malloc_cache; /* free pages we cache */
177#ifdef MALLOC_STATS
178 int malloc_stats; /* dump statistics at end */
179#endif
180 u_int32_t malloc_canary; /* Matched against ones in g_pool */
181};
103 182
104static int pagesz; /* page size */ 183/* This object is mapped PROT_READ after initialisation to prevent tampering */
105static int pagebucket; /* page size bucket */ 184static union {
185 struct malloc_readonly mopts;
186 u_char _pad[MALLOC_PAGESIZE];
187} malloc_readonly __attribute__((aligned(MALLOC_PAGESIZE)));
188#define mopts malloc_readonly.mopts
189#define g_pool mopts.g_pool
106 190
107#ifdef MSTATS 191char *malloc_options; /* compile-time options */
108/* 192
109 * nmalloc[i] is the difference between the number of mallocs and frees 193static char *malloc_func; /* current function */
110 * for a given block size. 194static int malloc_active; /* status of malloc */
195
196static size_t malloc_guarded; /* bytes used for guards */
197static size_t malloc_used; /* bytes allocated */
198
199static size_t rnibblesused; /* random nibbles used */
200static u_char rbytes[512]; /* random bytes */
201static u_char getrnibble(void);
202
203extern char *__progname;
204
205#ifdef MALLOC_STATS
206void malloc_dump(int);
207static void malloc_exit(void);
208#define CALLER __builtin_return_address(0)
209#else
210#define CALLER NULL
211#endif
212
213/* low bits of r->p determine size: 0 means >= page size and p->size holding
214 * real size, otherwise r->size is a shift count, or 1 for malloc(0)
111 */ 215 */
112static u_int nmalloc[NBUCKETS]; 216#define REALSIZE(sz, r) \
113#include <stdio.h> 217 (sz) = (uintptr_t)(r)->p & MALLOC_PAGEMASK, \
218 (sz) = ((sz) == 0 ? (r)->size : ((sz) == 1 ? 0 : (1 << ((sz)-1))))
219
220static inline size_t
221hash(void *p)
222{
223 size_t sum;
224 union {
225 uintptr_t p;
226 unsigned short a[sizeof(void *) / sizeof(short)];
227 } u;
228 u.p = (uintptr_t)p >> MALLOC_PAGESHIFT;
229 sum = u.a[0];
230 sum = (sum << 7) - sum + u.a[1];
231#ifdef __LP64__
232 sum = (sum << 7) - sum + u.a[2];
233 sum = (sum << 7) - sum + u.a[3];
114#endif 234#endif
235 return sum;
236}
115 237
116#if defined(DEBUG) || defined(RCHECK) 238static void
117#define ASSERT(p) if (!(p)) botch("p") 239wrterror(char *msg, void *p)
118#include <stdio.h>
119static
120botch(s)
121 char *s;
122{ 240{
123 fprintf(stderr, "\r\nassertion botched: %s\r\n", s); 241 char *q = " error: ";
124 (void) fflush(stderr); /* just in case user buffered it */ 242 struct iovec iov[6];
125 abort(); 243 char buf[20];
244 int saved_errno = errno;
245
246 iov[0].iov_base = __progname;
247 iov[0].iov_len = strlen(__progname);
248 iov[1].iov_base = malloc_func;
249 iov[1].iov_len = strlen(malloc_func);
250 iov[2].iov_base = q;
251 iov[2].iov_len = strlen(q);
252 iov[3].iov_base = msg;
253 iov[3].iov_len = strlen(msg);
254 iov[4].iov_base = buf;
255 if (p == NULL)
256 iov[4].iov_len = 0;
257 else {
258 snprintf(buf, sizeof(buf), " %p", p);
259 iov[4].iov_len = strlen(buf);
260 }
261 iov[5].iov_base = "\n";
262 iov[5].iov_len = 1;
263 writev(STDERR_FILENO, iov, 6);
264
265#ifdef MALLOC_STATS
266 if (mopts.malloc_stats)
267 malloc_dump(STDERR_FILENO);
268#endif /* MALLOC_STATS */
269
270 errno = saved_errno;
271 if (mopts.malloc_abort)
272 abort();
126} 273}
127#else
128#define ASSERT(p)
129#endif
130 274
131void * 275static void
132malloc(nbytes) 276rbytes_init(void)
133 size_t nbytes; 277{
278 arc4random_buf(rbytes, sizeof(rbytes));
279 rnibblesused = 0;
280}
281
282static inline u_char
283getrnibble(void)
284{
285 u_char x;
286
287 if (rnibblesused >= 2 * sizeof(rbytes))
288 rbytes_init();
289 x = rbytes[rnibblesused++ / 2];
290 return (rnibblesused & 1 ? x & 0xf : x >> 4);
291}
292
293/*
294 * Cache maintenance. We keep at most malloc_cache pages cached.
295 * If the cache is becoming full, unmap pages in the cache for real,
296 * and then add the region to the cache
297 * Opposed to the regular region data structure, the sizes in the
298 * cache are in MALLOC_PAGESIZE units.
299 */
300static void
301unmap(struct dir_info *d, void *p, size_t sz)
302{
303 size_t psz = sz >> MALLOC_PAGESHIFT;
304 size_t rsz, tounmap;
305 struct region_info *r;
306 u_int i, offset;
307
308 if (sz != PAGEROUND(sz)) {
309 wrterror("munmap round", NULL);
310 return;
311 }
312
313 if (psz > mopts.malloc_cache) {
314 if (munmap(p, sz))
315 wrterror("munmap", p);
316 malloc_used -= sz;
317 return;
318 }
319 tounmap = 0;
320 rsz = mopts.malloc_cache - d->free_regions_size;
321 if (psz > rsz)
322 tounmap = psz - rsz;
323 offset = getrnibble() + getrnibble() << 4;
324 for (i = 0; tounmap > 0 && i < mopts.malloc_cache; i++) {
325 r = &d->free_regions[(i + offset) & (mopts.malloc_cache - 1)];
326 if (r->p != NULL) {
327 rsz = r->size << MALLOC_PAGESHIFT;
328 if (munmap(r->p, rsz))
329 wrterror("munmap", r->p);
330 r->p = NULL;
331 if (tounmap > r->size)
332 tounmap -= r->size;
333 else
334 tounmap = 0;
335 d->free_regions_size -= r->size;
336 r->size = 0;
337 malloc_used -= rsz;
338 }
339 }
340 if (tounmap > 0)
341 wrterror("malloc cache underflow", NULL);
342 for (i = 0; i < mopts.malloc_cache; i++) {
343 r = &d->free_regions[(i + offset) & (mopts.malloc_cache - 1)];
344 if (r->p == NULL) {
345 if (mopts.malloc_hint)
346 madvise(p, sz, MADV_FREE);
347 if (mopts.malloc_freeprot)
348 mprotect(p, sz, PROT_NONE);
349 r->p = p;
350 r->size = psz;
351 d->free_regions_size += psz;
352 break;
353 }
354 }
355 if (i == mopts.malloc_cache)
356 wrterror("malloc free slot lost", NULL);
357 if (d->free_regions_size > mopts.malloc_cache)
358 wrterror("malloc cache overflow", NULL);
359}
360
361static void
362zapcacheregion(struct dir_info *d, void *p, size_t len)
363{
364 u_int i;
365 struct region_info *r;
366 size_t rsz;
367
368 for (i = 0; i < mopts.malloc_cache; i++) {
369 r = &d->free_regions[i];
370 if (r->p >= p && r->p <= (void *)((char *)p + len)) {
371 rsz = r->size << MALLOC_PAGESHIFT;
372 if (munmap(r->p, rsz))
373 wrterror("munmap", r->p);
374 r->p = NULL;
375 d->free_regions_size -= r->size;
376 r->size = 0;
377 malloc_used -= rsz;
378 }
379 }
380}
381
382static void *
383map(struct dir_info *d, size_t sz, int zero_fill)
384{
385 size_t psz = sz >> MALLOC_PAGESHIFT;
386 struct region_info *r, *big = NULL;
387 u_int i, offset;
388 void *p;
389
390 if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) ||
391 d->canary1 != ~d->canary2)
392 wrterror("internal struct corrupt", NULL);
393 if (sz != PAGEROUND(sz)) {
394 wrterror("map round", NULL);
395 return MAP_FAILED;
396 }
397 if (psz > d->free_regions_size) {
398 p = MMAP(sz);
399 if (p != MAP_FAILED)
400 malloc_used += sz;
401 /* zero fill not needed */
402 return p;
403 }
404 offset = getrnibble() + getrnibble() << 4;
405 for (i = 0; i < mopts.malloc_cache; i++) {
406 r = &d->free_regions[(i + offset) & (mopts.malloc_cache - 1)];
407 if (r->p != NULL) {
408 if (r->size == psz) {
409 p = r->p;
410 if (mopts.malloc_freeprot)
411 mprotect(p, sz, PROT_READ | PROT_WRITE);
412 if (mopts.malloc_hint)
413 madvise(p, sz, MADV_NORMAL);
414 r->p = NULL;
415 r->size = 0;
416 d->free_regions_size -= psz;
417 if (zero_fill)
418 memset(p, 0, sz);
419 else if (mopts.malloc_junk &&
420 mopts.malloc_freeprot)
421 memset(p, SOME_FREEJUNK, sz);
422 return p;
423 } else if (r->size > psz)
424 big = r;
425 }
426 }
427 if (big != NULL) {
428 r = big;
429 p = (char *)r->p + ((r->size - psz) << MALLOC_PAGESHIFT);
430 if (mopts.malloc_freeprot)
431 mprotect(p, sz, PROT_READ | PROT_WRITE);
432 if (mopts.malloc_hint)
433 madvise(p, sz, MADV_NORMAL);
434 r->size -= psz;
435 d->free_regions_size -= psz;
436 if (zero_fill)
437 memset(p, 0, sz);
438 else if (mopts.malloc_junk && mopts.malloc_freeprot)
439 memset(p, SOME_FREEJUNK, sz);
440 return p;
441 }
442 p = MMAP(sz);
443 if (p != MAP_FAILED)
444 malloc_used += sz;
445 if (d->free_regions_size > mopts.malloc_cache)
446 wrterror("malloc cache", NULL);
447 /* zero fill not needed */
448 return p;
449}
450
451/*
452 * Initialize a dir_info, which should have been cleared by caller
453 */
454static int
455omalloc_init(struct dir_info **dp)
134{ 456{
135 register union overhead *op; 457 char *p, b[64];
136 register long bucket, n; 458 int i, j;
137 register unsigned amt; 459 size_t d_avail, regioninfo_size;
460 struct dir_info *d;
461
462 rbytes_init();
138 463
139 /* 464 /*
140 * First time malloc is called, setup page size and 465 * Default options
141 * align break pointer so all data will be page aligned.
142 */ 466 */
143 if (pagesz == 0) { 467 mopts.malloc_abort = 1;
144 pagesz = n = getpagesize(); 468 mopts.malloc_move = 1;
145 op = (union overhead *)sbrk(0); 469 mopts.malloc_cache = MALLOC_DEFAULT_CACHE;
146 n = n - sizeof (*op) - ((long)op & (n - 1)); 470
147 if (n < 0) 471 for (i = 0; i < 3; i++) {
148 n += pagesz; 472 switch (i) {
149 if (n) { 473 case 0:
150 if (sbrk(n) == (char *)-1) 474 j = readlink("/etc/malloc.conf", b, sizeof b - 1);
151 return (NULL); 475 if (j <= 0)
476 continue;
477 b[j] = '\0';
478 p = b;
479 break;
480 case 1:
481 if (issetugid() == 0)
482 p = getenv("MALLOC_OPTIONS");
483 else
484 continue;
485 break;
486 case 2:
487 p = malloc_options;
488 break;
489 default:
490 p = NULL;
152 } 491 }
153 bucket = 0; 492
154 amt = 8; 493 for (; p != NULL && *p != '\0'; p++) {
155 while (pagesz > amt) { 494 switch (*p) {
156 amt <<= 1; 495 case '>':
157 bucket++; 496 mopts.malloc_cache <<= 1;
497 if (mopts.malloc_cache > MALLOC_MAXCACHE)
498 mopts.malloc_cache = MALLOC_MAXCACHE;
499 break;
500 case '<':
501 mopts.malloc_cache >>= 1;
502 break;
503 case 'a':
504 mopts.malloc_abort = 0;
505 break;
506 case 'A':
507 mopts.malloc_abort = 1;
508 break;
509#ifdef MALLOC_STATS
510 case 'd':
511 mopts.malloc_stats = 0;
512 break;
513 case 'D':
514 mopts.malloc_stats = 1;
515 break;
516#endif /* MALLOC_STATS */
517 case 'f':
518 mopts.malloc_freeprot = 0;
519 break;
520 case 'F':
521 mopts.malloc_freeprot = 1;
522 break;
523 case 'g':
524 mopts.malloc_guard = 0;
525 break;
526 case 'G':
527 mopts.malloc_guard = MALLOC_PAGESIZE;
528 break;
529 case 'h':
530 mopts.malloc_hint = 0;
531 break;
532 case 'H':
533 mopts.malloc_hint = 1;
534 break;
535 case 'j':
536 mopts.malloc_junk = 0;
537 break;
538 case 'J':
539 mopts.malloc_junk = 1;
540 break;
541 case 'n':
542 case 'N':
543 break;
544 case 'p':
545 mopts.malloc_move = 0;
546 break;
547 case 'P':
548 mopts.malloc_move = 1;
549 break;
550 case 'r':
551 mopts.malloc_realloc = 0;
552 break;
553 case 'R':
554 mopts.malloc_realloc = 1;
555 break;
556 case 's':
557 mopts.malloc_freeprot = mopts.malloc_junk = 0;
558 mopts.malloc_guard = 0;
559 mopts.malloc_cache = MALLOC_DEFAULT_CACHE;
560 break;
561 case 'S':
562 mopts.malloc_freeprot = mopts.malloc_junk = 1;
563 mopts.malloc_guard = MALLOC_PAGESIZE;
564 mopts.malloc_cache = 0;
565 break;
566 case 'x':
567 mopts.malloc_xmalloc = 0;
568 break;
569 case 'X':
570 mopts.malloc_xmalloc = 1;
571 break;
572 case 'z':
573 mopts.malloc_zero = 0;
574 break;
575 case 'Z':
576 mopts.malloc_zero = 1;
577 break;
578 default: {
579 static const char q[] = "malloc() warning: "
580 "unknown char in MALLOC_OPTIONS\n";
581 write(STDERR_FILENO, q, sizeof(q) - 1);
582 break;
583 }
584 }
158 } 585 }
159 pagebucket = bucket;
160 } 586 }
587
161 /* 588 /*
162 * Convert amount of memory requested into closest block size 589 * We want junk in the entire allocation, and zero only in the part
163 * stored in hash buckets which satisfies request. 590 * the user asked for.
164 * Account for space used per block for accounting.
165 */ 591 */
166 if (nbytes <= (n = pagesz - sizeof (*op) - RSLOP)) { 592 if (mopts.malloc_zero)
167#ifndef RCHECK 593 mopts.malloc_junk = 1;
168 amt = 8; /* size of first bucket */ 594
169 bucket = 0; 595#ifdef MALLOC_STATS
170#else 596 if (mopts.malloc_stats && (atexit(malloc_exit) == -1)) {
171 amt = 16; /* size of first bucket */ 597 static const char q[] = "malloc() warning: atexit(2) failed."
172 bucket = 1; 598 " Will not be able to dump stats on exit\n";
173#endif 599 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 } 600 }
601#endif /* MALLOC_STATS */
602
603 while ((mopts.malloc_canary = arc4random()) == 0)
604 ;
605
185 /* 606 /*
186 * If nothing in hash bucket right now, 607 * Allocate dir_info with a guard page on either side. Also
187 * request more memory from the system. 608 * randomise offset inside the page at which the dir_info
609 * lies (subject to alignment by 1 << MALLOC_MINSHIFT)
188 */ 610 */
189 if ((op = nextf[bucket]) == NULL) { 611 if ((p = MMAP(DIR_INFO_RSZ + (MALLOC_PAGESIZE * 2))) == MAP_FAILED)
190 morecore(bucket); 612 return -1;
191 if ((op = nextf[bucket]) == NULL) 613 mprotect(p, MALLOC_PAGESIZE, PROT_NONE);
192 return (NULL); 614 mprotect(p + MALLOC_PAGESIZE + DIR_INFO_RSZ,
193 } 615 MALLOC_PAGESIZE, PROT_NONE);
194 /* remove from linked list */ 616 d_avail = (DIR_INFO_RSZ - sizeof(*d)) >> MALLOC_MINSHIFT;
195 nextf[bucket] = op->ov_next; 617 d = (struct dir_info *)(p + MALLOC_PAGESIZE +
196 op->ov_magic = MAGIC; 618 (arc4random_uniform(d_avail) << MALLOC_MINSHIFT));
197 op->ov_index = bucket; 619
198#ifdef MSTATS 620 d->regions_free = d->regions_total = MALLOC_INITIAL_REGIONS;
199 nmalloc[bucket]++; 621 regioninfo_size = d->regions_total * sizeof(struct region_info);
200#endif 622 d->r = MMAP(regioninfo_size);
201#ifdef RCHECK 623 if (d->r == MAP_FAILED) {
624 wrterror("malloc init mmap failed", NULL);
625 d->regions_total = 0;
626 return 1;
627 }
628 for (i = 0; i <= MALLOC_MAXSHIFT; i++) {
629 LIST_INIT(&d->chunk_info_list[i]);
630 LIST_INIT(&d->chunk_dir[i]);
631 }
632 malloc_used += regioninfo_size;
633 d->canary1 = mopts.malloc_canary ^ (u_int32_t)(uintptr_t)d;
634 d->canary2 = ~d->canary1;
635
636 *dp = d;
637
202 /* 638 /*
203 * Record allocated size of block and 639 * Options have been set and will never be reset.
204 * bound space with magic numbers. 640 * Prevent further tampering with them.
205 */ 641 */
206 op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); 642 if (((uintptr_t)&malloc_readonly & MALLOC_PAGEMASK) == 0)
207 op->ov_rmagic = RMAGIC; 643 mprotect(&malloc_readonly, sizeof(malloc_readonly), PROT_READ);
208 *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC; 644
645 return 0;
646}
647
648static int
649omalloc_grow(struct dir_info *d)
650{
651 size_t newtotal;
652 size_t newsize;
653 size_t mask;
654 size_t i;
655 struct region_info *p;
656
657 if (d->regions_total > SIZE_MAX / sizeof(struct region_info) / 2 )
658 return 1;
659
660 newtotal = d->regions_total * 2;
661 newsize = newtotal * sizeof(struct region_info);
662 mask = newtotal - 1;
663
664 p = MMAP(newsize);
665 if (p == MAP_FAILED)
666 return 1;
667
668 malloc_used += newsize;
669 memset(p, 0, newsize);
670 STATS_ZERO(d->inserts);
671 STATS_ZERO(d->insert_collisions);
672 for (i = 0; i < d->regions_total; i++) {
673 void *q = d->r[i].p;
674 if (q != NULL) {
675 size_t index = hash(q) & mask;
676 STATS_INC(d->inserts);
677 while (p[index].p != NULL) {
678 index = (index - 1) & mask;
679 STATS_INC(d->insert_collisions);
680 }
681 p[index] = d->r[i];
682 }
683 }
684 /* avoid pages containing meta info to end up in cache */
685 if (munmap(d->r, d->regions_total * sizeof(struct region_info)))
686 wrterror("munmap", d->r);
687 else
688 malloc_used -= d->regions_total * sizeof(struct region_info);
689 d->regions_free = d->regions_free + d->regions_total;
690 d->regions_total = newtotal;
691 d->r = p;
692 return 0;
693}
694
695static struct chunk_info *
696alloc_chunk_info(struct dir_info *d, int bits)
697{
698 struct chunk_info *p;
699 size_t size, count;
700
701 if (bits == 0)
702 count = MALLOC_PAGESIZE / MALLOC_MINSIZE;
703 else
704 count = MALLOC_PAGESIZE >> bits;
705
706 size = howmany(count, MALLOC_BITS);
707 size = sizeof(struct chunk_info) + (size - 1) * sizeof(u_short);
708 size = ALIGN(size);
709
710 if (LIST_EMPTY(&d->chunk_info_list[bits])) {
711 void *q;
712 int i;
713
714 q = MMAP(MALLOC_PAGESIZE);
715 if (q == MAP_FAILED)
716 return NULL;
717 malloc_used += MALLOC_PAGESIZE;
718 count = MALLOC_PAGESIZE / size;
719 for (i = 0; i < count; i++, q += size)
720 LIST_INSERT_HEAD(&d->chunk_info_list[bits],
721 (struct chunk_info *)q, entries);
722 }
723 p = LIST_FIRST(&d->chunk_info_list[bits]);
724 LIST_REMOVE(p, entries);
725 memset(p, 0, size);
726 p->canary = d->canary1;
727 return p;
728}
729
730
731/*
732 * The hashtable uses the assumption that p is never NULL. This holds since
733 * non-MAP_FIXED mappings with hint 0 start at BRKSIZ.
734 */
735static int
736insert(struct dir_info *d, void *p, size_t sz, void *f)
737{
738 size_t index;
739 size_t mask;
740 void *q;
741
742 if (d->regions_free * 4 < d->regions_total) {
743 if (omalloc_grow(d))
744 return 1;
745 }
746 mask = d->regions_total - 1;
747 index = hash(p) & mask;
748 q = d->r[index].p;
749 STATS_INC(d->inserts);
750 while (q != NULL) {
751 index = (index - 1) & mask;
752 q = d->r[index].p;
753 STATS_INC(d->insert_collisions);
754 }
755 d->r[index].p = p;
756 d->r[index].size = sz;
757#ifdef MALLOC_STATS
758 d->r[index].f = f;
209#endif 759#endif
210 return ((char *)(op + 1)); 760 d->regions_free--;
761 return 0;
211} 762}
212 763
764static struct region_info *
765find(struct dir_info *d, void *p)
766{
767 size_t index;
768 size_t mask = d->regions_total - 1;
769 void *q, *r;
770
771 if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) ||
772 d->canary1 != ~d->canary2)
773 wrterror("internal struct corrupt", NULL);
774 p = MASK_POINTER(p);
775 index = hash(p) & mask;
776 r = d->r[index].p;
777 q = MASK_POINTER(r);
778 STATS_INC(d->finds);
779 while (q != p && r != NULL) {
780 index = (index - 1) & mask;
781 r = d->r[index].p;
782 q = MASK_POINTER(r);
783 STATS_INC(d->find_collisions);
784 }
785 return (q == p && r != NULL) ? &d->r[index] : NULL;
786}
787
788static void
789delete(struct dir_info *d, struct region_info *ri)
790{
791 /* algorithm R, Knuth Vol III section 6.4 */
792 size_t mask = d->regions_total - 1;
793 size_t i, j, r;
794
795 if (d->regions_total & (d->regions_total - 1))
796 wrterror("regions_total not 2^x", NULL);
797 d->regions_free++;
798 STATS_INC(g_pool->deletes);
799
800 i = ri - d->r;
801 for (;;) {
802 d->r[i].p = NULL;
803 d->r[i].size = 0;
804 j = i;
805 for (;;) {
806 i = (i - 1) & mask;
807 if (d->r[i].p == NULL)
808 return;
809 r = hash(d->r[i].p) & mask;
810 if ((i <= r && r < j) || (r < j && j < i) ||
811 (j < i && i <= r))
812 continue;
813 d->r[j] = d->r[i];
814 STATS_INC(g_pool->delete_moves);
815 break;
816 }
817
818 }
819}
820
213/* 821/*
214 * Allocate more memory to the indicated bucket. 822 * Allocate a page of chunks
215 */ 823 */
216static void 824static struct chunk_info *
217morecore(bucket) 825omalloc_make_chunks(struct dir_info *d, int bits)
218 int bucket;
219{ 826{
220 register union overhead *op; 827 struct chunk_info *bp;
221 register long sz; /* size of desired block */ 828 void *pp;
222 long amt; /* amount to allocate */ 829 int i, k;
223 int nblks; /* how many blocks we get */
224 830
225 /* 831 /* Allocate a new bucket */
226 * sbrk_size <= 0 only for big, FLUFFY, requests (about 832 pp = map(d, MALLOC_PAGESIZE, 0);
227 * 2^30 bytes on a VAX, I think) or for a negative arg. 833 if (pp == MAP_FAILED)
228 */ 834 return NULL;
229 sz = 1 << (bucket + 3); 835
230#ifdef DEBUG 836 bp = alloc_chunk_info(d, bits);
231 ASSERT(sz > 0); 837 if (bp == NULL) {
232#else 838 unmap(d, pp, MALLOC_PAGESIZE);
233 if (sz <= 0) 839 return NULL;
234 return; 840 }
235#endif 841
236 if (sz < pagesz) { 842 /* memory protect the page allocated in the malloc(0) case */
237 amt = pagesz; 843 if (bits == 0) {
238 nblks = amt / sz; 844 bp->size = 0;
845 bp->shift = 1;
846 i = MALLOC_MINSIZE - 1;
847 while (i >>= 1)
848 bp->shift++;
849 bp->total = bp->free = MALLOC_PAGESIZE >> bp->shift;
850 bp->page = pp;
851
852 k = mprotect(pp, MALLOC_PAGESIZE, PROT_NONE);
853 if (k < 0) {
854 unmap(d, pp, MALLOC_PAGESIZE);
855 LIST_INSERT_HEAD(&d->chunk_info_list[0], bp, entries);
856 return NULL;
857 }
239 } else { 858 } else {
240 amt = sz + pagesz; 859 bp->size = 1U << bits;
241 nblks = 1; 860 bp->shift = bits;
861 bp->total = bp->free = MALLOC_PAGESIZE >> bits;
862 bp->page = pp;
242 } 863 }
243 op = (union overhead *)sbrk(amt); 864
244 /* no more room! */ 865 /* set all valid bits in the bitmap */
245 if ((long)op == -1) 866 k = bp->total;
246 return; 867 i = 0;
247 /* 868
248 * Add new memory allocated to that on 869 /* Do a bunch at a time */
249 * free list for this hash bucket. 870 for (; (k - i) >= MALLOC_BITS; i += MALLOC_BITS)
250 */ 871 bp->bits[i / MALLOC_BITS] = (u_short)~0U;
251 nextf[bucket] = op; 872
252 while (--nblks > 0) { 873 for (; i < k; i++)
253 op->ov_next = (union overhead *)((caddr_t)op + sz); 874 bp->bits[i / MALLOC_BITS] |= (u_short)1U << (i % MALLOC_BITS);
254 op = (union overhead *)((caddr_t)op + sz); 875
255 } 876 LIST_INSERT_HEAD(&d->chunk_dir[bits], bp, entries);
877
878 bits++;
879 if ((uintptr_t)pp & bits)
880 wrterror("pp & bits", pp);
881
882 insert(d, (void *)((uintptr_t)pp | bits), (uintptr_t)bp, NULL);
883 return bp;
256} 884}
257 885
258void 886
259free(cp) 887/*
260 void *cp; 888 * Allocate a chunk
261{ 889 */
262 register long size; 890static void *
263 register union overhead *op; 891malloc_bytes(struct dir_info *d, size_t size, void *f)
264 892{
265 if (cp == NULL) 893 int i, j;
266 return; 894 size_t k;
267 op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); 895 u_short u, *lp;
268#ifdef DEBUG 896 struct chunk_info *bp;
269 ASSERT(op->ov_magic == MAGIC); /* make sure it was in use */ 897
270#else 898 if (mopts.malloc_canary != (d->canary1 ^ (u_int32_t)(uintptr_t)d) ||
271 if (op->ov_magic != MAGIC) 899 d->canary1 != ~d->canary2)
272 return; /* sanity */ 900 wrterror("internal struct corrupt", NULL);
273#endif 901 /* Don't bother with anything less than this */
274#ifdef RCHECK 902 /* unless we have a malloc(0) requests */
275 ASSERT(op->ov_rmagic == RMAGIC); 903 if (size != 0 && size < MALLOC_MINSIZE)
276 ASSERT(*(u_short *)((caddr_t)(op + 1) + op->ov_size) == RMAGIC); 904 size = MALLOC_MINSIZE;
277#endif 905
278 size = op->ov_index; 906 /* Find the right bucket */
279 ASSERT(size < NBUCKETS); 907 if (size == 0)
280 op->ov_next = nextf[size]; /* also clobbers ov_magic */ 908 j = 0;
281 nextf[size] = op; 909 else {
282#ifdef MSTATS 910 j = MALLOC_MINSHIFT;
283 nmalloc[size]--; 911 i = (size - 1) >> (MALLOC_MINSHIFT - 1);
912 while (i >>= 1)
913 j++;
914 }
915
916 /* If it's empty, make a page more of that size chunks */
917 if (LIST_EMPTY(&d->chunk_dir[j])) {
918 bp = omalloc_make_chunks(d, j);
919 if (bp == NULL)
920 return NULL;
921 } else
922 bp = LIST_FIRST(&d->chunk_dir[j]);
923
924 if (bp->canary != d->canary1)
925 wrterror("chunk info corrupted", NULL);
926
927 i = d->chunk_start;
928 if (bp->free > 1)
929 i += getrnibble();
930 if (i >= bp->total)
931 i &= bp->total - 1;
932 for (;;) {
933 for (;;) {
934 lp = &bp->bits[i / MALLOC_BITS];
935 if (!*lp) {
936 i += MALLOC_BITS;
937 i &= ~(MALLOC_BITS - 1);
938 if (i >= bp->total)
939 i = 0;
940 } else
941 break;
942 }
943 k = i % MALLOC_BITS;
944 u = 1 << k;
945 if (*lp & u)
946 break;
947 if (++i >= bp->total)
948 i = 0;
949 }
950 d->chunk_start += i + 1;
951#ifdef MALLOC_STATS
952 if (i == 0) {
953 struct region_info *r = find(d, bp->page);
954 r->f = f;
955 }
284#endif 956#endif
957
958 *lp ^= u;
959
960 /* If there are no more free, remove from free-list */
961 if (!--bp->free)
962 LIST_REMOVE(bp, entries);
963
964 /* Adjust to the real offset of that chunk */
965 k += (lp - bp->bits) * MALLOC_BITS;
966 k <<= bp->shift;
967
968 if (mopts.malloc_junk && bp->size > 0)
969 memset((char *)bp->page + k, SOME_JUNK, bp->size);
970 return ((char *)bp->page + k);
971}
972
973
974/*
975 * Free a chunk, and possibly the page it's on, if the page becomes empty.
976 */
977static void
978free_bytes(struct dir_info *d, struct region_info *r, void *ptr)
979{
980 struct chunk_head *mp;
981 struct chunk_info *info;
982 int i;
983
984 info = (struct chunk_info *)r->size;
985 if (info->canary != d->canary1)
986 wrterror("chunk info corrupted", NULL);
987
988 /* Find the chunk number on the page */
989 i = ((uintptr_t)ptr & MALLOC_PAGEMASK) >> info->shift;
990
991 if ((uintptr_t)ptr & ((1U << (info->shift)) - 1)) {
992 wrterror("modified chunk-pointer", ptr);
993 return;
994 }
995 if (info->bits[i / MALLOC_BITS] & (1U << (i % MALLOC_BITS))) {
996 wrterror("chunk is already free", ptr);
997 return;
998 }
999
1000 info->bits[i / MALLOC_BITS] |= 1U << (i % MALLOC_BITS);
1001 info->free++;
1002
1003 if (info->size != 0)
1004 mp = d->chunk_dir + info->shift;
1005 else
1006 mp = d->chunk_dir;
1007
1008 if (info->free == 1) {
1009 /* Page became non-full */
1010 LIST_INSERT_HEAD(mp, info, entries);
1011 return;
1012 }
1013 if (info->free != info->total)
1014 return;
1015
1016 LIST_REMOVE(info, entries);
1017
1018 if (info->size == 0 && !mopts.malloc_freeprot)
1019 mprotect(info->page, MALLOC_PAGESIZE, PROT_READ | PROT_WRITE);
1020 unmap(d, info->page, MALLOC_PAGESIZE);
1021
1022 delete(d, r);
1023 if (info->size != 0)
1024 mp = &d->chunk_info_list[info->shift];
1025 else
1026 mp = &d->chunk_info_list[0];
1027 LIST_INSERT_HEAD(mp, info, entries);
1028}
1029
1030
1031
1032static void *
1033omalloc(size_t sz, int zero_fill, void *f)
1034{
1035 void *p;
1036 size_t psz;
1037
1038 if (sz > MALLOC_MAXCHUNK) {
1039 if (sz >= SIZE_MAX - mopts.malloc_guard - MALLOC_PAGESIZE) {
1040 errno = ENOMEM;
1041 return NULL;
1042 }
1043 sz += mopts.malloc_guard;
1044 psz = PAGEROUND(sz);
1045 p = map(g_pool, psz, zero_fill);
1046 if (p == MAP_FAILED) {
1047 errno = ENOMEM;
1048 return NULL;
1049 }
1050 if (insert(g_pool, p, sz, f)) {
1051 unmap(g_pool, p, psz);
1052 errno = ENOMEM;
1053 return NULL;
1054 }
1055 if (mopts.malloc_guard) {
1056 if (mprotect((char *)p + psz - mopts.malloc_guard,
1057 mopts.malloc_guard, PROT_NONE))
1058 wrterror("mprotect", NULL);
1059 malloc_guarded += mopts.malloc_guard;
1060 }
1061
1062 if (mopts.malloc_move &&
1063 sz - mopts.malloc_guard < MALLOC_PAGESIZE -
1064 MALLOC_LEEWAY) {
1065 /* fill whole allocation */
1066 if (mopts.malloc_junk)
1067 memset(p, SOME_JUNK, psz - mopts.malloc_guard);
1068 /* shift towards the end */
1069 p = ((char *)p) + ((MALLOC_PAGESIZE - MALLOC_LEEWAY -
1070 (sz - mopts.malloc_guard)) & ~(MALLOC_MINSIZE-1));
1071 /* fill zeros if needed and overwritten above */
1072 if (zero_fill && mopts.malloc_junk)
1073 memset(p, 0, sz - mopts.malloc_guard);
1074 } else {
1075 if (mopts.malloc_junk) {
1076 if (zero_fill)
1077 memset((char *)p + sz - mopts.malloc_guard,
1078 SOME_JUNK, psz - sz);
1079 else
1080 memset(p, SOME_JUNK,
1081 psz - mopts.malloc_guard);
1082 }
1083 }
1084
1085 } else {
1086 /* takes care of SOME_JUNK */
1087 p = malloc_bytes(g_pool, sz, f);
1088 if (zero_fill && p != NULL && sz > 0)
1089 memset(p, 0, sz);
1090 }
1091
1092 return p;
285} 1093}
286 1094
287/* 1095/*
288 * When a program attempts "storage compaction" as mentioned in the 1096 * Common function for handling recursion. Only
289 * old malloc man page, it realloc's an already freed block. Usually 1097 * print the error message once, to avoid making the problem
290 * this is the last block it freed; occasionally it might be farther 1098 * potentially worse.
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 */ 1099 */
298int realloc_srchlen = 4; /* 4 should be plenty, -1 =>'s whole list */ 1100static void
1101malloc_recurse(void)
1102{
1103 static int noprint;
1104
1105 if (noprint == 0) {
1106 noprint = 1;
1107 wrterror("recursive call", NULL);
1108 }
1109 malloc_active--;
1110 _MALLOC_UNLOCK();
1111 errno = EDEADLK;
1112}
1113
1114static int
1115malloc_init(void)
1116{
1117 if (omalloc_init(&g_pool)) {
1118 _MALLOC_UNLOCK();
1119 if (mopts.malloc_xmalloc)
1120 wrterror("out of memory", NULL);
1121 errno = ENOMEM;
1122 return -1;
1123 }
1124 return 0;
1125}
299 1126
300void * 1127void *
301realloc(cp, nbytes) 1128malloc(size_t size)
302 void *cp; 1129{
303 size_t nbytes; 1130 void *r;
304{ 1131 int saved_errno = errno;
305 register u_long onb; 1132
306 register long i; 1133 _MALLOC_LOCK();
307 union overhead *op; 1134 malloc_func = " in malloc():";
308 char *res; 1135 if (g_pool == NULL) {
309 int was_alloced = 0; 1136 if (malloc_init() != 0)
310 1137 return NULL;
311 if (cp == NULL) 1138 }
312 return (malloc(nbytes)); 1139 if (malloc_active++) {
313 op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); 1140 malloc_recurse();
314 if (op->ov_magic == MAGIC) { 1141 return NULL;
315 was_alloced++; 1142 }
316 i = op->ov_index; 1143 r = omalloc(size, mopts.malloc_zero, CALLER);
1144 malloc_active--;
1145 _MALLOC_UNLOCK();
1146 if (r == NULL && mopts.malloc_xmalloc) {
1147 wrterror("out of memory", NULL);
1148 errno = ENOMEM;
1149 }
1150 if (r != NULL)
1151 errno = saved_errno;
1152 return r;
1153}
1154
1155static void
1156ofree(void *p)
1157{
1158 struct region_info *r;
1159 size_t sz;
1160
1161 r = find(g_pool, p);
1162 if (r == NULL) {
1163 wrterror("bogus pointer (double free?)", p);
1164 return;
1165 }
1166 REALSIZE(sz, r);
1167 if (sz > MALLOC_MAXCHUNK) {
1168 if (sz - mopts.malloc_guard >= MALLOC_PAGESIZE -
1169 MALLOC_LEEWAY) {
1170 if (r->p != p) {
1171 wrterror("bogus pointer", p);
1172 return;
1173 }
1174 } else {
1175#if notyetbecause_of_realloc
1176 /* shifted towards the end */
1177 if (p != ((char *)r->p) + ((MALLOC_PAGESIZE -
1178 MALLOC_MINSIZE - sz - mopts.malloc_guard) &
1179 ~(MALLOC_MINSIZE-1))) {
1180 }
1181#endif
1182 p = r->p;
1183 }
1184 if (mopts.malloc_guard) {
1185 if (sz < mopts.malloc_guard)
1186 wrterror("guard size", NULL);
1187 if (!mopts.malloc_freeprot) {
1188 if (mprotect((char *)p + PAGEROUND(sz) -
1189 mopts.malloc_guard, mopts.malloc_guard,
1190 PROT_READ | PROT_WRITE))
1191 wrterror("mprotect", NULL);
1192 }
1193 malloc_guarded -= mopts.malloc_guard;
1194 }
1195 if (mopts.malloc_junk && !mopts.malloc_freeprot)
1196 memset(p, SOME_FREEJUNK,
1197 PAGEROUND(sz) - mopts.malloc_guard);
1198 unmap(g_pool, p, PAGEROUND(sz));
1199 delete(g_pool, r);
1200 } else {
1201 void *tmp;
1202 int i;
1203
1204 if (mopts.malloc_junk && sz > 0)
1205 memset(p, SOME_FREEJUNK, sz);
1206 if (!mopts.malloc_freeprot) {
1207 i = getrnibble();
1208 tmp = p;
1209 p = g_pool->delayed_chunks[i];
1210 g_pool->delayed_chunks[i] = tmp;
1211 }
1212 if (p != NULL) {
1213 r = find(g_pool, p);
1214 if (r == NULL) {
1215 wrterror("bogus pointer (double free?)", p);
1216 return;
1217 }
1218 free_bytes(g_pool, r, p);
1219 }
1220 }
1221}
1222
1223void
1224free(void *ptr)
1225{
1226 int saved_errno = errno;
1227
1228 /* This is legal. */
1229 if (ptr == NULL)
1230 return;
1231
1232 _MALLOC_LOCK();
1233 malloc_func = " in free():";
1234 if (g_pool == NULL) {
1235 _MALLOC_UNLOCK();
1236 wrterror("free() called before allocation", NULL);
1237 return;
1238 }
1239 if (malloc_active++) {
1240 malloc_recurse();
1241 return;
1242 }
1243 ofree(ptr);
1244 malloc_active--;
1245 _MALLOC_UNLOCK();
1246 errno = saved_errno;
1247}
1248
1249
1250static void *
1251orealloc(void *p, size_t newsz, void *f)
1252{
1253 struct region_info *r;
1254 size_t oldsz, goldsz, gnewsz;
1255 void *q;
1256
1257 if (p == NULL)
1258 return omalloc(newsz, 0, f);
1259
1260 r = find(g_pool, p);
1261 if (r == NULL) {
1262 wrterror("bogus pointer (double free?)", p);
1263 return NULL;
1264 }
1265 if (newsz >= SIZE_MAX - mopts.malloc_guard - MALLOC_PAGESIZE) {
1266 errno = ENOMEM;
1267 return NULL;
1268 }
1269
1270 REALSIZE(oldsz, r);
1271 goldsz = oldsz;
1272 if (oldsz > MALLOC_MAXCHUNK) {
1273 if (oldsz < mopts.malloc_guard)
1274 wrterror("guard size", NULL);
1275 oldsz -= mopts.malloc_guard;
1276 }
1277
1278 gnewsz = newsz;
1279 if (gnewsz > MALLOC_MAXCHUNK)
1280 gnewsz += mopts.malloc_guard;
1281
1282 if (newsz > MALLOC_MAXCHUNK && oldsz > MALLOC_MAXCHUNK && p == r->p &&
1283 !mopts.malloc_realloc) {
1284 size_t roldsz = PAGEROUND(goldsz);
1285 size_t rnewsz = PAGEROUND(gnewsz);
1286
1287 if (rnewsz > roldsz) {
1288 if (!mopts.malloc_guard) {
1289 void *hint = (char *)p + roldsz;
1290 size_t needed = rnewsz - roldsz;
1291
1292 STATS_INC(g_pool->cheap_realloc_tries);
1293 zapcacheregion(g_pool, hint, needed);
1294 q = MQUERY(hint, needed);
1295 if (q == hint)
1296 q = MMAPA(hint, needed);
1297 else
1298 q = MAP_FAILED;
1299 if (q == hint) {
1300 malloc_used += needed;
1301 if (mopts.malloc_junk)
1302 memset(q, SOME_JUNK, needed);
1303 r->size = newsz;
1304 STATS_SETF(r, f);
1305 STATS_INC(g_pool->cheap_reallocs);
1306 return p;
1307 } else if (q != MAP_FAILED) {
1308 if (munmap(q, needed))
1309 wrterror("munmap", q);
1310 }
1311 }
1312 } else if (rnewsz < roldsz) {
1313 if (mopts.malloc_guard) {
1314 if (mprotect((char *)p + roldsz -
1315 mopts.malloc_guard, mopts.malloc_guard,
1316 PROT_READ | PROT_WRITE))
1317 wrterror("mprotect", NULL);
1318 if (mprotect((char *)p + rnewsz -
1319 mopts.malloc_guard, mopts.malloc_guard,
1320 PROT_NONE))
1321 wrterror("mprotect", NULL);
1322 }
1323 unmap(g_pool, (char *)p + rnewsz, roldsz - rnewsz);
1324 r->size = gnewsz;
1325 STATS_SETF(r, f);
1326 return p;
1327 } else {
1328 if (newsz > oldsz && mopts.malloc_junk)
1329 memset((char *)p + newsz, SOME_JUNK,
1330 rnewsz - mopts.malloc_guard - newsz);
1331 r->size = gnewsz;
1332 STATS_SETF(r, f);
1333 return p;
1334 }
1335 }
1336 if (newsz <= oldsz && newsz > oldsz / 2 && !mopts.malloc_realloc) {
1337 if (mopts.malloc_junk && newsz > 0)
1338 memset((char *)p + newsz, SOME_JUNK, oldsz - newsz);
1339 STATS_SETF(r, f);
1340 return p;
1341 } else if (newsz != oldsz || mopts.malloc_realloc) {
1342 q = omalloc(newsz, 0, f);
1343 if (q == NULL)
1344 return NULL;
1345 if (newsz != 0 && oldsz != 0)
1346 memcpy(q, p, oldsz < newsz ? oldsz : newsz);
1347 ofree(p);
1348 return q;
317 } else { 1349 } else {
1350 STATS_SETF(r, f);
1351 return p;
1352 }
1353}
1354
1355void *
1356realloc(void *ptr, size_t size)
1357{
1358 void *r;
1359 int saved_errno = errno;
1360
1361 _MALLOC_LOCK();
1362 malloc_func = " in realloc():";
1363 if (g_pool == NULL) {
1364 if (malloc_init() != 0)
1365 return NULL;
1366 }
1367 if (malloc_active++) {
1368 malloc_recurse();
1369 return NULL;
1370 }
1371 r = orealloc(ptr, size, CALLER);
1372
1373 malloc_active--;
1374 _MALLOC_UNLOCK();
1375 if (r == NULL && mopts.malloc_xmalloc) {
1376 wrterror("out of memory", NULL);
1377 errno = ENOMEM;
1378 }
1379 if (r != NULL)
1380 errno = saved_errno;
1381 return r;
1382}
1383
1384
1385#define MUL_NO_OVERFLOW (1UL << (sizeof(size_t) * 4))
1386
1387void *
1388calloc(size_t nmemb, size_t size)
1389{
1390 void *r;
1391 int saved_errno = errno;
1392
1393 _MALLOC_LOCK();
1394 malloc_func = " in calloc():";
1395 if (g_pool == NULL) {
1396 if (malloc_init() != 0)
1397 return NULL;
1398 }
1399 if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
1400 nmemb > 0 && SIZE_MAX / nmemb < size) {
1401 _MALLOC_UNLOCK();
1402 if (mopts.malloc_xmalloc)
1403 wrterror("out of memory", NULL);
1404 errno = ENOMEM;
1405 return NULL;
1406 }
1407
1408 if (malloc_active++) {
1409 malloc_recurse();
1410 return NULL;
1411 }
1412
1413 size *= nmemb;
1414 r = omalloc(size, 1, CALLER);
1415
1416 malloc_active--;
1417 _MALLOC_UNLOCK();
1418 if (r == NULL && mopts.malloc_xmalloc) {
1419 wrterror("out of memory", NULL);
1420 errno = ENOMEM;
1421 }
1422 if (r != NULL)
1423 errno = saved_errno;
1424 return r;
1425}
1426
1427static void *
1428mapalign(struct dir_info *d, size_t alignment, size_t sz, int zero_fill)
1429{
1430 void *p, *q;
1431
1432 if (alignment < MALLOC_PAGESIZE || ((alignment - 1) & alignment) != 0) {
1433 wrterror("mapalign bad alignment", NULL);
1434 return MAP_FAILED;
1435 }
1436 if (sz != PAGEROUND(sz)) {
1437 wrterror("mapalign round", NULL);
1438 return MAP_FAILED;
1439 }
1440
1441 /* Allocate sz + alignment bytes of memory, which must include a
1442 * subrange of size bytes that is properly aligned. Unmap the
1443 * other bytes, and then return that subrange.
1444 */
1445
1446 /* We need sz + alignment to fit into a size_t. */
1447 if (alignment > SIZE_MAX - sz)
1448 return MAP_FAILED;
1449
1450 p = map(d, sz + alignment, zero_fill);
1451 if (p == MAP_FAILED)
1452 return MAP_FAILED;
1453 q = (void *)(((uintptr_t)p + alignment - 1) & ~(alignment - 1));
1454 if (q != p) {
1455 if (munmap(p, q - p))
1456 wrterror("munmap", p);
1457 }
1458 if (munmap(q + sz, alignment - (q - p)))
1459 wrterror("munmap", q + sz);
1460 malloc_used -= alignment;
1461
1462 return q;
1463}
1464
1465static void *
1466omemalign(size_t alignment, size_t sz, int zero_fill, void *f)
1467{
1468 size_t psz;
1469 void *p;
1470
1471 if (alignment <= MALLOC_PAGESIZE) {
318 /* 1472 /*
319 * Already free, doing "compaction". 1473 * max(size, alignment) is enough to assure the requested alignment,
320 * 1474 * since the allocator always allocates power-of-two blocks.
321 * Search for the old block of memory on the
322 * free list. First, check the most common
323 * case (last element free'd), then (this failing)
324 * the last ``realloc_srchlen'' items free'd.
325 * If all lookups fail, then assume the size of
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 */ 1475 */
332 if ((i = findbucket(op, 1)) < 0 && 1476 if (sz < alignment)
333 (i = findbucket(op, realloc_srchlen)) < 0) 1477 sz = alignment;
334 i = NBUCKETS; 1478 return omalloc(sz, zero_fill, f);
335 } 1479 }
336 onb = 1 << (i + 3); 1480
337 if (onb < pagesz) 1481 if (sz >= SIZE_MAX - mopts.malloc_guard - MALLOC_PAGESIZE) {
338 onb -= sizeof (*op) + RSLOP; 1482 errno = ENOMEM;
339 else 1483 return NULL;
340 onb += pagesz - sizeof (*op) - RSLOP; 1484 }
341 /* avoid the copy if same size block */ 1485
342 if (was_alloced) { 1486 sz += mopts.malloc_guard;
343 if (i) { 1487 psz = PAGEROUND(sz);
344 i = 1 << (i + 2); 1488
345 if (i < pagesz) 1489 p = mapalign(g_pool, alignment, psz, zero_fill);
346 i -= sizeof (*op) + RSLOP; 1490 if (p == NULL) {
347 else 1491 errno = ENOMEM;
348 i += pagesz - sizeof (*op) - RSLOP; 1492 return NULL;
1493 }
1494
1495 if (insert(g_pool, p, sz, f)) {
1496 unmap(g_pool, p, psz);
1497 errno = ENOMEM;
1498 return NULL;
1499 }
1500
1501 if (mopts.malloc_guard) {
1502 if (mprotect((char *)p + psz - mopts.malloc_guard,
1503 mopts.malloc_guard, PROT_NONE))
1504 wrterror("mprotect", NULL);
1505 malloc_guarded += mopts.malloc_guard;
1506 }
1507
1508 if (mopts.malloc_junk) {
1509 if (zero_fill)
1510 memset((char *)p + sz - mopts.malloc_guard,
1511 SOME_JUNK, psz - sz);
1512 else
1513 memset(p, SOME_JUNK, psz - mopts.malloc_guard);
1514 }
1515
1516 return p;
1517}
1518
1519int
1520posix_memalign(void **memptr, size_t alignment, size_t size)
1521{
1522 int res, saved_errno = errno;
1523 void *r;
1524
1525 /* Make sure that alignment is a large enough power of 2. */
1526 if (((alignment - 1) & alignment) != 0 || alignment < sizeof(void *))
1527 return EINVAL;
1528
1529 _MALLOC_LOCK();
1530 malloc_func = " in posix_memalign():";
1531 if (g_pool == NULL) {
1532 if (malloc_init() != 0)
1533 goto err;
1534 }
1535 if (malloc_active++) {
1536 malloc_recurse();
1537 goto err;
1538 }
1539 r = omemalign(alignment, size, mopts.malloc_zero, CALLER);
1540 malloc_active--;
1541 _MALLOC_UNLOCK();
1542 if (r == NULL) {
1543 if (mopts.malloc_xmalloc) {
1544 wrterror("out of memory", NULL);
1545 errno = ENOMEM;
349 } 1546 }
350 if (nbytes <= onb && nbytes > i) { 1547 goto err;
351#ifdef RCHECK
352 op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1);
353 *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC;
354#endif
355 return(cp);
356 } else
357 free(cp);
358 } 1548 }
359 if ((res = malloc(nbytes)) == NULL) 1549 errno = saved_errno;
360 return (NULL); 1550 *memptr = r;
361 if (cp != res) /* common optimization if "compacting" */ 1551 return 0;
362 bcopy(cp, res, (nbytes < onb) ? nbytes : onb); 1552
363 return (res); 1553err:
1554 res = errno;
1555 errno = saved_errno;
1556 return res;
364} 1557}
365 1558
366/* 1559#ifdef MALLOC_STATS
367 * Search ``srchlen'' elements of each free list for a block whose 1560
368 * header starts at ``freep''. If srchlen is -1 search the whole list. 1561struct malloc_leak {
369 * Return bucket number, or -1 if not found. 1562 void (*f)();
370 */ 1563 size_t total_size;
371static 1564 int count;
372findbucket(freep, srchlen) 1565};
373 union overhead *freep; 1566
374 int srchlen; 1567struct leaknode {
1568 RB_ENTRY(leaknode) entry;
1569 struct malloc_leak d;
1570};
1571
1572static int
1573leakcmp(struct leaknode *e1, struct leaknode *e2)
375{ 1574{
376 register union overhead *p; 1575 return e1->d.f < e2->d.f ? -1 : e1->d.f > e2->d.f;
377 register int i, j; 1576}
378 1577
379 for (i = 0; i < NBUCKETS; i++) { 1578static RB_HEAD(leaktree, leaknode) leakhead;
380 j = 0; 1579RB_GENERATE_STATIC(leaktree, leaknode, entry, leakcmp)
381 for (p = nextf[i]; p && j != srchlen; p = p->ov_next) { 1580
382 if (p == freep) 1581static void
383 return (i); 1582putleakinfo(void *f, size_t sz, int cnt)
384 j++; 1583{
1584 struct leaknode key, *p;
1585 static struct leaknode *page;
1586 static int used;
1587
1588 if (cnt == 0)
1589 return;
1590
1591 key.d.f = f;
1592 p = RB_FIND(leaktree, &leakhead, &key);
1593 if (p == NULL) {
1594 if (page == NULL ||
1595 used >= MALLOC_PAGESIZE / sizeof(struct leaknode)) {
1596 page = MMAP(MALLOC_PAGESIZE);
1597 if (page == MAP_FAILED)
1598 return;
1599 used = 0;
385 } 1600 }
1601 p = &page[used++];
1602 p->d.f = f;
1603 p->d.total_size = sz * cnt;
1604 p->d.count = cnt;
1605 RB_INSERT(leaktree, &leakhead, p);
1606 } else {
1607 p->d.total_size += sz * cnt;
1608 p->d.count += cnt;
386 } 1609 }
387 return (-1);
388} 1610}
389 1611
390#ifdef MSTATS 1612static struct malloc_leak *malloc_leaks;
391/* 1613
392 * mstats - print out statistics about malloc 1614static void
393 * 1615dump_leaks(int fd)
394 * Prints two lines of numbers, one showing the length of the free list 1616{
395 * for each size category, the second showing the number of mallocs - 1617 struct leaknode *p;
396 * frees for each size category. 1618 char buf[64];
397 */ 1619 int i = 0;
398mstats(s) 1620
399 char *s; 1621 snprintf(buf, sizeof(buf), "Leak report\n");
400{ 1622 write(fd, buf, strlen(buf));
401 register int i, j; 1623 snprintf(buf, sizeof(buf), " f sum # avg\n");
402 register union overhead *p; 1624 write(fd, buf, strlen(buf));
403 int totfree = 0, 1625 /* XXX only one page of summary */
404 totused = 0; 1626 if (malloc_leaks == NULL)
405 1627 malloc_leaks = MMAP(MALLOC_PAGESIZE);
406 fprintf(stderr, "Memory allocation statistics %s\nfree:\t", s); 1628 if (malloc_leaks != MAP_FAILED)
407 for (i = 0; i < NBUCKETS; i++) { 1629 memset(malloc_leaks, 0, MALLOC_PAGESIZE);
408 for (j = 0, p = nextf[i]; p; p = p->ov_next, j++) 1630 RB_FOREACH(p, leaktree, &leakhead) {
409 ; 1631 snprintf(buf, sizeof(buf), "%12p %7zu %6u %6zu\n", p->d.f,
410 fprintf(stderr, " %d", j); 1632 p->d.total_size, p->d.count, p->d.total_size / p->d.count);
411 totfree += j * (1 << (i + 3)); 1633 write(fd, buf, strlen(buf));
412 } 1634 if (malloc_leaks == MAP_FAILED ||
413 fprintf(stderr, "\nused:\t"); 1635 i >= MALLOC_PAGESIZE / sizeof(struct malloc_leak))
414 for (i = 0; i < NBUCKETS; i++) { 1636 continue;
415 fprintf(stderr, " %d", nmalloc[i]); 1637 malloc_leaks[i].f = p->d.f;
416 totused += nmalloc[i] * (1 << (i + 3)); 1638 malloc_leaks[i].total_size = p->d.total_size;
417 } 1639 malloc_leaks[i].count = p->d.count;
418 fprintf(stderr, "\n\tTotal in use: %d, total free: %d\n", 1640 i++;
419 totused, totfree); 1641 }
420} 1642}
421#endif 1643
1644static void
1645dump_chunk(int fd, struct chunk_info *p, void *f, int fromfreelist)
1646{
1647 char buf[64];
1648
1649 while (p != NULL) {
1650 snprintf(buf, sizeof(buf), "chunk %12p %12p %4d %d/%d\n",
1651 p->page, ((p->bits[0] & 1) ? NULL : f),
1652 p->size, p->free, p->total);
1653 write(fd, buf, strlen(buf));
1654 if (!fromfreelist) {
1655 if (p->bits[0] & 1)
1656 putleakinfo(NULL, p->size, p->total - p->free);
1657 else {
1658 putleakinfo(f, p->size, 1);
1659 putleakinfo(NULL, p->size,
1660 p->total - p->free - 1);
1661 }
1662 break;
1663 }
1664 p = LIST_NEXT(p, entries);
1665 if (p != NULL) {
1666 snprintf(buf, sizeof(buf), " ");
1667 write(fd, buf, strlen(buf));
1668 }
1669 }
1670}
1671
1672static void
1673dump_free_chunk_info(int fd, struct dir_info *d)
1674{
1675 char buf[64];
1676 int i, count;
1677
1678 snprintf(buf, sizeof(buf), "Free chunk structs:\n");
1679 write(fd, buf, strlen(buf));
1680 for (i = 0; i <= MALLOC_MAXSHIFT; i++) {
1681 struct chunk_info *p;
1682
1683 count = 0;
1684 LIST_FOREACH(p, &d->chunk_info_list[i], entries)
1685 count++;
1686 p = LIST_FIRST(&d->chunk_dir[i]);
1687 if (p == NULL && count == 0)
1688 continue;
1689 snprintf(buf, sizeof(buf), "%2d) %3d ", i, count);
1690 write(fd, buf, strlen(buf));
1691 if (p != NULL)
1692 dump_chunk(fd, p, NULL, 1);
1693 else
1694 write(fd, "\n", 1);
1695 }
1696
1697}
1698
1699static void
1700dump_free_page_info(int fd, struct dir_info *d)
1701{
1702 char buf[64];
1703 int i;
1704
1705 snprintf(buf, sizeof(buf), "Free pages cached: %zu\n",
1706 d->free_regions_size);
1707 write(fd, buf, strlen(buf));
1708 for (i = 0; i < mopts.malloc_cache; i++) {
1709 if (d->free_regions[i].p != NULL) {
1710 snprintf(buf, sizeof(buf), "%2d) ", i);
1711 write(fd, buf, strlen(buf));
1712 snprintf(buf, sizeof(buf), "free at %p: %zu\n",
1713 d->free_regions[i].p, d->free_regions[i].size);
1714 write(fd, buf, strlen(buf));
1715 }
1716 }
1717}
1718
1719static void
1720malloc_dump1(int fd, struct dir_info *d)
1721{
1722 char buf[64];
1723 size_t i, realsize;
1724
1725 snprintf(buf, sizeof(buf), "Malloc dir of %s at %p\n", __progname, d);
1726 write(fd, buf, strlen(buf));
1727 if (d == NULL)
1728 return;
1729 snprintf(buf, sizeof(buf), "Region slots free %zu/%zu\n",
1730 d->regions_free, d->regions_total);
1731 write(fd, buf, strlen(buf));
1732 snprintf(buf, sizeof(buf), "Finds %zu/%zu\n", d->finds,
1733 d->find_collisions);
1734 write(fd, buf, strlen(buf));
1735 snprintf(buf, sizeof(buf), "Inserts %zu/%zu\n", d->inserts,
1736 d->insert_collisions);
1737 write(fd, buf, strlen(buf));
1738 snprintf(buf, sizeof(buf), "Deletes %zu/%zu\n", d->deletes,
1739 d->delete_moves);
1740 write(fd, buf, strlen(buf));
1741 snprintf(buf, sizeof(buf), "Cheap reallocs %zu/%zu\n",
1742 d->cheap_reallocs, d->cheap_realloc_tries);
1743 write(fd, buf, strlen(buf));
1744 dump_free_chunk_info(fd, d);
1745 dump_free_page_info(fd, d);
1746 snprintf(buf, sizeof(buf),
1747 "slot) hash d type page f size [free/n]\n");
1748 write(fd, buf, strlen(buf));
1749 for (i = 0; i < d->regions_total; i++) {
1750 if (d->r[i].p != NULL) {
1751 size_t h = hash(d->r[i].p) &
1752 (d->regions_total - 1);
1753 snprintf(buf, sizeof(buf), "%4zx) #%4zx %zd ",
1754 i, h, h - i);
1755 write(fd, buf, strlen(buf));
1756 REALSIZE(realsize, &d->r[i]);
1757 if (realsize > MALLOC_MAXCHUNK) {
1758 putleakinfo(d->r[i].f, realsize, 1);
1759 snprintf(buf, sizeof(buf),
1760 "pages %12p %12p %zu\n", d->r[i].p,
1761 d->r[i].f, realsize);
1762 write(fd, buf, strlen(buf));
1763 } else
1764 dump_chunk(fd,
1765 (struct chunk_info *)d->r[i].size,
1766 d->r[i].f, 0);
1767 }
1768 }
1769 snprintf(buf, sizeof(buf), "In use %zu\n", malloc_used);
1770 write(fd, buf, strlen(buf));
1771 snprintf(buf, sizeof(buf), "Guarded %zu\n", malloc_guarded);
1772 write(fd, buf, strlen(buf));
1773 dump_leaks(fd);
1774 write(fd, "\n", 1);
1775}
1776
1777void
1778malloc_dump(int fd)
1779{
1780 int i;
1781 void *p;
1782 struct region_info *r;
1783 int saved_errno = errno;
1784
1785 for (i = 0; i <= MALLOC_DELAYED_CHUNKS; i++) {
1786 p = g_pool->delayed_chunks[i];
1787 if (p == NULL)
1788 continue;
1789 r = find(g_pool, p);
1790 if (r == NULL)
1791 wrterror("bogus pointer in malloc_dump", p);
1792 free_bytes(g_pool, r, p);
1793 g_pool->delayed_chunks[i] = NULL;
1794 }
1795 /* XXX leak when run multiple times */
1796 RB_INIT(&leakhead);
1797 malloc_dump1(fd, g_pool);
1798 errno = saved_errno;
1799}
1800
1801static void
1802malloc_exit(void)
1803{
1804 static const char q[] = "malloc() warning: Couldn't dump stats\n";
1805 int save_errno = errno, fd;
1806
1807 fd = open("malloc.out", O_RDWR|O_APPEND);
1808 if (fd != -1) {
1809 malloc_dump(fd);
1810 close(fd);
1811 } else
1812 write(STDERR_FILENO, q, sizeof(q) - 1);
1813 errno = save_errno;
1814}
1815
1816#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..05ec1b9d14
--- /dev/null
+++ b/src/lib/libc/stdlib/posix_memalign.3
@@ -0,0 +1,92 @@
1.\" $OpenBSD: posix_memalign.3,v 1.3 2012/06/18 17:03:52 matthew 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: June 18 2012 $
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 .
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..50fe67d109 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.11 2012/06/02 00:14:16 guenther 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: June 2 2012 $
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,27 @@ 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
97.St -p1003.1-2008 .
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..340e6461bd 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.12 2012/06/02 00:14:16 guenther Exp $
13.\" 13.\"
14.Dd October 8, 1993 14.Dd $Mdocdate: June 2 2012 $
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,24 @@ 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 STANDARDS
165The
166.Fn drand48 ,
167.Fn erand48 ,
168.Fn jrand48 ,
169.Fn lcong48 ,
170.Fn lrand48 ,
171.Fn mrand48 ,
172.Fn nrand48 ,
173.Fn seed48 ,
174and
175.Fn srand48
176functions conform to
177.St -p1003.1-2008 .
178.Sh AUTHORS
179Martin 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..84756bb3e3 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.20 2012/06/01 01:01:57 guenther 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: June 1 2012 $
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 "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..9c5b9d0f3f 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.17 2012/06/01 01:01:57 guenther 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,29 @@ 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; 199 /* A seed of 0 would result in state[] always being zero. */
202 state[0] = x; 200 state[0] = x ? x : 1;
203 for (i = 1; i < rand_deg; i++) 201 for (i = 1; i < rand_deg; i++) {
204 state[i] = 1103515245 * state[i - 1] + 12345; 202 /*
203 * Implement the following, without overflowing 31 bits:
204 *
205 * state[i] = (16807 * state[i - 1]) % 2147483647;
206 *
207 * 2^31-1 (prime) = 2147483647 = 127773*16807+2836
208 */
209 val = div(state[i-1], 127773);
210 test = 16807 * val.rem - 2836 * val.quot;
211 state[i] = test + (test < 0 ? 2147483647 : 0);
212 }
205 fptr = &state[rand_sep]; 213 fptr = &state[rand_sep];
206 rptr = &state[0]; 214 rptr = &state[0];
207 for (i = 0; i < 10 * rand_deg; i++) 215 for (i = 0; i < 10 * rand_deg; i++)
@@ -210,6 +218,38 @@ srandom(x)
210} 218}
211 219
212/* 220/*
221 * srandomdev:
222 *
223 * Many programs choose the seed value in a totally predictable manner.
224 * This often causes problems. We seed the generator using random
225 * data from the kernel.
226 * Note that this particular seeding procedure can generate states
227 * which are impossible to reproduce by calling srandom() with any
228 * value, since the succeeding terms in the state buffer are no longer
229 * derived from the LC algorithm applied to a fixed seed.
230 */
231void
232srandomdev(void)
233{
234 int mib[2];
235 size_t len;
236
237 if (rand_type == TYPE_0)
238 len = sizeof(state[0]);
239 else
240 len = rand_deg * sizeof(state[0]);
241
242 mib[0] = CTL_KERN;
243 mib[1] = KERN_ARND;
244 sysctl(mib, 2, state, &len, NULL, 0);
245
246 if (rand_type != TYPE_0) {
247 fptr = &state[rand_sep];
248 rptr = &state[0];
249 }
250}
251
252/*
213 * initstate: 253 * initstate:
214 * 254 *
215 * Initialize the state information in the given array of n bytes for future 255 * Initialize the state information in the given array of n bytes for future
@@ -229,22 +269,16 @@ srandom(x)
229 * Returns a pointer to the old state. 269 * Returns a pointer to the old state.
230 */ 270 */
231char * 271char *
232initstate(seed, arg_state, n) 272initstate(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{ 273{
237 register char *ostate = (char *)(&state[-1]); 274 char *ostate = (char *)(&state[-1]);
238 275
239 if (rand_type == TYPE_0) 276 if (rand_type == TYPE_0)
240 state[-1] = rand_type; 277 state[-1] = rand_type;
241 else 278 else
242 state[-1] = MAX_TYPES * (rptr - state) + rand_type; 279 state[-1] = MAX_TYPES * (rptr - state) + rand_type;
243 if (n < BREAK_0) { 280 if (n < BREAK_0)
244 (void)fprintf(stderr, 281 return(NULL);
245 "random: not enough state (%d bytes); ignored.\n", n);
246 return(0);
247 }
248 if (n < BREAK_1) { 282 if (n < BREAK_1) {
249 rand_type = TYPE_0; 283 rand_type = TYPE_0;
250 rand_deg = DEG_0; 284 rand_deg = DEG_0;
@@ -266,7 +300,7 @@ initstate(seed, arg_state, n)
266 rand_deg = DEG_4; 300 rand_deg = DEG_4;
267 rand_sep = SEP_4; 301 rand_sep = SEP_4;
268 } 302 }
269 state = &(((long *)arg_state)[1]); /* first location */ 303 state = &(((int32_t *)arg_state)[1]); /* first location */
270 end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */ 304 end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */
271 srandom(seed); 305 srandom(seed);
272 if (rand_type == TYPE_0) 306 if (rand_type == TYPE_0)
@@ -292,12 +326,11 @@ initstate(seed, arg_state, n)
292 * Returns a pointer to the old state information. 326 * Returns a pointer to the old state information.
293 */ 327 */
294char * 328char *
295setstate(arg_state) 329setstate(char *arg_state)
296 char *arg_state;
297{ 330{
298 register long *new_state = (long *)arg_state; 331 int32_t *new_state = (int32_t *)arg_state;
299 register int type = new_state[0] % MAX_TYPES; 332 int32_t type = new_state[0] % MAX_TYPES;
300 register int rear = new_state[0] / MAX_TYPES; 333 int32_t rear = new_state[0] / MAX_TYPES;
301 char *ostate = (char *)(&state[-1]); 334 char *ostate = (char *)(&state[-1]);
302 335
303 if (rand_type == TYPE_0) 336 if (rand_type == TYPE_0)
@@ -315,8 +348,7 @@ setstate(arg_state)
315 rand_sep = seps[type]; 348 rand_sep = seps[type];
316 break; 349 break;
317 default: 350 default:
318 (void)fprintf(stderr, 351 return(NULL);
319 "random: state info corrupted; not changed.\n");
320 } 352 }
321 state = &new_state[1]; 353 state = &new_state[1];
322 if (rand_type != TYPE_0) { 354 if (rand_type != TYPE_0) {
@@ -345,9 +377,9 @@ setstate(arg_state)
345 * Returns a 31-bit random number. 377 * Returns a 31-bit random number.
346 */ 378 */
347long 379long
348random() 380random(void)
349{ 381{
350 long i; 382 int32_t i;
351 383
352 if (rand_type == TYPE_0) 384 if (rand_type == TYPE_0)
353 i = state[0] = (state[0] * 1103515245 + 12345) & 0x7fffffff; 385 i = state[0] = (state[0] * 1103515245 + 12345) & 0x7fffffff;
@@ -360,5 +392,5 @@ random()
360 } else if (++rptr >= end_ptr) 392 } else if (++rptr >= end_ptr)
361 rptr = state; 393 rptr = state;
362 } 394 }
363 return(i); 395 return((long)i);
364} 396}
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..534f48d4b4 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.15 2012/09/13 15:39:05 deraadt 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(symlink));
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..9060fdba88 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.14 2012/09/23 16:08:04 jeremy 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,122 @@
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 if (!name || !*name) {
98 errno = EINVAL;
99 return (-1);
100 }
101 for (np = name; *np && *np != '='; ++np)
102 ;
103 if (*np) {
104 errno = EINVAL;
105 return (-1); /* has `=' in name */
106 }
58 107
59 if (*value == '=') /* no `=' in value */
60 ++value;
61 l_value = strlen(value); 108 l_value = strlen(value);
62 if ((C = __findenv(name, &offset))) { /* find if already exists */ 109 if ((C = __findenv(name, (int)(np - name), &offset)) != NULL) {
110 int tmpoff = offset + 1;
63 if (!rewrite) 111 if (!rewrite)
64 return (0); 112 return (0);
113#if 0 /* XXX - existing entry may not be writable */
65 if (strlen(C) >= l_value) { /* old larger; copy over */ 114 if (strlen(C) >= l_value) { /* old larger; copy over */
66 while (*C++ = *value++); 115 while ((*C++ = *value++))
116 ;
67 return (0); 117 return (0);
68 } 118 }
119#endif
120 /* could be set multiple times */
121 while (__findenv(name, (int)(np - name), &tmpoff)) {
122 for (P = &environ[tmpoff];; ++P)
123 if (!(*P = *(P + 1)))
124 break;
125 }
69 } else { /* create new slot */ 126 } else { /* create new slot */
70 register int cnt; 127 size_t cnt;
71 register char **P;
72 128
73 for (P = environ, cnt = 0; *P; ++P, ++cnt); 129 for (P = environ; *P != NULL; P++)
74 if (alloced) { /* just increase size */ 130 ;
75 environ = (char **)realloc((char *)environ, 131 cnt = P - environ;
76 (size_t)(sizeof(char *) * (cnt + 2))); 132 P = (char **)realloc(lastenv, sizeof(char *) * (cnt + 2));
77 if (!environ) 133 if (!P)
78 return (-1); 134 return (-1);
79 } 135 if (lastenv != environ)
80 else { /* get new space */ 136 memcpy(P, environ, cnt * sizeof(char *));
81 alloced = 1; /* copy old entries into it */ 137 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; 138 offset = cnt;
139 environ[cnt + 1] = NULL;
91 } 140 }
92 for (C = (char *)name; *C && *C != '='; ++C); /* no `=' in name */
93 if (!(environ[offset] = /* name + `=' + value */ 141 if (!(environ[offset] = /* name + `=' + value */
94 malloc((size_t)((int)(C - name) + l_value + 2)))) 142 malloc((size_t)((int)(np - name) + l_value + 2))))
95 return (-1); 143 return (-1);
96 for (C = environ[offset]; (*C = *name++) && *C != '='; ++C) 144 for (C = environ[offset]; (*C = *name++) && *C != '='; ++C)
97 ; 145 ;
98 for (*C++ = '='; *C++ = *value++; ) 146 for (*C++ = '='; (*C++ = *value++); )
99 ; 147 ;
100 return (0); 148 return (0);
101} 149}
@@ -104,17 +152,29 @@ setenv(name, value, rewrite)
104 * unsetenv(name) -- 152 * unsetenv(name) --
105 * Delete environmental variable "name". 153 * Delete environmental variable "name".
106 */ 154 */
107void 155int
108unsetenv(name) 156unsetenv(const char *name)
109 const char *name;
110{ 157{
111 extern char **environ; 158 char **P;
112 register char **P; 159 const char *np;
113 int offset; 160 int offset = 0;
114 char *__findenv();
115 161
116 while (__findenv(name, &offset)) /* if set multiple times */ 162 if (!name || !*name) {
163 errno = EINVAL;
164 return (-1);
165 }
166 for (np = name; *np && *np != '='; ++np)
167 ;
168 if (*np) {
169 errno = EINVAL;
170 return (-1); /* has `=' in name */
171 }
172
173 /* could be set multiple times */
174 while (__findenv(name, (int)(np - name), &offset)) {
117 for (P = &environ[offset];; ++P) 175 for (P = &environ[offset];; ++P)
118 if (!(*P = *(P + 1))) 176 if (!(*P = *(P + 1)))
119 break; 177 break;
178 }
179 return (0);
120} 180}
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..0066cc02f3 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,99 @@
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.16 2012/09/16 17:54:03 jmc 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 16 2012 $
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 59.Fa nptr
60to
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
56.Fa nptr 73.Fa nptr
57to 74to
58.Em double 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.
89.Pp
90Alternatively, if the portion of the string following the optional
91plus or minus sign begins with
92.Dq INF
93or
94.Dq NAN ,
95ignoring case, it is interpreted as an infinity or a quiet \*(Na,
96respectively.
97The syntax
98.Dq NAN Ns Pq Ar s ,
99where
100.Ar s
101is an alphanumeric string, produces the same value as the call
102.Fo nan
103.Qq Ar s Ns
104.Fc
105(respectively,
106.Fo nanf
107.Qq Ar s Ns
108.Fc
109and
110.Fo nanl
111.Qq Ar s Ns
112.Fc . )
66.Pp 113.Pp
67Leading white-space characters in the string (as defined by the 114In any of the above cases, leading whitespace characters in the
115string (as defined by the
68.Xr isspace 3 116.Xr isspace 3
69function) are skipped. 117function) are skipped.
70.Sh RETURN VALUES 118.Sh RETURN VALUES
71The 119The
72.Fn strtod 120.Fn strtod ,
73function returns the converted value, if any. 121.Fn strtof
122and
123.Fn strtold
124functions return the converted value, if any.
74.Pp 125.Pp
75If 126If
76.Fa endptr 127.Fa endptr
@@ -88,18 +139,18 @@ is stored in the location referenced by
88If the correct value would cause overflow, plus or minus 139If the correct value would cause overflow, plus or minus
89.Dv HUGE_VAL 140.Dv HUGE_VAL
90is returned (according to the sign of the value), and 141is returned (according to the sign of the value), and
91.Dv ERANGE 142.Er ERANGE
92is stored in 143is stored in
93.Va errno . 144.Va errno .
94If the correct value would cause underflow, zero is 145If the correct value would cause underflow, zero is returned and
95returned and 146.Er ERANGE
96.Dv ERANGE 147is stored in
97is stored in
98.Va errno . 148.Va errno .
99.Sh ERRORS 149.Sh ERRORS
100.Bl -tag -width Er 150.Bl -tag -width Er
101.It Bq Er ERANGE 151.It Bq Er ERANGE
102Overflow or underflow occurred. 152Overflow or underflow occurred.
153.El
103.Sh SEE ALSO 154.Sh SEE ALSO
104.Xr atof 3 , 155.Xr atof 3 ,
105.Xr atoi 3 , 156.Xr atoi 3 ,
@@ -109,6 +160,11 @@ Overflow or underflow occurred.
109.Sh STANDARDS 160.Sh STANDARDS
110The 161The
111.Fn strtod 162.Fn strtod
112function 163function conforms to
113conforms to 164.St -ansiC-89 .
114.St -ansiC . 165The
166.Fn strtof
167and
168.Fn strtold
169functions conform to
170.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..829c4edf72
--- /dev/null
+++ b/src/lib/libc/stdlib/tsearch.3
@@ -0,0 +1,130 @@
1.\" $OpenBSD: tsearch.3,v 1.18 2012/07/08 10:25:55 guenther 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: July 8 2012 $
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.
71If the node to be deleted is the root of the binary search tree,
72.Fa rootp
73will be adjusted and an unspecified non-null pointer will be returned.
74It takes the same arguments as
75.Fn tfind
76and
77.Fn tsearch .
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 tdelete
100returns a pointer to the parent of the deleted node or an unspecified
101non-null pointer if the root node is deleted.
102.Pp
103.Fn tfind ,
104.Fn tsearch ,
105and
106.Fn tdelete
107return
108.Dv NULL
109if
110.Fa rootp
111is
112.Dv NULL
113or the datum cannot be found.
114.Pp
115The
116.Fn twalk
117function returns no value.
118.Sh SEE ALSO
119.Xr bsearch 3 ,
120.Xr lsearch 3
121.Sh STANDARDS
122These functions conform to
123.St -p1003.1-2008 .
124.Sh CAVEATS
125The value returned when deleting the root node was unspecified before
126the
127.St -p1003.1-2008
128standard, so users of the
129.Fn tdelete
130function should be wary of relying 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..2f5e369f6a
--- /dev/null
+++ b/src/lib/libc/stdlib/tsearch.c
@@ -0,0 +1,119 @@
1/* $OpenBSD: tsearch.c,v 1.7 2012/02/06 20:29:54 guenther 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 = (node *)1;
60 node *q;
61 node *r;
62 int cmp;
63
64 if (rootp == (struct node_t **)0 || *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 free((struct node_t *) *rootp); /* D4: Free node */
90 *rootp = q; /* link parent to new node */
91 return(p);
92}
93
94/* Walk the nodes of a tree */
95static void
96trecurse(node *root, void (*action)(const void *, VISIT, int), int level)
97{
98 if (root->left == (struct node_t *)0 && root->right == (struct node_t *)0)
99 (*action)(root, leaf, level);
100 else {
101 (*action)(root, preorder, level);
102 if (root->left != (struct node_t *)0)
103 trecurse(root->left, action, level + 1);
104 (*action)(root, postorder, level);
105 if (root->right != (struct node_t *)0)
106 trecurse(root->right, action, level + 1);
107 (*action)(root, endorder, level);
108 }
109}
110
111/* Walk the nodes of a tree */
112void
113twalk(const void *vroot, void (*action)(const void *, VISIT, int))
114{
115 node *root = (node *)vroot;
116
117 if (root != (node *)0 && action != (void (*)(const void *, VISIT, int))0)
118 trecurse(root, action, 0);
119}