summaryrefslogtreecommitdiffstats
path: root/lib/libc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/db/man/dbm.32
-rw-r--r--lib/libc/gen/sysctl.38
-rw-r--r--lib/libc/locale/mbstowcs.c4
-rw-r--r--lib/libc/locale/wcsftime.c11
-rw-r--r--lib/libc/locale/wcstombs.c4
-rw-r--r--lib/libc/net/getaddrinfo.357
-rw-r--r--lib/libc/sparc64/sys/__sparc_utrap.c2
-rw-r--r--lib/libc/stdio/ferror.311
-rw-r--r--lib/libc/stdio/fputws.c4
-rw-r--r--lib/libc/stdio/printf.33
-rw-r--r--lib/libc/stdio/printfcommon.h301
-rw-r--r--lib/libc/stdio/vfprintf.c477
-rw-r--r--lib/libc/stdio/vfscanf.c46
-rw-r--r--lib/libc/stdio/vfwprintf.c536
-rw-r--r--lib/libc/stdio/vfwscanf.c26
-rw-r--r--lib/libc/stdio/vswscanf.c4
-rw-r--r--lib/libc/stdio/wsetup.c1
-rw-r--r--lib/libc/string/Makefile.inc53
-rw-r--r--lib/libc/string/ffs.32
-rw-r--r--lib/libc/string/memccpy.c6
-rw-r--r--lib/libc/string/memchr.c5
-rw-r--r--lib/libc/string/memcmp.c4
-rw-r--r--lib/libc/string/memmem.c4
-rw-r--r--lib/libc/string/strcasecmp.c7
-rw-r--r--lib/libc/string/strcasestr.c3
-rw-r--r--lib/libc/string/strcmp.c5
-rw-r--r--lib/libc/string/strcoll.c3
-rw-r--r--lib/libc/string/strdup.c3
-rw-r--r--lib/libc/string/strlcat.c41
-rw-r--r--lib/libc/string/strlcpy.334
-rw-r--r--lib/libc/string/strlen.c93
-rw-r--r--lib/libc/string/strmode.c4
-rw-r--r--lib/libc/string/strncmp.c6
-rw-r--r--lib/libc/string/strncpy.c4
-rw-r--r--lib/libc/string/strnstr.c5
-rw-r--r--lib/libc/string/strpbrk.c5
-rw-r--r--lib/libc/string/strsep.c4
-rw-r--r--lib/libc/string/strstr.c7
-rw-r--r--lib/libc/string/wcscat.c4
-rw-r--r--lib/libc/string/wcscmp.c5
-rw-r--r--lib/libc/string/wcscpy.c4
-rw-r--r--lib/libc/string/wcscspn.c4
-rw-r--r--lib/libc/string/wcslcat.c5
-rw-r--r--lib/libc/string/wcslcpy.c5
-rw-r--r--lib/libc/string/wcslen.c3
-rw-r--r--lib/libc/string/wcsncat.c5
-rw-r--r--lib/libc/string/wcsncmp.c4
-rw-r--r--lib/libc/string/wcspbrk.c4
-rw-r--r--lib/libc/string/wcsspn.c4
-rw-r--r--lib/libc/string/wcsstr.c2
-rw-r--r--lib/libc/string/wmemchr.c5
-rw-r--r--lib/libc/string/wmemcmp.c5
-rw-r--r--lib/libc/string/wmemcpy.c6
-rw-r--r--lib/libc/string/wmemmove.c6
-rw-r--r--lib/libc/string/wmemset.c5
-rw-r--r--lib/libc/sys/jail.28
-rw-r--r--lib/libc/sys/send.24
-rw-r--r--lib/libc/sys/socket.27
-rw-r--r--lib/libc/sys/timer_create.25
59 files changed, 928 insertions, 967 deletions
diff --git a/lib/libc/db/man/dbm.3 b/lib/libc/db/man/dbm.3
index 16becc6..fabce8a 100644
--- a/lib/libc/db/man/dbm.3
+++ b/lib/libc/db/man/dbm.3
@@ -15,8 +15,6 @@
.\"
.\" $FreeBSD$
.\"
-.\" Note: The date here should be updated whenever a non-trivial
-.\" change is made to the manual page.
.Dd April 16, 2006
.Dt DBM 3
.Os
diff --git a/lib/libc/gen/sysctl.3 b/lib/libc/gen/sysctl.3
index bded0d1..75f8668 100644
--- a/lib/libc/gen/sysctl.3
+++ b/lib/libc/gen/sysctl.3
@@ -28,7 +28,7 @@
.\" @(#)sysctl.3 8.4 (Berkeley) 5/9/95
.\" $FreeBSD$
.\"
-.Dd March 27, 2008
+.Dd January 28, 2009
.Dt SYSCTL 3
.Os
.Sh NAME
@@ -440,10 +440,8 @@ attempts to comply.
.It Li KERN_PROC
Return selected information about specific running processes.
.Pp
-For the following names, an array of pairs of
-.Va struct proc
-followed by corresponding
-.Va struct eproc
+For the following names, an array of
+.Va struct kinfo_proc
structures is returned,
whose size depends on the current number of such objects in the system.
.Bl -column "Third level nameXXXXXX" "Fourth level is:XXXXXX" -offset indent
diff --git a/lib/libc/locale/mbstowcs.c b/lib/libc/locale/mbstowcs.c
index ad259d8..194ec2e 100644
--- a/lib/libc/locale/mbstowcs.c
+++ b/lib/libc/locale/mbstowcs.c
@@ -37,7 +37,9 @@ mbstowcs(wchar_t * __restrict pwcs, const char * __restrict s, size_t n)
{
static const mbstate_t initial;
mbstate_t mbs;
+ const char *sp;
mbs = initial;
- return (__mbsnrtowcs(pwcs, &s, SIZE_T_MAX, n, &mbs));
+ sp = s;
+ return (__mbsnrtowcs(pwcs, &sp, SIZE_T_MAX, n, &mbs));
}
diff --git a/lib/libc/locale/wcsftime.c b/lib/libc/locale/wcsftime.c
index 7a54fc0..a546dc6 100644
--- a/lib/libc/locale/wcsftime.c
+++ b/lib/libc/locale/wcsftime.c
@@ -52,7 +52,9 @@ wcsftime(wchar_t * __restrict wcs, size_t maxsize,
{
static const mbstate_t initial;
mbstate_t mbs;
- char *dst, *dstp, *sformat;
+ char *dst, *sformat;
+ const char *dstp;
+ const wchar_t *formatp;
size_t n, sflen;
int sverrno;
@@ -63,13 +65,14 @@ wcsftime(wchar_t * __restrict wcs, size_t maxsize,
* for strftime(), which only handles single-byte characters.
*/
mbs = initial;
- sflen = wcsrtombs(NULL, &format, 0, &mbs);
+ formatp = format;
+ sflen = wcsrtombs(NULL, &formatp, 0, &mbs);
if (sflen == (size_t)-1)
goto error;
if ((sformat = malloc(sflen + 1)) == NULL)
goto error;
mbs = initial;
- wcsrtombs(sformat, &format, sflen + 1, &mbs);
+ wcsrtombs(sformat, &formatp, sflen + 1, &mbs);
/*
* Allocate memory for longest multibyte sequence that will fit
@@ -88,7 +91,7 @@ wcsftime(wchar_t * __restrict wcs, size_t maxsize,
goto error;
dstp = dst;
mbs = initial;
- n = mbsrtowcs(wcs, (const char **)&dstp, maxsize, &mbs);
+ n = mbsrtowcs(wcs, &dstp, maxsize, &mbs);
if (n == (size_t)-2 || n == (size_t)-1 || dstp != NULL)
goto error;
diff --git a/lib/libc/locale/wcstombs.c b/lib/libc/locale/wcstombs.c
index acd0051..250d2b9 100644
--- a/lib/libc/locale/wcstombs.c
+++ b/lib/libc/locale/wcstombs.c
@@ -37,7 +37,9 @@ wcstombs(char * __restrict s, const wchar_t * __restrict pwcs, size_t n)
{
static const mbstate_t initial;
mbstate_t mbs;
+ const wchar_t *pwcsp;
mbs = initial;
- return (__wcsnrtombs(s, &pwcs, SIZE_T_MAX, n, &mbs));
+ pwcsp = pwcs;
+ return (__wcsnrtombs(s, &pwcsp, SIZE_T_MAX, n, &mbs));
}
diff --git a/lib/libc/net/getaddrinfo.3 b/lib/libc/net/getaddrinfo.3
index 8afdcf9..b09c068 100644
--- a/lib/libc/net/getaddrinfo.3
+++ b/lib/libc/net/getaddrinfo.3
@@ -18,7 +18,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd July 1, 2008
+.Dd January 6, 2009
.Dt GETADDRINFO 3
.Os
.Sh NAME
@@ -126,13 +126,11 @@ field to which the
parameter points shall be set to zero
or be the bitwise-inclusive OR of one or more of the values
.Dv AI_ADDRCONFIG ,
-.Dv AI_ALL ,
.Dv AI_CANONNAME ,
.Dv AI_NUMERICHOST ,
-.Dv AI_NUMERICSERV ,
-.Dv AI_PASSIVE ,
+.Dv AI_NUMERICSERV
and
-.Dv AI_V4MAPPED .
+.Dv AI_PASSIVE .
.Bl -tag -width "AI_CANONNAMEXX"
.It Dv AI_ADDRCONFIG
If the
@@ -141,19 +139,6 @@ bit is set, IPv4 addresses shall be returned only if
an IPv4 address is configured on the local system,
and IPv6 addresses shall be returned only if
an IPv6 address is configured on the local system.
-.It Dv AI_ALL
-If the
-.Dv AI_ALL
-bit is set with the
-.Dv AI_V4MAPPED
-bit, then
-.Fn getaddrinfo
-shall return all matching IPv6 and IPv4 addresses.
-The
-.Dv AI_ALL
-bit without the
-.Dv AI_V4MAPPED
-bit is ignored.
.It Dv AI_CANONNAME
If the
.Dv AI_CANONNAME
@@ -218,30 +203,6 @@ loopback address if
is the null pointer and
.Dv AI_PASSIVE
is not set.
-.It Dv AI_V4MAPPED
-If the
-.Dv AI_V4MAPPED
-flag is specified along with an
-.Fa ai_family
-of
-.Dv AF_INET6 ,
-then
-.Fn getaddrinfo
-shall return IPv4-mapped IPv6 addresses
-on finding no matching IPv6 addresses (
-.Fa ai_addrlen
-shall be 16).
-The
-.Dv AI_V4MAPPED
-flag shall be ignored unless
-.Fa ai_family
-equals
-.Dv AF_INET6 .
-Note: this flag is currently
-.Em not
-supported, see the
-.Sx BUGS
-section.
.El
.El
.Pp
@@ -490,18 +451,6 @@ freeaddrinfo(res0);
.%B "Proceedings of the freenix track: 2000 USENIX annual technical conference"
.%D June 2000
.Re
-.Sh BUGS
-The
-.Nm
-function as implemented in
-.Fx
-currently does not support
-.Dv AI_ALL
-and
-.Dv AI_V4MAPPED
-flags and returns
-.Dv EAI_BADFLAGS
-if one of them is specified.
.Sh STANDARDS
The
.Fn getaddrinfo
diff --git a/lib/libc/sparc64/sys/__sparc_utrap.c b/lib/libc/sparc64/sys/__sparc_utrap.c
index e556f83..7a5dafa 100644
--- a/lib/libc/sparc64/sys/__sparc_utrap.c
+++ b/lib/libc/sparc64/sys/__sparc_utrap.c
@@ -122,7 +122,7 @@ __utrap_write(const char *str)
}
void
-__utrap_kill_self(sig)
+__utrap_kill_self(int sig)
{
int berrno;
diff --git a/lib/libc/stdio/ferror.3 b/lib/libc/stdio/ferror.3
index d7daef3..043b688 100644
--- a/lib/libc/stdio/ferror.3
+++ b/lib/libc/stdio/ferror.3
@@ -32,7 +32,7 @@
.\" @(#)ferror.3 8.2 (Berkeley) 4/19/94
.\" $FreeBSD$
.\"
-.Dd January 10, 2003
+.Dd January 28, 2009
.Dt FERROR 3
.Os
.Sh NAME
@@ -77,17 +77,16 @@ The function
tests the end-of-file indicator for the stream pointed to by
.Fa stream ,
returning non-zero if it is set.
-The end-of-file indicator can only be cleared by the function
-.Fn clearerr .
+The end-of-file indicator may be cleared by explicitly calling
+.Fn clearerr ,
+or as a side-effect of other operations, e.g.\&
+.Fn fseek .
.Pp
The function
.Fn ferror
tests the error indicator for the stream pointed to by
.Fa stream ,
returning non-zero if it is set.
-The error indicator can only be reset by the
-.Fn clearerr
-function.
.Pp
The function
.Fn fileno
diff --git a/lib/libc/stdio/fputws.c b/lib/libc/stdio/fputws.c
index 7397411..b4462b7 100644
--- a/lib/libc/stdio/fputws.c
+++ b/lib/libc/stdio/fputws.c
@@ -45,6 +45,7 @@ fputws(const wchar_t * __restrict ws, FILE * __restrict fp)
char buf[BUFSIZ];
struct __suio uio;
struct __siov iov;
+ const wchar_t *wsp;
FLOCKFILE(fp);
ORIENT(fp, 1);
@@ -54,7 +55,8 @@ fputws(const wchar_t * __restrict ws, FILE * __restrict fp)
uio.uio_iovcnt = 1;
iov.iov_base = buf;
do {
- nbytes = __wcsnrtombs(buf, &ws, SIZE_T_MAX, sizeof(buf),
+ wsp = ws;
+ nbytes = __wcsnrtombs(buf, &wsp, SIZE_T_MAX, sizeof(buf),
&fp->_mbstate);
if (nbytes == (size_t)-1)
goto error;
diff --git a/lib/libc/stdio/printf.3 b/lib/libc/stdio/printf.3
index a126a64..98e26dc 100644
--- a/lib/libc/stdio/printf.3
+++ b/lib/libc/stdio/printf.3
@@ -207,8 +207,7 @@ conversions, this option has no effect.
For
.Cm o
conversions, the precision of the number is increased to force the first
-character of the output string to a zero (except if a zero value is printed
-with an explicit precision of zero).
+character of the output string to a zero.
For
.Cm x
and
diff --git a/lib/libc/stdio/printfcommon.h b/lib/libc/stdio/printfcommon.h
new file mode 100644
index 0000000..39b0003
--- /dev/null
+++ b/lib/libc/stdio/printfcommon.h
@@ -0,0 +1,301 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * This file defines common routines used by both printf and wprintf.
+ * You must define CHAR to either char or wchar_t prior to including this.
+ */
+
+
+#ifndef NO_FLOATING_POINT
+
+#define dtoa __dtoa
+#define freedtoa __freedtoa
+
+#include <float.h>
+#include <math.h>
+#include "floatio.h"
+#include "gdtoa.h"
+
+#define DEFPREC 6
+
+static int exponent(CHAR *, int, CHAR);
+
+#endif /* !NO_FLOATING_POINT */
+
+static CHAR *__ujtoa(uintmax_t, CHAR *, int, int, const char *);
+static CHAR *__ultoa(u_long, CHAR *, int, int, const char *);
+
+#define NIOV 8
+struct io_state {
+ FILE *fp;
+ struct __suio uio; /* output information: summary */
+ struct __siov iov[NIOV];/* ... and individual io vectors */
+};
+
+static inline void
+io_init(struct io_state *iop, FILE *fp)
+{
+
+ iop->uio.uio_iov = iop->iov;
+ iop->uio.uio_resid = 0;
+ iop->uio.uio_iovcnt = 0;
+ iop->fp = fp;
+}
+
+/*
+ * WARNING: The buffer passed to io_print() is not copied immediately; it must
+ * remain valid until io_flush() is called.
+ */
+static inline int
+io_print(struct io_state *iop, const CHAR * __restrict ptr, int len)
+{
+
+ iop->iov[iop->uio.uio_iovcnt].iov_base = (char *)ptr;
+ iop->iov[iop->uio.uio_iovcnt].iov_len = len;
+ iop->uio.uio_resid += len;
+ if (++iop->uio.uio_iovcnt >= NIOV)
+ return (__sprint(iop->fp, &iop->uio));
+ else
+ return (0);
+}
+
+/*
+ * Choose PADSIZE to trade efficiency vs. size. If larger printf
+ * fields occur frequently, increase PADSIZE and make the initialisers
+ * below longer.
+ */
+#define PADSIZE 16 /* pad chunk size */
+static const CHAR blanks[PADSIZE] =
+{' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
+static const CHAR zeroes[PADSIZE] =
+{'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
+
+/*
+ * Pad with blanks or zeroes. 'with' should point to either the blanks array
+ * or the zeroes array.
+ */
+static inline int
+io_pad(struct io_state *iop, int howmany, const CHAR * __restrict with)
+{
+ int n;
+
+ while (howmany > 0) {
+ n = (howmany >= PADSIZE) ? PADSIZE : howmany;
+ if (io_print(iop, with, n))
+ return (-1);
+ howmany -= n;
+ }
+ return (0);
+}
+
+/*
+ * Print exactly len characters of the string spanning p to ep, truncating
+ * or padding with 'with' as necessary.
+ */
+static inline int
+io_printandpad(struct io_state *iop, const CHAR *p, const CHAR *ep,
+ int len, const CHAR * __restrict with)
+{
+ int p_len;
+
+ p_len = ep - p;
+ if (p_len > len)
+ p_len = len;
+ if (p_len > 0) {
+ if (io_print(iop, p, p_len))
+ return (-1);
+ } else {
+ p_len = 0;
+ }
+ return (io_pad(iop, len - p_len, with));
+}
+
+static inline int
+io_flush(struct io_state *iop)
+{
+
+ return (__sprint(iop->fp, &iop->uio));
+}
+
+/*
+ * Convert an unsigned long to ASCII for printf purposes, returning
+ * a pointer to the first character of the string representation.
+ * Octal numbers can be forced to have a leading zero; hex numbers
+ * use the given digits.
+ */
+static CHAR *
+__ultoa(u_long val, CHAR *endp, int base, int octzero, const char *xdigs)
+{
+ CHAR *cp = endp;
+ long sval;
+
+ /*
+ * Handle the three cases separately, in the hope of getting
+ * better/faster code.
+ */
+ switch (base) {
+ case 10:
+ if (val < 10) { /* many numbers are 1 digit */
+ *--cp = to_char(val);
+ return (cp);
+ }
+ /*
+ * On many machines, unsigned arithmetic is harder than
+ * signed arithmetic, so we do at most one unsigned mod and
+ * divide; this is sufficient to reduce the range of
+ * the incoming value to where signed arithmetic works.
+ */
+ if (val > LONG_MAX) {
+ *--cp = to_char(val % 10);
+ sval = val / 10;
+ } else
+ sval = val;
+ do {
+ *--cp = to_char(sval % 10);
+ sval /= 10;
+ } while (sval != 0);
+ break;
+
+ case 8:
+ do {
+ *--cp = to_char(val & 7);
+ val >>= 3;
+ } while (val);
+ if (octzero && *cp != '0')
+ *--cp = '0';
+ break;
+
+ case 16:
+ do {
+ *--cp = xdigs[val & 15];
+ val >>= 4;
+ } while (val);
+ break;
+
+ default: /* oops */
+ abort();
+ }
+ return (cp);
+}
+
+/* Identical to __ultoa, but for intmax_t. */
+static CHAR *
+__ujtoa(uintmax_t val, CHAR *endp, int base, int octzero, const char *xdigs)
+{
+ CHAR *cp = endp;
+ intmax_t sval;
+
+ /* quick test for small values; __ultoa is typically much faster */
+ /* (perhaps instead we should run until small, then call __ultoa?) */
+ if (val <= ULONG_MAX)
+ return (__ultoa((u_long)val, endp, base, octzero, xdigs));
+ switch (base) {
+ case 10:
+ if (val < 10) {
+ *--cp = to_char(val % 10);
+ return (cp);
+ }
+ if (val > INTMAX_MAX) {
+ *--cp = to_char(val % 10);
+ sval = val / 10;
+ } else
+ sval = val;
+ do {
+ *--cp = to_char(sval % 10);
+ sval /= 10;
+ } while (sval != 0);
+ break;
+
+ case 8:
+ do {
+ *--cp = to_char(val & 7);
+ val >>= 3;
+ } while (val);
+ if (octzero && *cp != '0')
+ *--cp = '0';
+ break;
+
+ case 16:
+ do {
+ *--cp = xdigs[val & 15];
+ val >>= 4;
+ } while (val);
+ break;
+
+ default:
+ abort();
+ }
+ return (cp);
+}
+
+#ifndef NO_FLOATING_POINT
+
+static int
+exponent(CHAR *p0, int exp, CHAR fmtch)
+{
+ CHAR *p, *t;
+ CHAR expbuf[MAXEXPDIG];
+
+ p = p0;
+ *p++ = fmtch;
+ if (exp < 0) {
+ exp = -exp;
+ *p++ = '-';
+ }
+ else
+ *p++ = '+';
+ t = expbuf + MAXEXPDIG;
+ if (exp > 9) {
+ do {
+ *--t = to_char(exp % 10);
+ } while ((exp /= 10) > 9);
+ *--t = to_char(exp);
+ for (; t < expbuf + MAXEXPDIG; *p++ = *t++);
+ }
+ else {
+ /*
+ * Exponents for decimal floating point conversions
+ * (%[eEgG]) must be at least two characters long,
+ * whereas exponents for hexadecimal conversions can
+ * be only one character long.
+ */
+ if (fmtch == 'e' || fmtch == 'E')
+ *p++ = '0';
+ *p++ = to_char(exp);
+ }
+ return (p - p0);
+}
+
+#endif /* !NO_FLOATING_POINT */
diff --git a/lib/libc/stdio/vfprintf.c b/lib/libc/stdio/vfprintf.c
index dab331d..e3f95eb 100644
--- a/lib/libc/stdio/vfprintf.c
+++ b/lib/libc/stdio/vfprintf.c
@@ -65,13 +65,82 @@ __FBSDID("$FreeBSD$");
#include "printflocal.h"
static int __sprint(FILE *, struct __suio *);
-static int __sbprintf(FILE *, const char *, va_list) __printflike(2, 0);
-static char *__ujtoa(uintmax_t, char *, int, int, const char *, int, char,
- const char *);
-static char *__ultoa(u_long, char *, int, int, const char *, int, char,
- const char *);
+static int __sbprintf(FILE *, const char *, va_list) __printflike(2, 0)
+ __noinline;
static char *__wcsconv(wchar_t *, int);
+#define CHAR char
+#include "printfcommon.h"
+
+struct grouping_state {
+ char *thousands_sep; /* locale-specific thousands separator */
+ int thousep_len; /* length of thousands_sep */
+ const char *grouping; /* locale-specific numeric grouping rules */
+ int lead; /* sig figs before decimal or group sep */
+ int nseps; /* number of group separators with ' */
+ int nrepeats; /* number of repeats of the last group */
+};
+
+/*
+ * Initialize the thousands' grouping state in preparation to print a
+ * number with ndigits digits. This routine returns the total number
+ * of bytes that will be needed.
+ */
+static int
+grouping_init(struct grouping_state *gs, int ndigits)
+{
+ struct lconv *locale;
+
+ locale = localeconv();
+ gs->grouping = locale->grouping;
+ gs->thousands_sep = locale->thousands_sep;
+ gs->thousep_len = strlen(gs->thousands_sep);
+
+ gs->nseps = gs->nrepeats = 0;
+ gs->lead = ndigits;
+ while (*gs->grouping != CHAR_MAX) {
+ if (gs->lead <= *gs->grouping)
+ break;
+ gs->lead -= *gs->grouping;
+ if (*(gs->grouping+1)) {
+ gs->nseps++;
+ gs->grouping++;
+ } else
+ gs->nrepeats++;
+ }
+ return ((gs->nseps + gs->nrepeats) * gs->thousep_len);
+}
+
+/*
+ * Print a number with thousands' separators.
+ */
+static int
+grouping_print(struct grouping_state *gs, struct io_state *iop,
+ const CHAR *cp, const CHAR *ep)
+{
+ const CHAR *cp0 = cp;
+
+ if (io_printandpad(iop, cp, ep, gs->lead, zeroes))
+ return (-1);
+ cp += gs->lead;
+ while (gs->nseps > 0 || gs->nrepeats > 0) {
+ if (gs->nrepeats > 0)
+ gs->nrepeats--;
+ else {
+ gs->grouping--;
+ gs->nseps--;
+ }
+ if (io_print(iop, gs->thousands_sep, gs->thousep_len))
+ return (-1);
+ if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes))
+ return (-1);
+ cp += *gs->grouping;
+ }
+ if (cp > ep)
+ cp = ep;
+ return (cp - cp0);
+}
+
/*
* Flush out all the vectors defined by the given uio,
* then reset it so that it can be reused.
@@ -103,6 +172,10 @@ __sbprintf(FILE *fp, const char *fmt, va_list ap)
FILE fake;
unsigned char buf[BUFSIZ];
+ /* XXX This is probably not needed. */
+ if (prepwrite(fp) != 0)
+ return (EOF);
+
/* copy the important variables */
fake._flags = fp->_flags & ~__SNBF;
fake._file = fp->_file;
@@ -126,160 +199,6 @@ __sbprintf(FILE *fp, const char *fmt, va_list ap)
}
/*
- * Convert an unsigned long to ASCII for printf purposes, returning
- * a pointer to the first character of the string representation.
- * Octal numbers can be forced to have a leading zero; hex numbers
- * use the given digits.
- */
-static char *
-__ultoa(u_long val, char *endp, int base, int octzero, const char *xdigs,
- int needgrp, char thousep, const char *grp)
-{
- char *cp = endp;
- long sval;
- int ndig;
-
- /*
- * Handle the three cases separately, in the hope of getting
- * better/faster code.
- */
- switch (base) {
- case 10:
- if (val < 10) { /* many numbers are 1 digit */
- *--cp = to_char(val);
- return (cp);
- }
- ndig = 0;
- /*
- * On many machines, unsigned arithmetic is harder than
- * signed arithmetic, so we do at most one unsigned mod and
- * divide; this is sufficient to reduce the range of
- * the incoming value to where signed arithmetic works.
- */
- if (val > LONG_MAX) {
- *--cp = to_char(val % 10);
- ndig++;
- sval = val / 10;
- } else
- sval = val;
- do {
- *--cp = to_char(sval % 10);
- ndig++;
- /*
- * If (*grp == CHAR_MAX) then no more grouping
- * should be performed.
- */
- if (needgrp && ndig == *grp && *grp != CHAR_MAX
- && sval > 9) {
- *--cp = thousep;
- ndig = 0;
- /*
- * If (*(grp+1) == '\0') then we have to
- * use *grp character (last grouping rule)
- * for all next cases
- */
- if (*(grp+1) != '\0')
- grp++;
- }
- sval /= 10;
- } while (sval != 0);
- break;
-
- case 8:
- do {
- *--cp = to_char(val & 7);
- val >>= 3;
- } while (val);
- if (octzero && *cp != '0')
- *--cp = '0';
- break;
-
- case 16:
- do {
- *--cp = xdigs[val & 15];
- val >>= 4;
- } while (val);
- break;
-
- default: /* oops */
- abort();
- }
- return (cp);
-}
-
-/* Identical to __ultoa, but for intmax_t. */
-static char *
-__ujtoa(uintmax_t val, char *endp, int base, int octzero, const char *xdigs,
- int needgrp, char thousep, const char *grp)
-{
- char *cp = endp;
- intmax_t sval;
- int ndig;
-
- /* quick test for small values; __ultoa is typically much faster */
- /* (perhaps instead we should run until small, then call __ultoa?) */
- if (val <= ULONG_MAX)
- return (__ultoa((u_long)val, endp, base, octzero, xdigs,
- needgrp, thousep, grp));
- switch (base) {
- case 10:
- if (val < 10) {
- *--cp = to_char(val % 10);
- return (cp);
- }
- ndig = 0;
- if (val > INTMAX_MAX) {
- *--cp = to_char(val % 10);
- ndig++;
- sval = val / 10;
- } else
- sval = val;
- do {
- *--cp = to_char(sval % 10);
- ndig++;
- /*
- * If (*grp == CHAR_MAX) then no more grouping
- * should be performed.
- */
- if (needgrp && *grp != CHAR_MAX && ndig == *grp
- && sval > 9) {
- *--cp = thousep;
- ndig = 0;
- /*
- * If (*(grp+1) == '\0') then we have to
- * use *grp character (last grouping rule)
- * for all next cases
- */
- if (*(grp+1) != '\0')
- grp++;
- }
- sval /= 10;
- } while (sval != 0);
- break;
-
- case 8:
- do {
- *--cp = to_char(val & 7);
- val >>= 3;
- } while (val);
- if (octzero && *cp != '0')
- *--cp = '0';
- break;
-
- case 16:
- do {
- *--cp = xdigs[val & 15];
- val >>= 4;
- } while (val);
- break;
-
- default:
- abort();
- }
- return (cp);
-}
-
-/*
* Convert a wide character string argument for the %ls format to a multibyte
* string representation. If not -1, prec specifies the maximum number of
* bytes to output, and also means that we can't assume that the wide char.
@@ -348,35 +267,26 @@ vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap)
int ret;
FLOCKFILE(fp);
- ret = __vfprintf(fp, fmt0, ap);
+ /* optimise fprintf(stderr) (and other unbuffered Unix files) */
+ if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
+ fp->_file >= 0)
+ ret = __sbprintf(fp, fmt0, ap);
+ else
+ ret = __vfprintf(fp, fmt0, ap);
FUNLOCKFILE(fp);
return (ret);
}
-#ifndef NO_FLOATING_POINT
-
-#define dtoa __dtoa
-#define freedtoa __freedtoa
-
-#include <float.h>
-#include <math.h>
-#include "floatio.h"
-#include "gdtoa.h"
-
-#define DEFPREC 6
-
-static int exponent(char *, int, int);
-
-#endif /* !NO_FLOATING_POINT */
-
/*
* The size of the buffer we use as scratch space for integer
- * conversions, among other things. Technically, we would need the
- * most space for base 10 conversions with thousands' grouping
- * characters between each pair of digits. 100 bytes is a
- * conservative overestimate even for a 128-bit uintmax_t.
+ * conversions, among other things. We need enough space to
+ * write a uintmax_t in octal (plus one byte).
*/
-#define BUF 100
+#if UINTMAX_MAX <= UINT64_MAX
+#define BUF 32
+#else
+#error "BUF must be large enough to format a uintmax_t"
+#endif
/*
* Non-MT-safe version
@@ -388,14 +298,13 @@ __vfprintf(FILE *fp, const char *fmt0, va_list ap)
int ch; /* character from fmt */
int n, n2; /* handy integer (short term usage) */
char *cp; /* handy char pointer (short term usage) */
- struct __siov *iovp; /* for PRINT macro */
int flags; /* flags as above */
int ret; /* return value accumulator */
int width; /* width from format (%8d), or 0 */
int prec; /* precision from format; <0 for N/A */
char sign; /* sign prefix (' ', '+', '-', or \0) */
- char thousands_sep; /* locale specific thousands separator */
- const char *grouping; /* locale specific numeric grouping rules */
+ struct grouping_state gs; /* thousands' grouping info */
+
#ifndef NO_FLOATING_POINT
/*
* We can decompose the printed representation of floating
@@ -412,6 +321,7 @@ __vfprintf(FILE *fp, const char *fmt0, va_list ap)
* F: at least two digits for decimal, at least one digit for hex
*/
char *decimal_point; /* locale specific decimal point */
+ int decpt_len; /* length of decimal_point */
int signflag; /* true if float is negative */
union { /* floating point arguments %[aAeEfFgG] */
double dbl;
@@ -421,12 +331,9 @@ __vfprintf(FILE *fp, const char *fmt0, va_list ap)
char expchar; /* exponent character: [eEpP\0] */
char *dtoaend; /* pointer to end of converted digits */
int expsize; /* character count for expstr */
- int lead; /* sig figs before decimal or group sep */
int ndig; /* actual number of digits returned by dtoa */
char expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */
char *dtoaresult; /* buffer allocated by dtoa */
- int nseps; /* number of group separators with ' */
- int nrepeats; /* number of repeats of the last group */
#endif
u_long ulval; /* integer arguments %[diouxX] */
uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */
@@ -436,9 +343,7 @@ __vfprintf(FILE *fp, const char *fmt0, va_list ap)
int size; /* size of converted field or string */
int prsize; /* max size of printed field */
const char *xdigs; /* digits for %[xX] conversion */
-#define NIOV 8
- struct __suio uio; /* output information: summary */
- struct __siov iov[NIOV];/* ... and individual io vectors */
+ struct io_state io; /* I/O buffering state */
char buf[BUF]; /* buffer with space for digits of uintmax_t */
char ox[2]; /* space for 0x; ox[1] is either x, X, or \0 */
union arg *argtable; /* args, built due to positional arg */
@@ -447,56 +352,25 @@ __vfprintf(FILE *fp, const char *fmt0, va_list ap)
va_list orgap; /* original argument pointer */
char *convbuf; /* wide to multibyte conversion result */
- /*
- * Choose PADSIZE to trade efficiency vs. size. If larger printf
- * fields occur frequently, increase PADSIZE and make the initialisers
- * below longer.
- */
-#define PADSIZE 16 /* pad chunk size */
- static char blanks[PADSIZE] =
- {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
- static char zeroes[PADSIZE] =
- {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
-
static const char xdigs_lower[16] = "0123456789abcdef";
static const char xdigs_upper[16] = "0123456789ABCDEF";
- /*
- * BEWARE, these `goto error' on error, and PAD uses `n'.
- */
+ /* BEWARE, these `goto error' on error. */
#define PRINT(ptr, len) { \
- iovp->iov_base = (ptr); \
- iovp->iov_len = (len); \
- uio.uio_resid += (len); \
- iovp++; \
- if (++uio.uio_iovcnt >= NIOV) { \
- if (__sprint(fp, &uio)) \
- goto error; \
- iovp = iov; \
- } \
+ if (io_print(&io, (ptr), (len))) \
+ goto error; \
}
#define PAD(howmany, with) { \
- if ((n = (howmany)) > 0) { \
- while (n > PADSIZE) { \
- PRINT(with, PADSIZE); \
- n -= PADSIZE; \
- } \
- PRINT(with, n); \
- } \
+ if (io_pad(&io, (howmany), (with))) \
+ goto error; \
+}
+#define PRINTANDPAD(p, ep, len, with) { \
+ if (io_printandpad(&io, (p), (ep), (len), (with))) \
+ goto error; \
}
-#define PRINTANDPAD(p, ep, len, with) do { \
- n2 = (ep) - (p); \
- if (n2 > (len)) \
- n2 = (len); \
- if (n2 > 0) \
- PRINT((p), n2); \
- PAD((len) - (n2 > 0 ? n2 : 0), (with)); \
-} while(0)
#define FLUSH() { \
- if (uio.uio_resid && __sprint(fp, &uio)) \
+ if (io_flush(&io)) \
goto error; \
- uio.uio_iovcnt = 0; \
- iovp = iov; \
}
/*
@@ -571,25 +445,18 @@ __vfprintf(FILE *fp, const char *fmt0, va_list ap)
if (prepwrite(fp) != 0)
return (EOF);
- /* optimise fprintf(stderr) (and other unbuffered Unix files) */
- if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
- fp->_file >= 0)
- return (__sbprintf(fp, fmt0, ap));
-
- thousands_sep = '\0';
- grouping = NULL;
convbuf = NULL;
fmt = (char *)fmt0;
argtable = NULL;
nextarg = 1;
va_copy(orgap, ap);
- uio.uio_iov = iovp = iov;
- uio.uio_resid = 0;
- uio.uio_iovcnt = 0;
+ io_init(&io, fp);
ret = 0;
#ifndef NO_FLOATING_POINT
dtoaresult = NULL;
decimal_point = localeconv()->decimal_point;
+ /* The overwhelmingly common case is decpt_len == 1. */
+ decpt_len = (decimal_point[1] == '\0' ? 1 : strlen(decimal_point));
#endif
/*
@@ -614,6 +481,7 @@ __vfprintf(FILE *fp, const char *fmt0, va_list ap)
dprec = 0;
width = 0;
prec = -1;
+ gs.grouping = NULL;
sign = '\0';
ox[1] = '\0';
@@ -651,8 +519,6 @@ reswitch: switch (ch) {
goto rflag;
case '\'':
flags |= GROUPING;
- thousands_sep = *(localeconv()->thousands_sep);
- grouping = localeconv()->grouping;
goto rflag;
case '.':
if ((ch = *fmt++) == '*') {
@@ -873,7 +739,7 @@ fp_common:
expsize = exponent(expstr, expt - 1, expchar);
size = expsize + prec;
if (prec > 1 || flags & ALT)
- ++size;
+ size += decpt_len;
} else {
/* space for digits before decimal point */
if (expt > 0)
@@ -882,24 +748,9 @@ fp_common:
size = 1;
/* space for decimal pt and following digits */
if (prec || flags & ALT)
- size += prec + 1;
- if (grouping && expt > 0) {
- /* space for thousands' grouping */
- nseps = nrepeats = 0;
- lead = expt;
- while (*grouping != CHAR_MAX) {
- if (lead <= *grouping)
- break;
- lead -= *grouping;
- if (*(grouping+1)) {
- nseps++;
- grouping++;
- } else
- nrepeats++;
- }
- size += nseps + nrepeats;
- } else
- lead = expt;
+ size += prec + decpt_len;
+ if ((flags & GROUPING) && expt > 0)
+ size += grouping_init(&gs, expt);
}
break;
#endif /* !NO_FLOATING_POINT */
@@ -1040,20 +891,18 @@ number: if ((dprec = prec) >= 0)
if (ujval != 0 || prec != 0 ||
(flags & ALT && base == 8))
cp = __ujtoa(ujval, cp, base,
- flags & ALT, xdigs,
- flags & GROUPING, thousands_sep,
- grouping);
+ flags & ALT, xdigs);
} else {
if (ulval != 0 || prec != 0 ||
(flags & ALT && base == 8))
cp = __ultoa(ulval, cp, base,
- flags & ALT, xdigs,
- flags & GROUPING, thousands_sep,
- grouping);
+ flags & ALT, xdigs);
}
size = buf + BUF - cp;
if (size > BUF) /* should never happen */
abort();
+ if ((flags & GROUPING) && size != 0)
+ size += grouping_init(&gs, size);
break;
default: /* "%?" prints ?, unless ? is NUL */
if (ch == '\0')
@@ -1109,51 +958,48 @@ number: if ((dprec = prec) >= 0)
if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
PAD(width - realsz, zeroes);
- /* leading zeroes from decimal precision */
- PAD(dprec - size, zeroes);
-
/* the string or number proper */
#ifndef NO_FLOATING_POINT
if ((flags & FPT) == 0) {
- PRINT(cp, size);
+#endif
+ /* leading zeroes from decimal precision */
+ PAD(dprec - size, zeroes);
+ if (gs.grouping) {
+ if (grouping_print(&gs, &io, cp, buf+BUF) < 0)
+ goto error;
+ } else {
+ PRINT(cp, size);
+ }
+#ifndef NO_FLOATING_POINT
} else { /* glue together f_p fragments */
if (!expchar) { /* %[fF] or sufficiently short %[gG] */
if (expt <= 0) {
PRINT(zeroes, 1);
if (prec || flags & ALT)
- PRINT(decimal_point, 1);
+ PRINT(decimal_point,decpt_len);
PAD(-expt, zeroes);
/* already handled initial 0's */
prec += expt;
} else {
- PRINTANDPAD(cp, dtoaend, lead, zeroes);
- cp += lead;
- if (grouping) {
- while (nseps>0 || nrepeats>0) {
- if (nrepeats > 0)
- nrepeats--;
- else {
- grouping--;
- nseps--;
- }
- PRINT(&thousands_sep,
- 1);
- PRINTANDPAD(cp,dtoaend,
- *grouping, zeroes);
- cp += *grouping;
- }
- if (cp > dtoaend)
- cp = dtoaend;
+ if (gs.grouping) {
+ n = grouping_print(&gs, &io,
+ cp, dtoaend);
+ if (n < 0)
+ goto error;
+ cp += n;
+ } else {
+ PRINTANDPAD(cp, dtoaend,
+ expt, zeroes);
+ cp += expt;
}
if (prec || flags & ALT)
- PRINT(decimal_point,1);
+ PRINT(decimal_point,decpt_len);
}
PRINTANDPAD(cp, dtoaend, prec, zeroes);
} else { /* %[eE] or sufficiently long %[gG] */
if (prec > 1 || flags & ALT) {
- buf[0] = *cp++;
- buf[1] = *decimal_point;
- PRINT(buf, 2);
+ PRINT(cp++, 1);
+ PRINT(decimal_point, decpt_len);
PRINT(cp, ndig-1);
PAD(prec - ndig, zeroes);
} else /* XeYYY */
@@ -1161,8 +1007,6 @@ number: if ((dprec = prec) >= 0)
PRINT(expstr, expsize);
}
}
-#else
- PRINT(cp, size);
#endif
/* left-adjusting padding (always blank) */
if (flags & LADJUST)
@@ -1191,42 +1035,3 @@ error:
/* NOTREACHED */
}
-
-#ifndef NO_FLOATING_POINT
-
-static int
-exponent(char *p0, int exp, int fmtch)
-{
- char *p, *t;
- char expbuf[MAXEXPDIG];
-
- p = p0;
- *p++ = fmtch;
- if (exp < 0) {
- exp = -exp;
- *p++ = '-';
- }
- else
- *p++ = '+';
- t = expbuf + MAXEXPDIG;
- if (exp > 9) {
- do {
- *--t = to_char(exp % 10);
- } while ((exp /= 10) > 9);
- *--t = to_char(exp);
- for (; t < expbuf + MAXEXPDIG; *p++ = *t++);
- }
- else {
- /*
- * Exponents for decimal floating point conversions
- * (%[eEgG]) must be at least two characters long,
- * whereas exponents for hexadecimal conversions can
- * be only one character long.
- */
- if (fmtch == 'e' || fmtch == 'E')
- *p++ = '0';
- *p++ = to_char(exp);
- }
- return (p - p0);
-}
-#endif /* !NO_FLOATING_POINT */
diff --git a/lib/libc/stdio/vfscanf.c b/lib/libc/stdio/vfscanf.c
index 9d724eb..bce4481 100644
--- a/lib/libc/stdio/vfscanf.c
+++ b/lib/libc/stdio/vfscanf.c
@@ -911,13 +911,13 @@ static int
parsefloat(FILE *fp, char *buf, char *end)
{
char *commit, *p;
- int infnanpos = 0;
+ int infnanpos = 0, decptpos = 0;
enum {
- S_START, S_GOTSIGN, S_INF, S_NAN, S_MAYBEHEX,
- S_DIGITS, S_FRAC, S_EXP, S_EXPDIGITS
+ S_START, S_GOTSIGN, S_INF, S_NAN, S_DONE, S_MAYBEHEX,
+ S_DIGITS, S_DECPT, S_FRAC, S_EXP, S_EXPDIGITS
} state = S_START;
unsigned char c;
- char decpt = *localeconv()->decimal_point;
+ const char *decpt = localeconv()->decimal_point;
_Bool gotmantdig = 0, ishex = 0;
/*
@@ -970,8 +970,6 @@ reswitch:
break;
case S_NAN:
switch (infnanpos) {
- case -1: /* XXX kludge to deal with nan(...) */
- goto parsedone;
case 0:
if (c != 'A' && c != 'a')
goto parsedone;
@@ -989,13 +987,15 @@ reswitch:
default:
if (c == ')') {
commit = p;
- infnanpos = -2;
+ state = S_DONE;
} else if (!isalnum(c) && c != '_')
goto parsedone;
break;
}
infnanpos++;
break;
+ case S_DONE:
+ goto parsedone;
case S_MAYBEHEX:
state = S_DIGITS;
if (c == 'X' || c == 'x') {
@@ -1006,16 +1006,34 @@ reswitch:
goto reswitch;
}
case S_DIGITS:
- if ((ishex && isxdigit(c)) || isdigit(c))
+ if ((ishex && isxdigit(c)) || isdigit(c)) {
gotmantdig = 1;
- else {
+ commit = p;
+ break;
+ } else {
+ state = S_DECPT;
+ goto reswitch;
+ }
+ case S_DECPT:
+ if (c == decpt[decptpos]) {
+ if (decpt[++decptpos] == '\0') {
+ /* We read the complete decpt seq. */
+ state = S_FRAC;
+ if (gotmantdig)
+ commit = p;
+ }
+ break;
+ } else if (!decptpos) {
+ /* We didn't read any decpt characters. */
state = S_FRAC;
- if (c != decpt)
- goto reswitch;
+ goto reswitch;
+ } else {
+ /*
+ * We read part of a multibyte decimal point,
+ * but the rest is invalid, so bail.
+ */
+ goto parsedone;
}
- if (gotmantdig)
- commit = p;
- break;
case S_FRAC:
if (((c == 'E' || c == 'e') && !ishex) ||
((c == 'P' || c == 'p') && ishex)) {
diff --git a/lib/libc/stdio/vfwprintf.c b/lib/libc/stdio/vfwprintf.c
index 9f06f1b..054299a 100644
--- a/lib/libc/stdio/vfwprintf.c
+++ b/lib/libc/stdio/vfwprintf.c
@@ -66,14 +66,139 @@ __FBSDID("$FreeBSD$");
#include "fvwrite.h"
#include "printflocal.h"
-static int __sbprintf(FILE *, const wchar_t *, va_list);
+static int __sprint(FILE *, struct __suio *);
+static int __sbprintf(FILE *, const wchar_t *, va_list) __noinline;
static wint_t __xfputwc(wchar_t, FILE *);
-static wchar_t *__ujtoa(uintmax_t, wchar_t *, int, int, const char *, int,
- char, const char *);
-static wchar_t *__ultoa(u_long, wchar_t *, int, int, const char *, int,
- char, const char *);
static wchar_t *__mbsconv(char *, int);
+#define CHAR wchar_t
+#include "printfcommon.h"
+
+struct grouping_state {
+ wchar_t thousands_sep; /* locale-specific thousands separator */
+ const char *grouping; /* locale-specific numeric grouping rules */
+ int lead; /* sig figs before decimal or group sep */
+ int nseps; /* number of group separators with ' */
+ int nrepeats; /* number of repeats of the last group */
+};
+
+static const mbstate_t initial_mbs;
+
+static inline wchar_t
+get_decpt(void)
+{
+ mbstate_t mbs;
+ wchar_t decpt;
+ int nconv;
+
+ mbs = initial_mbs;
+ nconv = mbrtowc(&decpt, localeconv()->decimal_point, MB_CUR_MAX, &mbs);
+ if (nconv == (size_t)-1 || nconv == (size_t)-2)
+ decpt = '.'; /* failsafe */
+ return (decpt);
+}
+
+static inline wchar_t
+get_thousep(void)
+{
+ mbstate_t mbs;
+ wchar_t thousep;
+ int nconv;
+
+ mbs = initial_mbs;
+ nconv = mbrtowc(&thousep, localeconv()->thousands_sep,
+ MB_CUR_MAX, &mbs);
+ if (nconv == (size_t)-1 || nconv == (size_t)-2)
+ thousep = '\0'; /* failsafe */
+ return (thousep);
+}
+
+/*
+ * Initialize the thousands' grouping state in preparation to print a
+ * number with ndigits digits. This routine returns the total number
+ * of wide characters that will be printed.
+ */
+static int
+grouping_init(struct grouping_state *gs, int ndigits)
+{
+
+ gs->grouping = localeconv()->grouping;
+ gs->thousands_sep = get_thousep();
+
+ gs->nseps = gs->nrepeats = 0;
+ gs->lead = ndigits;
+ while (*gs->grouping != CHAR_MAX) {
+ if (gs->lead <= *gs->grouping)
+ break;
+ gs->lead -= *gs->grouping;
+ if (*(gs->grouping+1)) {
+ gs->nseps++;
+ gs->grouping++;
+ } else
+ gs->nrepeats++;
+ }
+ return (gs->nseps + gs->nrepeats);
+}
+
+/*
+ * Print a number with thousands' separators.
+ */
+static int
+grouping_print(struct grouping_state *gs, struct io_state *iop,
+ const CHAR *cp, const CHAR *ep)
+{
+ const CHAR *cp0 = cp;
+
+ if (io_printandpad(iop, cp, ep, gs->lead, zeroes))
+ return (-1);
+ cp += gs->lead;
+ while (gs->nseps > 0 || gs->nrepeats > 0) {
+ if (gs->nrepeats > 0)
+ gs->nrepeats--;
+ else {
+ gs->grouping--;
+ gs->nseps--;
+ }
+ if (io_print(iop, &gs->thousands_sep, 1))
+ return (-1);
+ if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes))
+ return (-1);
+ cp += *gs->grouping;
+ }
+ if (cp > ep)
+ cp = ep;
+ return (cp - cp0);
+}
+
+
+/*
+ * Flush out all the vectors defined by the given uio,
+ * then reset it so that it can be reused.
+ *
+ * XXX The fact that we do this a character at a time and convert to a
+ * multibyte character sequence even if the destination is a wide
+ * string eclipses the benefits of buffering.
+ */
+static int
+__sprint(FILE *fp, struct __suio *uio)
+{
+ struct __siov *iov;
+ wchar_t *p;
+ int i, len;
+
+ iov = uio->uio_iov;
+ for (; uio->uio_resid != 0; uio->uio_resid -= len, iov++) {
+ p = (wchar_t *)iov->iov_base;
+ len = iov->iov_len;
+ for (i = 0; i < len; i++) {
+ if (__xfputwc(p[i], fp) == WEOF)
+ return (-1);
+ }
+ }
+ uio->uio_iovcnt = 0;
+ return (0);
+}
+
/*
* Helper function for `fprintf to unbuffered unix file': creates a
* temporary buffer. We only work on write-only files; this avoids
@@ -86,6 +211,10 @@ __sbprintf(FILE *fp, const wchar_t *fmt, va_list ap)
FILE fake;
unsigned char buf[BUFSIZ];
+ /* XXX This is probably not needed. */
+ if (prepwrite(fp) != 0)
+ return (EOF);
+
/* copy the important variables */
fake._flags = fp->_flags & ~__SNBF;
fake._file = fp->_file;
@@ -115,7 +244,6 @@ __sbprintf(FILE *fp, const wchar_t *fmt, va_list ap)
static wint_t
__xfputwc(wchar_t wc, FILE *fp)
{
- static const mbstate_t initial;
mbstate_t mbs;
char buf[MB_LEN_MAX];
struct __suio uio;
@@ -125,7 +253,7 @@ __xfputwc(wchar_t wc, FILE *fp)
if ((fp->_flags & __SSTR) == 0)
return (__fputwc(wc, fp));
- mbs = initial;
+ mbs = initial_mbs;
if ((len = wcrtomb(buf, wc, &mbs)) == (size_t)-1) {
fp->_flags |= __SERR;
return (WEOF);
@@ -139,160 +267,6 @@ __xfputwc(wchar_t wc, FILE *fp)
}
/*
- * Convert an unsigned long to ASCII for printf purposes, returning
- * a pointer to the first character of the string representation.
- * Octal numbers can be forced to have a leading zero; hex numbers
- * use the given digits.
- */
-static wchar_t *
-__ultoa(u_long val, wchar_t *endp, int base, int octzero, const char *xdigs,
- int needgrp, char thousep, const char *grp)
-{
- wchar_t *cp = endp;
- long sval;
- int ndig;
-
- /*
- * Handle the three cases separately, in the hope of getting
- * better/faster code.
- */
- switch (base) {
- case 10:
- if (val < 10) { /* many numbers are 1 digit */
- *--cp = to_char(val);
- return (cp);
- }
- ndig = 0;
- /*
- * On many machines, unsigned arithmetic is harder than
- * signed arithmetic, so we do at most one unsigned mod and
- * divide; this is sufficient to reduce the range of
- * the incoming value to where signed arithmetic works.
- */
- if (val > LONG_MAX) {
- *--cp = to_char(val % 10);
- ndig++;
- sval = val / 10;
- } else
- sval = val;
- do {
- *--cp = to_char(sval % 10);
- ndig++;
- /*
- * If (*grp == CHAR_MAX) then no more grouping
- * should be performed.
- */
- if (needgrp && ndig == *grp && *grp != CHAR_MAX
- && sval > 9) {
- *--cp = thousep;
- ndig = 0;
- /*
- * If (*(grp+1) == '\0') then we have to
- * use *grp character (last grouping rule)
- * for all next cases
- */
- if (*(grp+1) != '\0')
- grp++;
- }
- sval /= 10;
- } while (sval != 0);
- break;
-
- case 8:
- do {
- *--cp = to_char(val & 7);
- val >>= 3;
- } while (val);
- if (octzero && *cp != '0')
- *--cp = '0';
- break;
-
- case 16:
- do {
- *--cp = xdigs[val & 15];
- val >>= 4;
- } while (val);
- break;
-
- default: /* oops */
- abort();
- }
- return (cp);
-}
-
-/* Identical to __ultoa, but for intmax_t. */
-static wchar_t *
-__ujtoa(uintmax_t val, wchar_t *endp, int base, int octzero,
- const char *xdigs, int needgrp, char thousep, const char *grp)
-{
- wchar_t *cp = endp;
- intmax_t sval;
- int ndig;
-
- /* quick test for small values; __ultoa is typically much faster */
- /* (perhaps instead we should run until small, then call __ultoa?) */
- if (val <= ULONG_MAX)
- return (__ultoa((u_long)val, endp, base, octzero, xdigs,
- needgrp, thousep, grp));
- switch (base) {
- case 10:
- if (val < 10) {
- *--cp = to_char(val % 10);
- return (cp);
- }
- ndig = 0;
- if (val > INTMAX_MAX) {
- *--cp = to_char(val % 10);
- ndig++;
- sval = val / 10;
- } else
- sval = val;
- do {
- *--cp = to_char(sval % 10);
- ndig++;
- /*
- * If (*grp == CHAR_MAX) then no more grouping
- * should be performed.
- */
- if (needgrp && *grp != CHAR_MAX && ndig == *grp
- && sval > 9) {
- *--cp = thousep;
- ndig = 0;
- /*
- * If (*(grp+1) == '\0') then we have to
- * use *grp character (last grouping rule)
- * for all next cases
- */
- if (*(grp+1) != '\0')
- grp++;
- }
- sval /= 10;
- } while (sval != 0);
- break;
-
- case 8:
- do {
- *--cp = to_char(val & 7);
- val >>= 3;
- } while (val);
- if (octzero && *cp != '0')
- *--cp = '0';
- break;
-
- case 16:
- do {
- *--cp = xdigs[val & 15];
- val >>= 4;
- } while (val);
- break;
-
- default:
- abort();
- }
- return (cp);
-}
-
-/*
* Convert a multibyte character string argument for the %s format to a wide
* string representation. ``prec'' specifies the maximum number of bytes
* to output. If ``prec'' is greater than or equal to zero, we can't assume
@@ -301,7 +275,6 @@ __ujtoa(uintmax_t val, wchar_t *endp, int base, int octzero,
static wchar_t *
__mbsconv(char *mbsarg, int prec)
{
- static const mbstate_t initial;
mbstate_t mbs;
wchar_t *convbuf, *wcp;
const char *p;
@@ -321,7 +294,7 @@ __mbsconv(char *mbsarg, int prec)
*/
p = mbsarg;
insize = nchars = 0;
- mbs = initial;
+ mbs = initial_mbs;
while (nchars != (size_t)prec) {
nconv = mbrlen(p, MB_CUR_MAX, &mbs);
if (nconv == 0 || nconv == (size_t)-1 ||
@@ -348,7 +321,7 @@ __mbsconv(char *mbsarg, int prec)
return (NULL);
wcp = convbuf;
p = mbsarg;
- mbs = initial;
+ mbs = initial_mbs;
while (insize != 0) {
nconv = mbrtowc(wcp, p, insize, &mbs);
if (nconv == 0 || nconv == (size_t)-1 || nconv == (size_t)-2)
@@ -376,35 +349,26 @@ vfwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt0, va_list ap)
int ret;
FLOCKFILE(fp);
- ret = __vfwprintf(fp, fmt0, ap);
+ /* optimise fprintf(stderr) (and other unbuffered Unix files) */
+ if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
+ fp->_file >= 0)
+ ret = __sbprintf(fp, fmt0, ap);
+ else
+ ret = __vfwprintf(fp, fmt0, ap);
FUNLOCKFILE(fp);
return (ret);
}
-#ifndef NO_FLOATING_POINT
-
-#define dtoa __dtoa
-#define freedtoa __freedtoa
-
-#include <float.h>
-#include <math.h>
-#include "floatio.h"
-#include "gdtoa.h"
-
-#define DEFPREC 6
-
-static int exponent(wchar_t *, int, wchar_t);
-
-#endif /* !NO_FLOATING_POINT */
-
/*
* The size of the buffer we use as scratch space for integer
- * conversions, among other things. Technically, we would need the
- * most space for base 10 conversions with thousands' grouping
- * characters between each pair of digits. 100 bytes is a
- * conservative overestimate even for a 128-bit uintmax_t.
+ * conversions, among other things. We need enough space to
+ * write a uintmax_t in octal (plus one byte).
*/
-#define BUF 100
+#if UINTMAX_MAX <= UINT64_MAX
+#define BUF 32
+#else
+#error "BUF must be large enough to format a uintmax_t"
+#endif
/*
* Non-MT-safe version
@@ -414,15 +378,14 @@ __vfwprintf(FILE *fp, const wchar_t *fmt0, va_list ap)
{
wchar_t *fmt; /* format string */
wchar_t ch; /* character from fmt */
- int n, n2, n3; /* handy integer (short term usage) */
+ int n, n2; /* handy integer (short term usage) */
wchar_t *cp; /* handy char pointer (short term usage) */
int flags; /* flags as above */
int ret; /* return value accumulator */
int width; /* width from format (%8d), or 0 */
int prec; /* precision from format; <0 for N/A */
wchar_t sign; /* sign prefix (' ', '+', '-', or \0) */
- char thousands_sep; /* locale specific thousands separator */
- const char *grouping; /* locale specific numeric grouping rules */
+ struct grouping_state gs; /* thousands' grouping info */
#ifndef NO_FLOATING_POINT
/*
* We can decompose the printed representation of floating
@@ -438,7 +401,7 @@ __vfwprintf(FILE *fp, const wchar_t *fmt0, va_list ap)
* D: expchar holds this character; '\0' if no exponent, e.g. %f
* F: at least two digits for decimal, at least one digit for hex
*/
- char *decimal_point; /* locale specific decimal point */
+ wchar_t decimal_point; /* locale specific decimal point */
int signflag; /* true if float is negative */
union { /* floating point arguments %[aAeEfFgG] */
double dbl;
@@ -448,12 +411,9 @@ __vfwprintf(FILE *fp, const wchar_t *fmt0, va_list ap)
char expchar; /* exponent character: [eEpP\0] */
char *dtoaend; /* pointer to end of converted digits */
int expsize; /* character count for expstr */
- int lead; /* sig figs before decimal or group sep */
int ndig; /* actual number of digits returned by dtoa */
wchar_t expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */
char *dtoaresult; /* buffer allocated by dtoa */
- int nseps; /* number of group separators with ' */
- int nrepeats; /* number of repeats of the last group */
#endif
u_long ulval; /* integer arguments %[diouxX] */
uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */
@@ -463,6 +423,7 @@ __vfwprintf(FILE *fp, const wchar_t *fmt0, va_list ap)
int size; /* size of converted field or string */
int prsize; /* max size of printed field */
const char *xdigs; /* digits for [xX] conversion */
+ struct io_state io; /* I/O buffering state */
wchar_t buf[BUF]; /* buffer with space for digits of uintmax_t */
wchar_t ox[2]; /* space for 0x hex-prefix */
union arg *argtable; /* args, built due to positional arg */
@@ -471,45 +432,26 @@ __vfwprintf(FILE *fp, const wchar_t *fmt0, va_list ap)
va_list orgap; /* original argument pointer */
wchar_t *convbuf; /* multibyte to wide conversion result */
- /*
- * Choose PADSIZE to trade efficiency vs. size. If larger printf
- * fields occur frequently, increase PADSIZE and make the initialisers
- * below longer.
- */
-#define PADSIZE 16 /* pad chunk size */
- static wchar_t blanks[PADSIZE] =
- {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
- static wchar_t zeroes[PADSIZE] =
- {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
-
static const char xdigs_lower[16] = "0123456789abcdef";
static const char xdigs_upper[16] = "0123456789ABCDEF";
- /*
- * BEWARE, these `goto error' on error, PRINT uses `n2' and
- * PAD uses `n'.
- */
+ /* BEWARE, these `goto error' on error. */
#define PRINT(ptr, len) do { \
- for (n3 = 0; n3 < (len); n3++) \
- __xfputwc((ptr)[n3], fp); \
+ if (io_print(&io, (ptr), (len))) \
+ goto error; \
} while (0)
-#define PAD(howmany, with) do { \
- if ((n = (howmany)) > 0) { \
- while (n > PADSIZE) { \
- PRINT(with, PADSIZE); \
- n -= PADSIZE; \
- } \
- PRINT(with, n); \
- } \
-} while (0)
-#define PRINTANDPAD(p, ep, len, with) do { \
- n2 = (ep) - (p); \
- if (n2 > (len)) \
- n2 = (len); \
- if (n2 > 0) \
- PRINT((p), n2); \
- PAD((len) - (n2 > 0 ? n2 : 0), (with)); \
-} while(0)
+#define PAD(howmany, with) { \
+ if (io_pad(&io, (howmany), (with))) \
+ goto error; \
+}
+#define PRINTANDPAD(p, ep, len, with) { \
+ if (io_printandpad(&io, (p), (ep), (len), (with))) \
+ goto error; \
+}
+#define FLUSH() { \
+ if (io_flush(&io)) \
+ goto error; \
+}
/*
* Get the argument indexed by nextarg. If the argument table is
@@ -579,21 +521,15 @@ __vfwprintf(FILE *fp, const wchar_t *fmt0, va_list ap)
if (prepwrite(fp) != 0)
return (EOF);
- /* optimise fprintf(stderr) (and other unbuffered Unix files) */
- if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
- fp->_file >= 0)
- return (__sbprintf(fp, fmt0, ap));
-
- thousands_sep = '\0';
- grouping = NULL;
convbuf = NULL;
fmt = (wchar_t *)fmt0;
argtable = NULL;
nextarg = 1;
va_copy(orgap, ap);
+ io_init(&io, fp);
ret = 0;
#ifndef NO_FLOATING_POINT
- decimal_point = localeconv()->decimal_point;
+ decimal_point = get_decpt();
#endif
/*
@@ -618,6 +554,7 @@ __vfwprintf(FILE *fp, const wchar_t *fmt0, va_list ap)
dprec = 0;
width = 0;
prec = -1;
+ gs.grouping = NULL;
sign = '\0';
ox[1] = '\0';
@@ -655,8 +592,6 @@ reswitch: switch (ch) {
goto rflag;
case '\'':
flags |= GROUPING;
- thousands_sep = *(localeconv()->thousands_sep);
- grouping = localeconv()->grouping;
goto rflag;
case '.':
if ((ch = *fmt++) == '*') {
@@ -880,23 +815,8 @@ fp_common:
/* space for decimal pt and following digits */
if (prec || flags & ALT)
size += prec + 1;
- if (grouping && expt > 0) {
- /* space for thousands' grouping */
- nseps = nrepeats = 0;
- lead = expt;
- while (*grouping != CHAR_MAX) {
- if (lead <= *grouping)
- break;
- lead -= *grouping;
- if (*(grouping+1)) {
- nseps++;
- grouping++;
- } else
- nrepeats++;
- }
- size += nseps + nrepeats;
- } else
- lead = expt;
+ if ((flags & GROUPING) && expt > 0)
+ size += grouping_init(&gs, expt);
}
break;
#endif /* !NO_FLOATING_POINT */
@@ -1040,20 +960,18 @@ number: if ((dprec = prec) >= 0)
if (ujval != 0 || prec != 0 ||
(flags & ALT && base == 8))
cp = __ujtoa(ujval, cp, base,
- flags & ALT, xdigs,
- flags & GROUPING, thousands_sep,
- grouping);
+ flags & ALT, xdigs);
} else {
if (ulval != 0 || prec != 0 ||
(flags & ALT && base == 8))
cp = __ultoa(ulval, cp, base,
- flags & ALT, xdigs,
- flags & GROUPING, thousands_sep,
- grouping);
+ flags & ALT, xdigs);
}
size = buf + BUF - cp;
if (size > BUF) /* should never happen */
abort();
+ if ((flags & GROUPING) && size != 0)
+ size += grouping_init(&gs, size);
break;
default: /* "%?" prints ?, unless ? is NUL */
if (ch == '\0')
@@ -1109,53 +1027,48 @@ number: if ((dprec = prec) >= 0)
if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
PAD(width - realsz, zeroes);
- /* leading zeroes from decimal precision */
- PAD(dprec - size, zeroes);
-
/* the string or number proper */
#ifndef NO_FLOATING_POINT
if ((flags & FPT) == 0) {
- PRINT(cp, size);
+#endif
+ /* leading zeroes from decimal precision */
+ PAD(dprec - size, zeroes);
+ if (gs.grouping) {
+ if (grouping_print(&gs, &io, cp, buf+BUF) < 0)
+ goto error;
+ } else {
+ PRINT(cp, size);
+ }
+#ifndef NO_FLOATING_POINT
} else { /* glue together f_p fragments */
if (!expchar) { /* %[fF] or sufficiently short %[gG] */
if (expt <= 0) {
PRINT(zeroes, 1);
if (prec || flags & ALT)
- PRINT(decimal_point, 1);
+ PRINT(&decimal_point, 1);
PAD(-expt, zeroes);
/* already handled initial 0's */
prec += expt;
} else {
- PRINTANDPAD(cp, convbuf + ndig, lead, zeroes);
- cp += lead;
- if (grouping) {
- while (nseps>0 || nrepeats>0) {
- if (nrepeats > 0)
- nrepeats--;
- else {
- grouping--;
- nseps--;
- }
- PRINT(&thousands_sep,
- 1);
- PRINTANDPAD(cp,
- convbuf + ndig,
- *grouping, zeroes);
- cp += *grouping;
- }
- if (cp > convbuf + ndig)
- cp = convbuf + ndig;
- }
- if (prec || flags & ALT) {
- buf[0] = *decimal_point;
- PRINT(buf, 1);
+ if (gs.grouping) {
+ n = grouping_print(&gs, &io,
+ cp, convbuf + ndig);
+ if (n < 0)
+ goto error;
+ cp += n;
+ } else {
+ PRINTANDPAD(cp, convbuf + ndig,
+ expt, zeroes);
+ cp += expt;
}
+ if (prec || flags & ALT)
+ PRINT(&decimal_point, 1);
}
PRINTANDPAD(cp, convbuf + ndig, prec, zeroes);
} else { /* %[eE] or sufficiently long %[gG] */
if (prec > 1 || flags & ALT) {
buf[0] = *cp++;
- buf[1] = *decimal_point;
+ buf[1] = decimal_point;
PRINT(buf, 2);
PRINT(cp, ndig-1);
PAD(prec - ndig, zeroes);
@@ -1164,8 +1077,6 @@ number: if ((dprec = prec) >= 0)
PRINT(expstr, expsize);
}
}
-#else
- PRINT(cp, size);
#endif
/* left-adjusting padding (always blank) */
if (flags & LADJUST)
@@ -1173,8 +1084,11 @@ number: if ((dprec = prec) >= 0)
/* finally, adjust ret */
ret += prsize;
+
+ FLUSH(); /* copy out the I/O vectors */
}
done:
+ FLUSH();
error:
va_end(orgap);
if (convbuf != NULL)
@@ -1186,43 +1100,3 @@ error:
return (ret);
/* NOTREACHED */
}
-
-
-#ifndef NO_FLOATING_POINT
-
-static int
-exponent(wchar_t *p0, int exp, wchar_t fmtch)
-{
- wchar_t *p, *t;
- wchar_t expbuf[MAXEXPDIG];
-
- p = p0;
- *p++ = fmtch;
- if (exp < 0) {
- exp = -exp;
- *p++ = '-';
- }
- else
- *p++ = '+';
- t = expbuf + MAXEXPDIG;
- if (exp > 9) {
- do {
- *--t = to_char(exp % 10);
- } while ((exp /= 10) > 9);
- *--t = to_char(exp);
- for (; t < expbuf + MAXEXPDIG; *p++ = *t++);
- }
- else {
- /*
- * Exponents for decimal floating point conversions
- * (%[eEgG]) must be at least two characters long,
- * whereas exponents for hexadecimal conversions can
- * be only one character long.
- */
- if (fmtch == 'e' || fmtch == 'E')
- *p++ = '0';
- *p++ = to_char(exp);
- }
- return (p - p0);
-}
-#endif /* !NO_FLOATING_POINT */
diff --git a/lib/libc/stdio/vfwscanf.c b/lib/libc/stdio/vfwscanf.c
index 8a62a8f7..60c7c71 100644
--- a/lib/libc/stdio/vfwscanf.c
+++ b/lib/libc/stdio/vfwscanf.c
@@ -103,6 +103,8 @@ static int parsefloat(FILE *, wchar_t *, wchar_t *);
(cclcompl ? (wmemchr(ccls, (_c), ccle - ccls) == NULL) : \
(wmemchr(ccls, (_c), ccle - ccls) != NULL))
+static const mbstate_t initial_mbs;
+
/*
* MT-safe version.
*/
@@ -142,7 +144,6 @@ __vfwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, va_list ap)
char *mbp; /* multibyte string pointer for %c %s %[ */
size_t nconv; /* number of bytes in mb. conversion */
char mbbuf[MB_LEN_MAX]; /* temporary mb. character buffer */
- static const mbstate_t initial;
mbstate_t mbs;
/* `basefix' is used to avoid `if' tests in the integer scanner */
@@ -375,7 +376,7 @@ literal:
if (!(flags & SUPPRESS))
mbp = va_arg(ap, char *);
n = 0;
- mbs = initial;
+ mbs = initial_mbs;
while (width != 0 &&
(wi = __fgetwc(fp)) != WEOF) {
if (width >= MB_CUR_MAX &&
@@ -440,7 +441,7 @@ literal:
if (!(flags & SUPPRESS))
mbp = va_arg(ap, char *);
n = 0;
- mbs = initial;
+ mbs = initial_mbs;
while ((wi = __fgetwc(fp)) != WEOF &&
width != 0 && INCCL(wi)) {
if (width >= MB_CUR_MAX &&
@@ -501,7 +502,7 @@ literal:
} else {
if (!(flags & SUPPRESS))
mbp = va_arg(ap, char *);
- mbs = initial;
+ mbs = initial_mbs;
while ((wi = __fgetwc(fp)) != WEOF &&
width != 0 &&
!iswspace(wi)) {
@@ -721,16 +722,23 @@ match_failure:
static int
parsefloat(FILE *fp, wchar_t *buf, wchar_t *end)
{
+ mbstate_t mbs;
+ size_t nconv;
wchar_t *commit, *p;
int infnanpos = 0;
enum {
- S_START, S_GOTSIGN, S_INF, S_NAN, S_MAYBEHEX,
+ S_START, S_GOTSIGN, S_INF, S_NAN, S_DONE, S_MAYBEHEX,
S_DIGITS, S_FRAC, S_EXP, S_EXPDIGITS
} state = S_START;
wchar_t c;
- wchar_t decpt = (wchar_t)(unsigned char)*localeconv()->decimal_point;
+ wchar_t decpt;
_Bool gotmantdig = 0, ishex = 0;
+ mbs = initial_mbs;
+ nconv = mbrtowc(&decpt, localeconv()->decimal_point, MB_CUR_MAX, &mbs);
+ if (nconv == (size_t)-1 || nconv == (size_t)-2)
+ decpt = '.'; /* failsafe */
+
/*
* We set commit = p whenever the string we have read so far
* constitutes a valid representation of a floating point
@@ -783,8 +791,6 @@ reswitch:
break;
case S_NAN:
switch (infnanpos) {
- case -1: /* XXX kludge to deal with nan(...) */
- goto parsedone;
case 0:
if (c != 'A' && c != 'a')
goto parsedone;
@@ -802,13 +808,15 @@ reswitch:
default:
if (c == ')') {
commit = p;
- infnanpos = -2;
+ state = S_DONE;
} else if (!iswalnum(c) && c != '_')
goto parsedone;
break;
}
infnanpos++;
break;
+ case S_DONE:
+ goto parsedone;
case S_MAYBEHEX:
state = S_DIGITS;
if (c == 'X' || c == 'x') {
diff --git a/lib/libc/stdio/vswscanf.c b/lib/libc/stdio/vswscanf.c
index 67bfb47..8a70d44 100644
--- a/lib/libc/stdio/vswscanf.c
+++ b/lib/libc/stdio/vswscanf.c
@@ -66,6 +66,7 @@ vswscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt,
char *mbstr;
size_t mlen;
int r;
+ const wchar_t *strp;
/*
* XXX Convert the wide character string to multibyte, which
@@ -74,7 +75,8 @@ vswscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt,
if ((mbstr = malloc(wcslen(str) * MB_CUR_MAX + 1)) == NULL)
return (EOF);
mbs = initial;
- if ((mlen = wcsrtombs(mbstr, &str, SIZE_T_MAX, &mbs)) == (size_t)-1) {
+ strp = str;
+ if ((mlen = wcsrtombs(mbstr, &strp, SIZE_T_MAX, &mbs)) == (size_t)-1) {
free(mbstr);
return (EOF);
}
diff --git a/lib/libc/stdio/wsetup.c b/lib/libc/stdio/wsetup.c
index a5da23f..37bfc58 100644
--- a/lib/libc/stdio/wsetup.c
+++ b/lib/libc/stdio/wsetup.c
@@ -60,6 +60,7 @@ __swsetup(fp)
if ((fp->_flags & __SWR) == 0) {
if ((fp->_flags & __SRW) == 0) {
errno = EBADF;
+ fp->_flags |= __SERR;
return (EOF);
}
if (fp->_flags & __SRD) {
diff --git a/lib/libc/string/Makefile.inc b/lib/libc/string/Makefile.inc
index 7fddae4..dffaf87 100644
--- a/lib/libc/string/Makefile.inc
+++ b/lib/libc/string/Makefile.inc
@@ -35,34 +35,45 @@ MAN+= bcmp.3 bcopy.3 bstring.3 bzero.3 ffs.3 index.3 memccpy.3 memchr.3 \
strspn.3 strstr.3 strtok.3 strxfrm.3 swab.3 wcscoll.3 wcstok.3 \
wcswidth.3 wcsxfrm.3 wmemchr.3
-MLINKS+=ffs.3 ffsl.3
-MLINKS+=ffs.3 fls.3
-MLINKS+=ffs.3 flsl.3
-MLINKS+=ffs.3 ffsll.3
-MLINKS+=ffs.3 flsll.3
+MLINKS+=ffs.3 ffsl.3 \
+ ffs.3 ffsll.3 \
+ ffs.3 fls.3 \
+ ffs.3 flsl.3 \
+ ffs.3 flsll.3
MLINKS+=index.3 rindex.3
MLINKS+=memchr.3 memrchr.3
MLINKS+=strcasecmp.3 strncasecmp.3
MLINKS+=strcat.3 strncat.3
MLINKS+=strchr.3 strrchr.3
MLINKS+=strcmp.3 strncmp.3
-MLINKS+=strcpy.3 stpcpy.3
+MLINKS+=strcpy.3 stpcpy.3 \
+ strcpy.3 strncpy.3
MLINKS+=strdup.3 strndup.3
-MLINKS+=strcpy.3 strncpy.3
-MLINKS+=strerror.3 perror.3 strerror.3 sys_errlist.3 strerror.3 sys_nerr.3
-MLINKS+=strerror.3 strerror_r.3
+MLINKS+=strerror.3 perror.3 \
+ strerror.3 strerror_r.3 \
+ strerror.3 sys_errlist.3 \
+ strerror.3 sys_nerr.3
MLINKS+=strlcpy.3 strlcat.3
+MLINKS+=strstr.3 strcasestr.3 \
+ strstr.3 strnstr.3
MLINKS+=strtok.3 strtok_r.3
-MLINKS+=strstr.3 strcasestr.3
-MLINKS+=strstr.3 strnstr.3
-MLINKS+=wmemchr.3 wmemcmp.3 wmemchr.3 wmemcpy.3 \
- wmemchr.3 wmemmove.3 wmemchr.3 wmemset.3 \
- wmemchr.3 wcscat.3 wmemchr.3 wcschr.3 \
- wmemchr.3 wcscmp.3 wmemchr.3 wcscpy.3 \
- wmemchr.3 wcscspn.3 wmemchr.3 wcsdup.3 \
+MLINKS+=wmemchr.3 wcscat.3 \
+ wmemchr.3 wcschr.3 \
+ wmemchr.3 wcscmp.3 \
+ wmemchr.3 wcscpy.3 \
+ wmemchr.3 wcscspn.3 \
+ wmemchr.3 wcsdup.3 \
wmemchr.3 wcslcat.3 \
- wmemchr.3 wcslcpy.3 wmemchr.3 wcslen.3 \
- wmemchr.3 wcsncat.3 wmemchr.3 wcsncmp.3 \
- wmemchr.3 wcsncpy.3 wmemchr.3 wcspbrk.3 \
- wmemchr.3 wcsrchr.3 wmemchr.3 wcsspn.3 \
- wmemchr.3 wcsstr.3
+ wmemchr.3 wcslcpy.3 \
+ wmemchr.3 wcslen.3 \
+ wmemchr.3 wcsncat.3 \
+ wmemchr.3 wcsncmp.3 \
+ wmemchr.3 wcsncpy.3 \
+ wmemchr.3 wcspbrk.3 \
+ wmemchr.3 wcsrchr.3 \
+ wmemchr.3 wcsspn.3 \
+ wmemchr.3 wcsstr.3 \
+ wmemchr.3 wmemcmp.3 \
+ wmemchr.3 wmemcpy.3 \
+ wmemchr.3 wmemmove.3 \
+ wmemchr.3 wmemset.3
diff --git a/lib/libc/string/ffs.3 b/lib/libc/string/ffs.3
index e66d7eb..acb1ac8 100644
--- a/lib/libc/string/ffs.3
+++ b/lib/libc/string/ffs.3
@@ -108,4 +108,4 @@ The
and
.Fn flsll
functions appeared in
-.Fx 8.0 .
+.Fx 7.1 .
diff --git a/lib/libc/string/memccpy.c b/lib/libc/string/memccpy.c
index 5b4223e..539d33e 100644
--- a/lib/libc/string/memccpy.c
+++ b/lib/libc/string/memccpy.c
@@ -36,11 +36,7 @@ __FBSDID("$FreeBSD$");
#include <string.h>
void *
-memccpy(t, f, c, n)
- void *t;
- const void *f;
- int c;
- size_t n;
+memccpy(void *t, const void *f, int c, size_t n)
{
if (n) {
diff --git a/lib/libc/string/memchr.c b/lib/libc/string/memchr.c
index 2b1231d..6d7c2fd 100644
--- a/lib/libc/string/memchr.c
+++ b/lib/libc/string/memchr.c
@@ -39,10 +39,7 @@ __FBSDID("$FreeBSD$");
#include <string.h>
void *
-memchr(s, c, n)
- const void *s;
- unsigned char c;
- size_t n;
+memchr(const void *s, int c, size_t n)
{
if (n != 0) {
const unsigned char *p = s;
diff --git a/lib/libc/string/memcmp.c b/lib/libc/string/memcmp.c
index d048068..4a1b66e 100644
--- a/lib/libc/string/memcmp.c
+++ b/lib/libc/string/memcmp.c
@@ -42,9 +42,7 @@ __FBSDID("$FreeBSD$");
* Compare memory regions.
*/
int
-memcmp(s1, s2, n)
- const void *s1, *s2;
- size_t n;
+memcmp(const void *s1, const void *s2, size_t n)
{
if (n != 0) {
const unsigned char *p1 = s1, *p2 = s2;
diff --git a/lib/libc/string/memmem.c b/lib/libc/string/memmem.c
index 0ac0a6d..72e6517 100644
--- a/lib/libc/string/memmem.c
+++ b/lib/libc/string/memmem.c
@@ -36,9 +36,7 @@ __FBSDID("$FreeBSD$");
*/
void *
-memmem(l, l_len, s, s_len)
- const void *l; size_t l_len;
- const void *s; size_t s_len;
+memmem(const void *l, size_t l_len, const void *s, size_t s_len)
{
register char *cur, *last;
const char *cl = (const char *)l;
diff --git a/lib/libc/string/strcasecmp.c b/lib/libc/string/strcasecmp.c
index 2efcf55..4a474fe 100644
--- a/lib/libc/string/strcasecmp.c
+++ b/lib/libc/string/strcasecmp.c
@@ -39,8 +39,7 @@ __FBSDID("$FreeBSD$");
typedef unsigned char u_char;
int
-strcasecmp(s1, s2)
- const char *s1, *s2;
+strcasecmp(const char *s1, const char *s2)
{
const u_char
*us1 = (const u_char *)s1,
@@ -53,9 +52,7 @@ strcasecmp(s1, s2)
}
int
-strncasecmp(s1, s2, n)
- const char *s1, *s2;
- size_t n;
+strncasecmp(const char *s1, const char *s2, size_t n)
{
if (n != 0) {
const u_char
diff --git a/lib/libc/string/strcasestr.c b/lib/libc/string/strcasestr.c
index b358b7d..9b28bf5 100644
--- a/lib/libc/string/strcasestr.c
+++ b/lib/libc/string/strcasestr.c
@@ -40,8 +40,7 @@ __FBSDID("$FreeBSD$");
* Find the first occurrence of find in s, ignore case.
*/
char *
-strcasestr(s, find)
- const char *s, *find;
+strcasestr(const char *s, const char *find)
{
char c, sc;
size_t len;
diff --git a/lib/libc/string/strcmp.c b/lib/libc/string/strcmp.c
index ab95333..95c778d 100644
--- a/lib/libc/string/strcmp.c
+++ b/lib/libc/string/strcmp.c
@@ -42,11 +42,10 @@ __FBSDID("$FreeBSD$");
* Compare strings.
*/
int
-strcmp(s1, s2)
- const char *s1, *s2;
+strcmp(const char *s1, const char *s2)
{
while (*s1 == *s2++)
- if (*s1++ == 0)
+ if (*s1++ == '\0')
return (0);
return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1));
}
diff --git a/lib/libc/string/strcoll.c b/lib/libc/string/strcoll.c
index a0daf8d..0da5c57 100644
--- a/lib/libc/string/strcoll.c
+++ b/lib/libc/string/strcoll.c
@@ -33,8 +33,7 @@ __FBSDID("$FreeBSD$");
#include "collate.h"
int
-strcoll(s, s2)
- const char *s, *s2;
+strcoll(const char *s, const char *s2)
{
int len, len2, prim, prim2, sec, sec2, ret, ret2;
const char *t, *t2;
diff --git a/lib/libc/string/strdup.c b/lib/libc/string/strdup.c
index c0b581d..570ad83 100644
--- a/lib/libc/string/strdup.c
+++ b/lib/libc/string/strdup.c
@@ -38,8 +38,7 @@ __FBSDID("$FreeBSD$");
#include <string.h>
char *
-strdup(str)
- const char *str;
+strdup(const char *str)
{
size_t len;
char *copy;
diff --git a/lib/libc/string/strlcat.c b/lib/libc/string/strlcat.c
index 7f19f6b..feeac3b 100644
--- a/lib/libc/string/strlcat.c
+++ b/lib/libc/string/strlcat.c
@@ -1,35 +1,21 @@
-/* $OpenBSD: strlcat.c,v 1.2 1999/06/17 16:28:58 millert Exp $ */
+/* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */
/*
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
- * All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
*
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static char *rcsid = "$OpenBSD: strlcat.c,v 1.2 1999/06/17 16:28:58 millert Exp $";
-#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -44,10 +30,7 @@ __FBSDID("$FreeBSD$");
* If retval >= siz, truncation occurred.
*/
size_t
-strlcat(dst, src, siz)
- char *dst;
- const char *src;
- size_t siz;
+strlcat(char *dst, const char *src, size_t siz)
{
char *d = dst;
const char *s = src;
diff --git a/lib/libc/string/strlcpy.3 b/lib/libc/string/strlcpy.3
index f674fe2..88af06d 100644
--- a/lib/libc/string/strlcpy.3
+++ b/lib/libc/string/strlcpy.3
@@ -1,18 +1,18 @@
-.\" $OpenBSD: strlcpy.3,v 1.5 1999/06/06 15:17:32 aaron Exp $
+.\" $OpenBSD: strlcpy.3,v 1.19 2007/05/31 19:19:32 jmc Exp $
.\"
-.\" Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
-.\" All rights reserved.
+.\" Copyright (c) 1998, 2000 Todd C. Miller <Todd.Miller@courtesan.com>
.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\" 3. The name of the author may not be used to endorse or promote products
-.\" derived from this software without specific prior written permission.
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
@@ -64,7 +64,7 @@ is larger than 0 or, in the case of
.Fn strlcat ,
as long as there is at least one byte free in
.Fa dst ) .
-Note that you should include a byte for the NUL in
+Note that a byte for the NUL should be included in
.Fa size .
Also note that
.Fn strlcpy
@@ -121,7 +121,7 @@ that means the initial length of
plus
the length of
.Fa src .
-While this may seem somewhat confusing it was done to make
+While this may seem somewhat confusing, it was done to make
truncation detection simple.
.Pp
Note however, that if
@@ -168,8 +168,8 @@ if (strlcat(pname, file, sizeof(pname)) >= sizeof(pname))
goto toolong;
.Ed
.Pp
-Since we know how many characters we copied the first time, we can
-speed things up a bit by using a copy instead of an append:
+Since it is known how many characters were copied the first time, things
+can be sped up a bit by using a copy instead of an append
.Bd -literal -offset indent
char *dir, *file, pname[MAXPATHLEN];
size_t n;
diff --git a/lib/libc/string/strlen.c b/lib/libc/string/strlen.c
index db4fe26..860a988 100644
--- a/lib/libc/string/strlen.c
+++ b/lib/libc/string/strlen.c
@@ -1,6 +1,6 @@
/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 2009 Xin LI <delphij@FreeBSD.org>
+ * All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,14 +10,11 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
*
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@@ -27,21 +24,87 @@
* SUCH DAMAGE.
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)strlen.c 8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <sys/limits.h>
+#include <sys/types.h>
#include <string.h>
+/*
+ * Portable strlen() for 32-bit and 64-bit systems.
+ *
+ * Rationale: it is generally much more efficient to do word length
+ * operations and avoid branches on modern computer systems, as
+ * compared to byte-length operations with a lot of branches.
+ *
+ * The expression:
+ *
+ * ((x - 0x01....01) & ~x & 0x80....80)
+ *
+ * would evaluate to a non-zero value iff any of the bytes in the
+ * original word is zero. However, we can further reduce ~1/3 of
+ * time if we consider that strlen() usually operate on 7-bit ASCII
+ * by employing the following expression, which allows false positive
+ * when high bit of 1 and use the tail case to catch these case:
+ *
+ * ((x - 0x01....01) & 0x80....80)
+ *
+ * This is more than 5.2 times as fast as the raw implementation on
+ * Intel T7300 under long mode for strings longer than word length.
+ */
+
+/* Magic numbers for the algorithm */
+#if LONG_BIT == 32
+static const unsigned long mask01 = 0x01010101;
+static const unsigned long mask80 = 0x80808080;
+#elif LONG_BIT == 64
+static const unsigned long mask01 = 0x0101010101010101;
+static const unsigned long mask80 = 0x8080808080808080;
+#else
+#error Unsupported word size
+#endif
+
+#define LONGPTR_MASK (sizeof(long) - 1)
+
+/*
+ * Helper macro to return string length if we caught the zero
+ * byte.
+ */
+#define testbyte(x) \
+ do { \
+ if (p[x] == '\0') \
+ return (p - str + x); \
+ } while (0)
+
size_t
-strlen(str)
- const char *str;
+strlen(const char *str)
{
- const char *s;
+ const char *p;
+ const unsigned long *lp;
+
+ /* Skip the first few bytes until we have an aligned p */
+ for (p = str; (uintptr_t)p & LONGPTR_MASK; p++)
+ if (*p == '\0')
+ return (p - str);
+
+ /* Scan the rest of the string using word sized operation */
+ for (lp = (const unsigned long *)p; ; lp++)
+ if ((*lp - mask01) & mask80) {
+ p = (const char *)(lp);
+ testbyte(0);
+ testbyte(1);
+ testbyte(2);
+ testbyte(3);
+#if (LONG_BIT >= 64)
+ testbyte(4);
+ testbyte(5);
+ testbyte(6);
+ testbyte(7);
+#endif
+ }
- for (s = str; *s; ++s);
- return(s - str);
+ /* NOTREACHED */
+ return (0);
}
diff --git a/lib/libc/string/strmode.c b/lib/libc/string/strmode.c
index be09d7a..57295d7 100644
--- a/lib/libc/string/strmode.c
+++ b/lib/libc/string/strmode.c
@@ -38,9 +38,7 @@ __FBSDID("$FreeBSD$");
#include <string.h>
void
-strmode(mode, p)
- mode_t mode;
- char *p;
+strmode(/* mode_t */ int mode, char *p)
{
/* print type */
switch (mode & S_IFMT) {
diff --git a/lib/libc/string/strncmp.c b/lib/libc/string/strncmp.c
index 659a7cb..5bc3d5e 100644
--- a/lib/libc/string/strncmp.c
+++ b/lib/libc/string/strncmp.c
@@ -36,9 +36,7 @@ __FBSDID("$FreeBSD$");
#include <string.h>
int
-strncmp(s1, s2, n)
- const char *s1, *s2;
- size_t n;
+strncmp(const char *s1, const char *s2, size_t n)
{
if (n == 0)
@@ -47,7 +45,7 @@ strncmp(s1, s2, n)
if (*s1 != *s2++)
return (*(const unsigned char *)s1 -
*(const unsigned char *)(s2 - 1));
- if (*s1++ == 0)
+ if (*s1++ == '\0')
break;
} while (--n != 0);
return (0);
diff --git a/lib/libc/string/strncpy.c b/lib/libc/string/strncpy.c
index 07b9166..980dbc7 100644
--- a/lib/libc/string/strncpy.c
+++ b/lib/libc/string/strncpy.c
@@ -50,10 +50,10 @@ strncpy(char * __restrict dst, const char * __restrict src, size_t n)
const char *s = src;
do {
- if ((*d++ = *s++) == 0) {
+ if ((*d++ = *s++) == '\0') {
/* NUL pad the remaining n-1 bytes */
while (--n != 0)
- *d++ = 0;
+ *d++ = '\0';
break;
}
} while (--n != 0);
diff --git a/lib/libc/string/strnstr.c b/lib/libc/string/strnstr.c
index bbb1ca6..45be95d 100644
--- a/lib/libc/string/strnstr.c
+++ b/lib/libc/string/strnstr.c
@@ -44,10 +44,7 @@ __FBSDID("$FreeBSD$");
* first slen characters of s.
*/
char *
-strnstr(s, find, slen)
- const char *s;
- const char *find;
- size_t slen;
+strnstr(const char *s, const char *find, size_t slen)
{
char c, sc;
size_t len;
diff --git a/lib/libc/string/strpbrk.c b/lib/libc/string/strpbrk.c
index efbdc8a..2069bee 100644
--- a/lib/libc/string/strpbrk.c
+++ b/lib/libc/string/strpbrk.c
@@ -39,14 +39,13 @@ __FBSDID("$FreeBSD$");
* Find the first occurrence in s1 of a character in s2 (excluding NUL).
*/
char *
-strpbrk(s1, s2)
- const char *s1, *s2;
+strpbrk(const char *s1, const char *s2)
{
const char *scanp;
int c, sc;
while ((c = *s1++) != 0) {
- for (scanp = s2; (sc = *scanp++) != 0;)
+ for (scanp = s2; (sc = *scanp++) != '\0';)
if (sc == c)
return ((char *)(s1 - 1));
}
diff --git a/lib/libc/string/strsep.c b/lib/libc/string/strsep.c
index 0850b0b..670ab04 100644
--- a/lib/libc/string/strsep.c
+++ b/lib/libc/string/strsep.c
@@ -48,9 +48,7 @@ __FBSDID("$FreeBSD$");
* If *stringp is NULL, strsep returns NULL.
*/
char *
-strsep(stringp, delim)
- char **stringp;
- const char *delim;
+strsep(char **stringp, const char *delim)
{
char *s;
const char *spanp;
diff --git a/lib/libc/string/strstr.c b/lib/libc/string/strstr.c
index e2edd80..82b4c5a 100644
--- a/lib/libc/string/strstr.c
+++ b/lib/libc/string/strstr.c
@@ -42,17 +42,16 @@ __FBSDID("$FreeBSD$");
* Find the first occurrence of find in s.
*/
char *
-strstr(s, find)
- const char *s, *find;
+strstr(const char *s, const char *find)
{
char c, sc;
size_t len;
- if ((c = *find++) != 0) {
+ if ((c = *find++) != '\0') {
len = strlen(find);
do {
do {
- if ((sc = *s++) == 0)
+ if ((sc = *s++) == '\0')
return (NULL);
} while (sc != c);
} while (strncmp(s, find, len) != 0);
diff --git a/lib/libc/string/wcscat.c b/lib/libc/string/wcscat.c
index 1c96533..7ae4e80 100644
--- a/lib/libc/string/wcscat.c
+++ b/lib/libc/string/wcscat.c
@@ -37,9 +37,7 @@ __FBSDID("$FreeBSD$");
#include <wchar.h>
wchar_t *
-wcscat(s1, s2)
- wchar_t * __restrict s1;
- const wchar_t * __restrict s2;
+wcscat(wchar_t * __restrict s1, const wchar_t * __restrict s2)
{
wchar_t *cp;
diff --git a/lib/libc/string/wcscmp.c b/lib/libc/string/wcscmp.c
index 59c3eef..2d48914 100644
--- a/lib/libc/string/wcscmp.c
+++ b/lib/libc/string/wcscmp.c
@@ -45,12 +45,11 @@ __FBSDID("$FreeBSD$");
* Compare strings.
*/
int
-wcscmp(s1, s2)
- const wchar_t *s1, *s2;
+wcscmp(const wchar_t *s1, const wchar_t *s2)
{
while (*s1 == *s2++)
- if (*s1++ == 0)
+ if (*s1++ == '\0')
return (0);
/* XXX assumes wchar_t = int */
return (*(const unsigned int *)s1 - *(const unsigned int *)--s2);
diff --git a/lib/libc/string/wcscpy.c b/lib/libc/string/wcscpy.c
index 180bbd1..0c6e1f2 100644
--- a/lib/libc/string/wcscpy.c
+++ b/lib/libc/string/wcscpy.c
@@ -37,9 +37,7 @@ __FBSDID("$FreeBSD$");
#include <wchar.h>
wchar_t *
-wcscpy(s1, s2)
- wchar_t * __restrict s1;
- const wchar_t * __restrict s2;
+wcscpy(wchar_t * __restrict s1, const wchar_t * __restrict s2)
{
wchar_t *cp;
diff --git a/lib/libc/string/wcscspn.c b/lib/libc/string/wcscspn.c
index 57a804c..7729dc8 100644
--- a/lib/libc/string/wcscspn.c
+++ b/lib/libc/string/wcscspn.c
@@ -37,9 +37,7 @@ __FBSDID("$FreeBSD$");
#include <wchar.h>
size_t
-wcscspn(s, set)
- const wchar_t *s;
- const wchar_t *set;
+wcscspn(const wchar_t *s, const wchar_t *set)
{
const wchar_t *p;
const wchar_t *q;
diff --git a/lib/libc/string/wcslcat.c b/lib/libc/string/wcslcat.c
index 6466f06..f5f1e1e 100644
--- a/lib/libc/string/wcslcat.c
+++ b/lib/libc/string/wcslcat.c
@@ -46,10 +46,7 @@ __FBSDID("$FreeBSD$");
* truncation occurred.
*/
size_t
-wcslcat(dst, src, siz)
- wchar_t *dst;
- const wchar_t *src;
- size_t siz;
+wcslcat(wchar_t *dst, const wchar_t *src, size_t siz)
{
wchar_t *d = dst;
const wchar_t *s = src;
diff --git a/lib/libc/string/wcslcpy.c b/lib/libc/string/wcslcpy.c
index 1b9459a..b104a06 100644
--- a/lib/libc/string/wcslcpy.c
+++ b/lib/libc/string/wcslcpy.c
@@ -44,10 +44,7 @@ __FBSDID("$FreeBSD$");
* Returns wcslen(src); if retval >= siz, truncation occurred.
*/
size_t
-wcslcpy(dst, src, siz)
- wchar_t *dst;
- const wchar_t *src;
- size_t siz;
+wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz)
{
wchar_t *d = dst;
const wchar_t *s = src;
diff --git a/lib/libc/string/wcslen.c b/lib/libc/string/wcslen.c
index 1636d98..ca3004e 100644
--- a/lib/libc/string/wcslen.c
+++ b/lib/libc/string/wcslen.c
@@ -37,8 +37,7 @@ __FBSDID("$FreeBSD$");
#include <wchar.h>
size_t
-wcslen(s)
- const wchar_t *s;
+wcslen(const wchar_t *s)
{
const wchar_t *p;
diff --git a/lib/libc/string/wcsncat.c b/lib/libc/string/wcsncat.c
index ba49a9e..44f1ff9 100644
--- a/lib/libc/string/wcsncat.c
+++ b/lib/libc/string/wcsncat.c
@@ -37,10 +37,7 @@ __FBSDID("$FreeBSD$");
#include <wchar.h>
wchar_t *
-wcsncat(s1, s2, n)
- wchar_t * __restrict s1;
- const wchar_t * __restrict s2;
- size_t n;
+wcsncat(wchar_t * __restrict s1, const wchar_t * __restrict s2, size_t n)
{
wchar_t *p;
wchar_t *q;
diff --git a/lib/libc/string/wcsncmp.c b/lib/libc/string/wcsncmp.c
index 5b7b3ee..86d7a51 100644
--- a/lib/libc/string/wcsncmp.c
+++ b/lib/libc/string/wcsncmp.c
@@ -39,9 +39,7 @@ __FBSDID("$FreeBSD$");
#include <wchar.h>
int
-wcsncmp(s1, s2, n)
- const wchar_t *s1, *s2;
- size_t n;
+wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t n)
{
if (n == 0)
diff --git a/lib/libc/string/wcspbrk.c b/lib/libc/string/wcspbrk.c
index 7315c44..2ff71ba 100644
--- a/lib/libc/string/wcspbrk.c
+++ b/lib/libc/string/wcspbrk.c
@@ -37,9 +37,7 @@ __FBSDID("$FreeBSD$");
#include <wchar.h>
wchar_t *
-wcspbrk(s, set)
- const wchar_t *s;
- const wchar_t *set;
+wcspbrk(const wchar_t *s, const wchar_t *set)
{
const wchar_t *p;
const wchar_t *q;
diff --git a/lib/libc/string/wcsspn.c b/lib/libc/string/wcsspn.c
index 584a9d3..6569206 100644
--- a/lib/libc/string/wcsspn.c
+++ b/lib/libc/string/wcsspn.c
@@ -37,9 +37,7 @@ __FBSDID("$FreeBSD$");
#include <wchar.h>
size_t
-wcsspn(s, set)
- const wchar_t *s;
- const wchar_t *set;
+wcsspn(const wchar_t *s, const wchar_t *set)
{
const wchar_t *p;
const wchar_t *q;
diff --git a/lib/libc/string/wcsstr.c b/lib/libc/string/wcsstr.c
index b8a7598..a9dc27b 100644
--- a/lib/libc/string/wcsstr.c
+++ b/lib/libc/string/wcsstr.c
@@ -49,7 +49,7 @@ wcsstr(const wchar_t * __restrict s, const wchar_t * __restrict find)
wchar_t c, sc;
size_t len;
- if ((c = *find++) != 0) {
+ if ((c = *find++) != L'\0') {
len = wcslen(find);
do {
do {
diff --git a/lib/libc/string/wmemchr.c b/lib/libc/string/wmemchr.c
index 2d96708..cab89c9 100644
--- a/lib/libc/string/wmemchr.c
+++ b/lib/libc/string/wmemchr.c
@@ -37,10 +37,7 @@ __FBSDID("$FreeBSD$");
#include <wchar.h>
wchar_t *
-wmemchr(s, c, n)
- const wchar_t *s;
- wchar_t c;
- size_t n;
+wmemchr(const wchar_t *s, wchar_t c, size_t n)
{
size_t i;
diff --git a/lib/libc/string/wmemcmp.c b/lib/libc/string/wmemcmp.c
index c9a9095..fdb1f986 100644
--- a/lib/libc/string/wmemcmp.c
+++ b/lib/libc/string/wmemcmp.c
@@ -37,10 +37,7 @@ __FBSDID("$FreeBSD$");
#include <wchar.h>
int
-wmemcmp(s1, s2, n)
- const wchar_t *s1;
- const wchar_t *s2;
- size_t n;
+wmemcmp(const wchar_t *s1, const wchar_t *s2, size_t n)
{
size_t i;
diff --git a/lib/libc/string/wmemcpy.c b/lib/libc/string/wmemcpy.c
index 38d563d..c10770c 100644
--- a/lib/libc/string/wmemcpy.c
+++ b/lib/libc/string/wmemcpy.c
@@ -38,11 +38,7 @@ __FBSDID("$FreeBSD$");
#include <wchar.h>
wchar_t *
-wmemcpy(d, s, n)
- wchar_t * __restrict d;
- const wchar_t * __restrict s;
- size_t n;
+wmemcpy(wchar_t * __restrict d, const wchar_t * __restrict s, size_t n)
{
-
return (wchar_t *)memcpy(d, s, n * sizeof(wchar_t));
}
diff --git a/lib/libc/string/wmemmove.c b/lib/libc/string/wmemmove.c
index 6b3ee94..05cfd10 100644
--- a/lib/libc/string/wmemmove.c
+++ b/lib/libc/string/wmemmove.c
@@ -38,11 +38,7 @@ __FBSDID("$FreeBSD$");
#include <wchar.h>
wchar_t *
-wmemmove(d, s, n)
- wchar_t *d;
- const wchar_t *s;
- size_t n;
+wmemmove(wchar_t *d, const wchar_t *s, size_t n)
{
-
return (wchar_t *)memmove(d, s, n * sizeof(wchar_t));
}
diff --git a/lib/libc/string/wmemset.c b/lib/libc/string/wmemset.c
index b923f14..0e96356 100644
--- a/lib/libc/string/wmemset.c
+++ b/lib/libc/string/wmemset.c
@@ -37,10 +37,7 @@ __FBSDID("$FreeBSD$");
#include <wchar.h>
wchar_t *
-wmemset(s, c, n)
- wchar_t *s;
- wchar_t c;
- size_t n;
+wmemset(wchar_t *s, wchar_t c, size_t n)
{
size_t i;
wchar_t *p;
diff --git a/lib/libc/sys/jail.2 b/lib/libc/sys/jail.2
index f7b3912..cdf89dc 100644
--- a/lib/libc/sys/jail.2
+++ b/lib/libc/sys/jail.2
@@ -8,7 +8,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd November 29, 2008
+.Dd January 6, 2009
.Dt JAIL 2
.Os
.Sh NAME
@@ -118,6 +118,12 @@ or, if present, the per-jail
.Pp
All IP activity will be forced to happen to/from the IP number specified,
which should be an alias on one of the network interfaces.
+All connections to/from the loopback address
+.Pf ( Li 127.0.0.1
+for IPv4,
+.Li ::1
+for IPv6) will be changed to be to/from the primary address
+of the jail for the given address family.
.Pp
It is possible to identify a process as jailed by examining
.Dq Li /proc/<pid>/status :
diff --git a/lib/libc/sys/send.2 b/lib/libc/sys/send.2
index 6a61426..8fa2c64 100644
--- a/lib/libc/sys/send.2
+++ b/lib/libc/sys/send.2
@@ -28,7 +28,7 @@
.\" From: @(#)send.2 8.2 (Berkeley) 2/21/94
.\" $FreeBSD$
.\"
-.Dd September 13, 2006
+.Dd February 5, 2009
.Dt SEND 2
.Os
.Sh NAME
@@ -190,7 +190,7 @@ receiver is not listening on the remote port.
The remote host was down.
.It Bq Er ENETDOWN
The remote network was down.
-.It Bq Er EPERM
+.It Bq Er EADDRNOTAVAIL
The process using a
.Dv SOCK_RAW
socket was jailed and the source
diff --git a/lib/libc/sys/socket.2 b/lib/libc/sys/socket.2
index ce4c1fb..dae33d0 100644
--- a/lib/libc/sys/socket.2
+++ b/lib/libc/sys/socket.2
@@ -28,7 +28,7 @@
.\" From: @(#)socket.2 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.Dd August 4, 2008
+.Dd January 5, 2009
.Dt SOCKET 2
.Os
.Sh NAME
@@ -131,6 +131,11 @@ in which communication
is to take place; see
.Xr protocols 5 .
.Pp
+The
+.Fa protocol
+argument may be set to zero (0) to request the default
+implementation of a socket type for the protocol, if any.
+.Pp
Sockets of type
.Dv SOCK_STREAM
are full-duplex byte streams, similar
diff --git a/lib/libc/sys/timer_create.2 b/lib/libc/sys/timer_create.2
index 36eae43..3fb415c 100644
--- a/lib/libc/sys/timer_create.2
+++ b/lib/libc/sys/timer_create.2
@@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd September 11, 2000
+.Dd January 12, 2009
.Dt TIMER_CREATE 2
.Os
.Sh NAME
@@ -37,6 +37,7 @@
.Lb librt
.Sh SYNOPSIS
.In time.h
+.In signal.h
.Ft int
.Fo timer_create
.Fa "clockid_t clockid" "struct sigevent *restrict evp"
@@ -100,7 +101,7 @@ or
.Dv CLOCK_MONOTONIC .
.Pp
If
-.Fa evp->sigev_sigev_notify
+.Fa evp->sigev_notify
is
.Dv SIGEV_THREAD
and
OpenPOWER on IntegriCloud