summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile4
-rw-r--r--lib/libarchive/archive_read_support_compression_gzip.c5
-rw-r--r--lib/libarchive/archive_read_support_format_ar.c7
-rw-r--r--lib/libarchive/archive_read_support_format_iso9660.c7
-rw-r--r--lib/libarchive/archive_write_disk.c82
-rw-r--r--lib/libarchive/test/Makefile2
-rw-r--r--lib/libarchive/test/test_write_disk_failures.c62
-rw-r--r--lib/libarchive/test/test_write_disk_secure.c2
-rw-r--r--lib/libarchive/test/test_write_disk_sparse.c278
-rw-r--r--lib/libauditd/Makefile22
-rw-r--r--lib/libbsm/Makefile13
-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
-rw-r--r--lib/libelf/README12
-rw-r--r--lib/libmagic/Makefile7
-rw-r--r--lib/libmd/mdX.35
-rw-r--r--lib/libpmc/libpmc.c24
-rw-r--r--lib/libstand/bootp.c2
-rw-r--r--lib/libusb20/libusb20.c2
-rw-r--r--lib/libusb20/libusb20_desc.c42
-rw-r--r--lib/libusbhid/Makefile2
-rw-r--r--lib/libusbhid/descr.c72
-rw-r--r--lib/libusbhid/descr_compat.c77
-rw-r--r--lib/libusbhid/usbhid.315
-rw-r--r--lib/libusbhid/usbhid.h2
-rw-r--r--lib/libusbhid/usbvar.h5
-rw-r--r--lib/msun/src/e_rem_pio2.c2
-rw-r--r--lib/msun/src/e_rem_pio2f.c2
-rw-r--r--lib/msun/src/k_cosf.c2
-rw-r--r--lib/msun/src/k_sinf.c2
-rw-r--r--lib/msun/src/k_tanf.c2
-rw-r--r--lib/msun/src/math.h10
89 files changed, 1607 insertions, 1059 deletions
diff --git a/lib/Makefile b/lib/Makefile
index a44335c..06263ea 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -8,6 +8,7 @@
#
# csu must be built before all shared libaries for ELF.
# libc must be built before all other shared libraries.
+# libbsm must be built before ibauditd.
# libcom_err must be built before libkrb5 and libpam.
# libcrypt must be built before libkrb5 and libpam.
# libkvm must be built before libdevstat.
@@ -26,7 +27,8 @@
#
# Otherwise, the SUBDIR list should be in alphabetical order.
-SUBDIR= ${_csu} libc libbsm libcom_err libcrypt libelf libkvm msun libmd \
+SUBDIR= ${_csu} libc libbsm libauditd libcom_err libcrypt libelf libkvm msun \
+ libmd \
ncurses ${_libnetgraph} libradius librpcsvc libsbuf \
libtacplus libutil ${_libypclnt} libalias libarchive ${_libatm} \
libbegemot ${_libbluetooth} ${_libbsnmp} libbz2 \
diff --git a/lib/libarchive/archive_read_support_compression_gzip.c b/lib/libarchive/archive_read_support_compression_gzip.c
index 1e8f818..4669ea4 100644
--- a/lib/libarchive/archive_read_support_compression_gzip.c
+++ b/lib/libarchive/archive_read_support_compression_gzip.c
@@ -428,8 +428,9 @@ gzip_source_read(struct archive_read_source *self, const void **p)
"Failed to clean up gzip decompressor");
return (ARCHIVE_FATAL);
}
- /* Restart header parser with the next block. */
- state->header_state = state->header_done = 0;
+ /* zlib has been torn down */
+ state->header_done = 0;
+ state->eof = 1;
/* FALL THROUGH */
case Z_OK: /* Decompressor made some progress. */
/* If we filled our buffer, update stats and return. */
diff --git a/lib/libarchive/archive_read_support_format_ar.c b/lib/libarchive/archive_read_support_format_ar.c
index fed979d..0201364 100644
--- a/lib/libarchive/archive_read_support_format_ar.c
+++ b/lib/libarchive/archive_read_support_format_ar.c
@@ -511,11 +511,10 @@ ar_parse_gnu_filename_table(struct archive_read *a)
}
}
/*
- * Sanity check, last two chars must be `/\n' or '\n\n',
- * depending on whether the string table is padded by a '\n'
- * (string table produced by GNU ar always has a even size).
+ * GNU ar always pads the table to an even size.
+ * The pad character is either '\n' or '`'.
*/
- if (p != ar->strtab + size && *p != '\n')
+ if (p != ar->strtab + size && *p != '\n' && *p != '`')
goto bad_string_table;
/* Enforce zero termination. */
diff --git a/lib/libarchive/archive_read_support_format_iso9660.c b/lib/libarchive/archive_read_support_format_iso9660.c
index e64b6fc..ab96a27 100644
--- a/lib/libarchive/archive_read_support_format_iso9660.c
+++ b/lib/libarchive/archive_read_support_format_iso9660.c
@@ -466,7 +466,10 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
* seek backwards to extract it, so issue a warning. */
if (file->offset < iso9660->current_position) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
- "Ignoring out-of-order file");
+ "Ignoring out-of-order file @%x (%s) %jd < %jd",
+ file,
+ iso9660->pathname.s,
+ file->offset, iso9660->current_position);
iso9660->entry_bytes_remaining = 0;
iso9660->entry_sparse_offset = 0;
release_file(iso9660, file);
@@ -607,7 +610,7 @@ parse_file_info(struct iso9660 *iso9660, struct file_info *parent,
file->parent = parent;
if (parent != NULL)
parent->refcount++;
- file->offset = toi(isodirrec + DR_extent_offset, DR_extent_size)
+ file->offset = (uint64_t)toi(isodirrec + DR_extent_offset, DR_extent_size)
* iso9660->logical_block_size;
file->size = toi(isodirrec + DR_size_offset, DR_size_size);
file->mtime = isodate7(isodirrec + DR_date_offset);
diff --git a/lib/libarchive/archive_write_disk.c b/lib/libarchive/archive_write_disk.c
index 68da515..ddac630 100644
--- a/lib/libarchive/archive_write_disk.c
+++ b/lib/libarchive/archive_write_disk.c
@@ -178,6 +178,8 @@ struct archive_write_disk {
int fd;
/* Current offset for writing data to the file. */
off_t offset;
+ /* Last offset actually written to disk. */
+ off_t fd_offset;
/* Maximum size of file, -1 if unknown. */
off_t filesize;
/* Dir we were in before this restore; only for deep paths. */
@@ -187,8 +189,6 @@ struct archive_write_disk {
/* UID/GID to use in restoring this entry. */
uid_t uid;
gid_t gid;
- /* Last offset written to disk. */
- off_t last_offset;
};
/*
@@ -235,7 +235,7 @@ static struct fixup_entry *sort_dir_list(struct fixup_entry *p);
static gid_t trivial_lookup_gid(void *, const char *, gid_t);
static uid_t trivial_lookup_uid(void *, const char *, uid_t);
static ssize_t write_data_block(struct archive_write_disk *,
- const char *, size_t, off_t);
+ const char *, size_t);
static struct archive_vtable *archive_write_disk_vtable(void);
@@ -337,7 +337,7 @@ _archive_write_header(struct archive *_a, struct archive_entry *entry)
}
a->entry = archive_entry_clone(entry);
a->fd = -1;
- a->last_offset = 0;
+ a->fd_offset = 0;
a->offset = 0;
a->uid = a->user_uid;
a->mode = archive_entry_mode(a->entry);
@@ -484,7 +484,7 @@ _archive_write_header(struct archive *_a, struct archive_entry *entry)
}
/* We've created the object and are ready to pour data into it. */
- if (ret == ARCHIVE_OK)
+ if (ret >= ARCHIVE_WARN)
a->archive.state = ARCHIVE_STATE_DATA;
/*
* If it's not open, tell our client not to try writing.
@@ -513,9 +513,9 @@ archive_write_disk_set_skip_file(struct archive *_a, dev_t d, ino_t i)
}
static ssize_t
-write_data_block(struct archive_write_disk *a,
- const char *buff, size_t size, off_t offset)
+write_data_block(struct archive_write_disk *a, const char *buff, size_t size)
{
+ uint64_t start_size = size;
ssize_t bytes_written = 0;
ssize_t block_size = 0, bytes_to_write;
@@ -538,8 +538,9 @@ write_data_block(struct archive_write_disk *a,
#endif
}
- if (a->filesize >= 0 && (off_t)(offset + size) > a->filesize)
- size = (size_t)(a->filesize - offset);
+ /* If this write would run beyond the file size, truncate it. */
+ if (a->filesize >= 0 && (off_t)(a->offset + size) > a->filesize)
+ start_size = size = (size_t)(a->filesize - a->offset);
/* Write the data. */
while (size > 0) {
@@ -555,7 +556,7 @@ write_data_block(struct archive_write_disk *a,
if (*p != '\0')
break;
}
- offset += p - buff;
+ a->offset += p - buff;
size -= p - buff;
buff = p;
if (size == 0)
@@ -563,22 +564,25 @@ write_data_block(struct archive_write_disk *a,
/* Calculate next block boundary after offset. */
block_end
- = (offset / block_size) * block_size + block_size;
+ = (a->offset / block_size + 1) * block_size;
/* If the adjusted write would cross block boundary,
* truncate it to the block boundary. */
bytes_to_write = size;
- if (offset + bytes_to_write > block_end)
- bytes_to_write = block_end - offset;
+ if (a->offset + bytes_to_write > block_end)
+ bytes_to_write = block_end - a->offset;
}
/* Seek if necessary to the specified offset. */
- if (offset != a->last_offset) {
- if (lseek(a->fd, offset, SEEK_SET) < 0) {
+ if (a->offset != a->fd_offset) {
+ if (lseek(a->fd, a->offset, SEEK_SET) < 0) {
archive_set_error(&a->archive, errno,
"Seek failed");
return (ARCHIVE_FATAL);
}
+ a->fd_offset = a->offset;
+ a->archive.file_position = a->offset;
+ a->archive.raw_position = a->offset;
}
bytes_written = write(a->fd, buff, bytes_to_write);
if (bytes_written < 0) {
@@ -587,12 +591,12 @@ write_data_block(struct archive_write_disk *a,
}
buff += bytes_written;
size -= bytes_written;
- offset += bytes_written;
+ a->offset += bytes_written;
a->archive.file_position += bytes_written;
a->archive.raw_position += bytes_written;
- a->last_offset = a->offset = offset;
+ a->fd_offset = a->offset;
}
- return (bytes_written);
+ return (start_size - size);
}
static ssize_t
@@ -605,9 +609,9 @@ _archive_write_data_block(struct archive *_a,
__archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
ARCHIVE_STATE_DATA, "archive_write_disk_block");
- r = write_data_block(a, buff, size, offset);
-
- if (r < 0)
+ a->offset = offset;
+ r = write_data_block(a, buff, size);
+ if (r < ARCHIVE_OK)
return (r);
if ((size_t)r < size) {
archive_set_error(&a->archive, 0,
@@ -625,7 +629,7 @@ _archive_write_data(struct archive *_a, const void *buff, size_t size)
__archive_check_magic(&a->archive, ARCHIVE_WRITE_DISK_MAGIC,
ARCHIVE_STATE_DATA, "archive_write_data");
- return (write_data_block(a, buff, size, a->offset));
+ return (write_data_block(a, buff, size));
}
static int
@@ -646,7 +650,7 @@ _archive_write_finish_entry(struct archive *_a)
/* There's no file. */
} else if (a->filesize < 0) {
/* File size is unknown, so we can't set the size. */
- } else if (a->last_offset == a->filesize) {
+ } else if (a->fd_offset == a->filesize) {
/* Last write ended at exactly the filesize; we're done. */
/* Hopefully, this is the common case. */
} else {
@@ -843,7 +847,7 @@ edit_deep_directories(struct archive_write_disk *a)
*tail = '\0'; /* Terminate dir portion */
ret = create_dir(a, a->name);
if (ret == ARCHIVE_OK && chdir(a->name) != 0)
- ret = ARCHIVE_WARN;
+ ret = ARCHIVE_FAILED;
*tail = '/'; /* Restore the / we removed. */
if (ret != ARCHIVE_OK)
return;
@@ -884,7 +888,7 @@ restore_entry(struct archive_write_disk *a)
/* We tried, but couldn't get rid of it. */
archive_set_error(&a->archive, errno,
"Could not unlink");
- return(ARCHIVE_WARN);
+ return(ARCHIVE_FAILED);
}
}
@@ -903,7 +907,7 @@ restore_entry(struct archive_write_disk *a)
&& (a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) {
/* If we're not overwriting, we're done. */
archive_set_error(&a->archive, en, "Already exists");
- return (ARCHIVE_WARN);
+ return (ARCHIVE_FAILED);
}
/*
@@ -918,7 +922,7 @@ restore_entry(struct archive_write_disk *a)
if (rmdir(a->name) != 0) {
archive_set_error(&a->archive, errno,
"Can't remove already-existing dir");
- return (ARCHIVE_WARN);
+ return (ARCHIVE_FAILED);
}
a->pst = NULL;
/* Try again. */
@@ -945,7 +949,7 @@ restore_entry(struct archive_write_disk *a)
if (r != 0) {
archive_set_error(&a->archive, errno,
"Can't stat existing object");
- return (ARCHIVE_WARN);
+ return (ARCHIVE_FAILED);
}
/*
@@ -974,7 +978,7 @@ restore_entry(struct archive_write_disk *a)
if (unlink(a->name) != 0) {
archive_set_error(&a->archive, errno,
"Can't unlink already-existing object");
- return (ARCHIVE_WARN);
+ return (ARCHIVE_FAILED);
}
a->pst = NULL;
/* Try again. */
@@ -984,7 +988,7 @@ restore_entry(struct archive_write_disk *a)
if (rmdir(a->name) != 0) {
archive_set_error(&a->archive, errno,
"Can't remove already-existing dir");
- return (ARCHIVE_WARN);
+ return (ARCHIVE_FAILED);
}
/* Try again. */
en = create_filesystem_object(a);
@@ -1007,7 +1011,7 @@ restore_entry(struct archive_write_disk *a)
if (en) {
/* Everything failed; give up here. */
archive_set_error(&a->archive, en, "Can't create '%s'", a->name);
- return (ARCHIVE_WARN);
+ return (ARCHIVE_FAILED);
}
a->pst = NULL; /* Cached stat data no longer valid. */
@@ -1393,7 +1397,7 @@ check_symlinks(struct archive_write_disk *a)
"Could not remove symlink %s",
a->name);
pn[0] = c;
- return (ARCHIVE_WARN);
+ return (ARCHIVE_FAILED);
}
a->pst = NULL;
/*
@@ -1417,7 +1421,7 @@ check_symlinks(struct archive_write_disk *a)
"Cannot remove intervening symlink %s",
a->name);
pn[0] = c;
- return (ARCHIVE_WARN);
+ return (ARCHIVE_FAILED);
}
a->pst = NULL;
} else {
@@ -1425,7 +1429,7 @@ check_symlinks(struct archive_write_disk *a)
"Cannot extract through symlink %s",
a->name);
pn[0] = c;
- return (ARCHIVE_WARN);
+ return (ARCHIVE_FAILED);
}
}
}
@@ -1551,7 +1555,7 @@ create_parent_dir(struct archive_write_disk *a, char *path)
* Create the specified dir, recursing to create parents as necessary.
*
* Returns ARCHIVE_OK if the path exists when we're done here.
- * Otherwise, returns ARCHIVE_WARN.
+ * Otherwise, returns ARCHIVE_FAILED.
* Assumes path is in mutable storage; path is unchanged on exit.
*/
static int
@@ -1596,18 +1600,18 @@ create_dir(struct archive_write_disk *a, char *path)
if ((a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE)) {
archive_set_error(&a->archive, EEXIST,
"Can't create directory '%s'", path);
- return (ARCHIVE_WARN);
+ return (ARCHIVE_FAILED);
}
if (unlink(path) != 0) {
archive_set_error(&a->archive, errno,
"Can't create directory '%s': "
"Conflicting file cannot be removed");
- return (ARCHIVE_WARN);
+ return (ARCHIVE_FAILED);
}
} else if (errno != ENOENT && errno != ENOTDIR) {
/* Stat failed? */
archive_set_error(&a->archive, errno, "Can't test directory '%s'", path);
- return (ARCHIVE_WARN);
+ return (ARCHIVE_FAILED);
} else if (slash != NULL) {
*slash = '\0';
r = create_dir(a, path);
@@ -1648,7 +1652,7 @@ create_dir(struct archive_write_disk *a, char *path)
return (ARCHIVE_OK);
archive_set_error(&a->archive, errno, "Failed to create dir '%s'", path);
- return (ARCHIVE_WARN);
+ return (ARCHIVE_FAILED);
}
/*
diff --git a/lib/libarchive/test/Makefile b/lib/libarchive/test/Makefile
index cb532aa..fc8e3e9 100644
--- a/lib/libarchive/test/Makefile
+++ b/lib/libarchive/test/Makefile
@@ -58,9 +58,11 @@ TESTS= \
test_write_compress.c \
test_write_compress_program.c \
test_write_disk.c \
+ test_write_disk_failures.c \
test_write_disk_hardlink.c \
test_write_disk_perms.c \
test_write_disk_secure.c \
+ test_write_disk_sparse.c \
test_write_disk_times.c \
test_write_format_ar.c \
test_write_format_cpio.c \
diff --git a/lib/libarchive/test/test_write_disk_failures.c b/lib/libarchive/test/test_write_disk_failures.c
new file mode 100644
index 0000000..76c9c3f
--- /dev/null
+++ b/lib/libarchive/test/test_write_disk_failures.c
@@ -0,0 +1,62 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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(S) 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.
+ */
+#include "test.h"
+__FBSDID("$FreeBSD$");
+
+#if ARCHIVE_VERSION_NUMBER >= 1009000
+
+#define UMASK 022
+
+
+#endif
+
+DEFINE_TEST(test_write_disk_failures)
+{
+#if ARCHIVE_VERSION_NUMBER < 1009000
+ skipping("archive_write_disk interface");
+#else
+ struct archive_entry *ae;
+ struct archive *a;
+
+ /* Force the umask to something predictable. */
+ umask(UMASK);
+
+ /* A directory that we can't write to. */
+ assertEqualInt(0, mkdir("dir", 0555));
+
+ /* Try to extract a regular file into the directory above. */
+ assert((ae = archive_entry_new()) != NULL);
+ archive_entry_copy_pathname(ae, "dir/file");
+ archive_entry_set_mode(ae, S_IFREG | 0755);
+ archive_entry_set_size(ae, 8);
+ assert((a = archive_write_disk_new()) != NULL);
+ archive_write_disk_set_options(a, ARCHIVE_EXTRACT_TIME);
+ archive_entry_set_mtime(ae, 123456789, 0);
+ assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae));
+ assertEqualIntA(a, 0, archive_write_finish_entry(a));
+ assertEqualInt(0, archive_write_finish(a));
+ archive_entry_free(ae);
+#endif
+}
diff --git a/lib/libarchive/test/test_write_disk_secure.c b/lib/libarchive/test/test_write_disk_secure.c
index bcb0bf4..b898c97 100644
--- a/lib/libarchive/test/test_write_disk_secure.c
+++ b/lib/libarchive/test/test_write_disk_secure.c
@@ -80,7 +80,7 @@ DEFINE_TEST(test_write_disk_secure)
archive_entry_set_mode(ae, S_IFREG | 0777);
archive_write_disk_set_options(a, ARCHIVE_EXTRACT_SECURE_SYMLINKS);
failure("Extracting a file through a symlink should fail here.");
- assertEqualInt(ARCHIVE_WARN, archive_write_header(a, ae));
+ assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae));
archive_entry_free(ae);
assert(0 == archive_write_finish_entry(a));
diff --git a/lib/libarchive/test/test_write_disk_sparse.c b/lib/libarchive/test/test_write_disk_sparse.c
new file mode 100644
index 0000000..6179610
--- /dev/null
+++ b/lib/libarchive/test/test_write_disk_sparse.c
@@ -0,0 +1,278 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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(S) 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.
+ */
+#include "test.h"
+__FBSDID("$FreeBSD$");
+
+/*
+ * Write a file using archive_write_data call, read the file
+ * back and verify the contents. The data written includes large
+ * blocks of nulls, so it should exercise the sparsification logic
+ * if ARCHIVE_EXTRACT_SPARSE is enabled.
+ */
+static void
+verify_write_data(struct archive *a, int sparse)
+{
+ static const char data[]="abcdefghijklmnopqrstuvwxyz";
+ struct stat st;
+ struct archive_entry *ae;
+ size_t buff_size = 64 * 1024;
+ char *buff, *p;
+ const char *msg = sparse ? "sparse" : "non-sparse";
+ int fd;
+
+ buff = malloc(buff_size);
+ assert(buff != NULL);
+
+ ae = archive_entry_new();
+ assert(ae != NULL);
+ archive_entry_set_size(ae, 8 * buff_size);
+ archive_entry_set_pathname(ae, "test_write_data");
+ archive_entry_set_mode(ae, AE_IFREG | 0755);
+ assertEqualIntA(a, 0, archive_write_header(a, ae));
+
+ /* Use archive_write_data() to write three relatively sparse blocks. */
+
+ /* First has non-null data at beginning. */
+ memset(buff, 0, buff_size);
+ memcpy(buff, data, sizeof(data));
+ failure("%s", msg);
+ assertEqualInt(buff_size, archive_write_data(a, buff, buff_size));
+
+ /* Second has non-null data in the middle. */
+ memset(buff, 0, buff_size);
+ memcpy(buff + buff_size / 2 - 3, data, sizeof(data));
+ failure("%s", msg);
+ assertEqualInt(buff_size, archive_write_data(a, buff, buff_size));
+
+ /* Third has non-null data at the end. */
+ memset(buff, 0, buff_size);
+ memcpy(buff + buff_size - sizeof(data), data, sizeof(data));
+ failure("%s", msg);
+ assertEqualInt(buff_size, archive_write_data(a, buff, buff_size));
+
+ failure("%s", msg);
+ assertEqualIntA(a, 0, archive_write_finish_entry(a));
+
+ /* Test the entry on disk. */
+ assert(0 == stat(archive_entry_pathname(ae), &st));
+ assertEqualInt(st.st_size, 8 * buff_size);
+ fd = open(archive_entry_pathname(ae), O_RDONLY);
+ if (!assert(fd >= 0))
+ return;
+
+ /* Check first block. */
+ assertEqualInt(buff_size, read(fd, buff, buff_size));
+ failure("%s", msg);
+ assertEqualMem(buff, data, sizeof(data));
+ for (p = buff + sizeof(data); p < buff + buff_size; ++p) {
+ failure("offset: %d, %s", (int)(p - buff), msg);
+ if (!assertEqualInt(0, *p))
+ break;
+ }
+
+ /* Check second block. */
+ assertEqualInt(buff_size, read(fd, buff, buff_size));
+ for (p = buff; p < buff + buff_size; ++p) {
+ failure("offset: %d, %s", (int)(p - buff), msg);
+ if (p == buff + buff_size / 2 - 3) {
+ assertEqualMem(p, data, sizeof(data));
+ p += sizeof(data);
+ } else if (!assertEqualInt(0, *p))
+ break;
+ }
+
+ /* Check third block. */
+ assertEqualInt(buff_size, read(fd, buff, buff_size));
+ for (p = buff; p < buff + buff_size - sizeof(data); ++p) {
+ failure("offset: %d, %s", (int)(p - buff), msg);
+ if (!assertEqualInt(0, *p))
+ break;
+ }
+ failure("%s", msg);
+ assertEqualMem(buff + buff_size - sizeof(data), data, sizeof(data));
+
+ /* XXX more XXX */
+
+ assertEqualInt(0, close(fd));
+ free(buff);
+}
+
+/*
+ * As above, but using the archive_write_data_block() call.
+ */
+static void
+verify_write_data_block(struct archive *a, int sparse)
+{
+ static const char data[]="abcdefghijklmnopqrstuvwxyz";
+ struct stat st;
+ struct archive_entry *ae;
+ size_t buff_size = 64 * 1024;
+ char *buff, *p;
+ const char *msg = sparse ? "sparse" : "non-sparse";
+ int fd;
+
+ buff = malloc(buff_size);
+ assert(buff != NULL);
+
+ ae = archive_entry_new();
+ assert(ae != NULL);
+ archive_entry_set_size(ae, 8 * buff_size);
+ archive_entry_set_pathname(ae, "test_write_data_block");
+ archive_entry_set_mode(ae, AE_IFREG | 0755);
+ assertEqualIntA(a, 0, archive_write_header(a, ae));
+
+ /* Use archive_write_data_block() to write three
+ relatively sparse blocks. */
+
+ /* First has non-null data at beginning. */
+ memset(buff, 0, buff_size);
+ memcpy(buff, data, sizeof(data));
+ failure("%s", msg);
+ assertEqualInt(ARCHIVE_OK,
+ archive_write_data_block(a, buff, buff_size, 100));
+
+ /* Second has non-null data in the middle. */
+ memset(buff, 0, buff_size);
+ memcpy(buff + buff_size / 2 - 3, data, sizeof(data));
+ failure("%s", msg);
+ assertEqualInt(ARCHIVE_OK,
+ archive_write_data_block(a, buff, buff_size, buff_size + 200));
+
+ /* Third has non-null data at the end. */
+ memset(buff, 0, buff_size);
+ memcpy(buff + buff_size - sizeof(data), data, sizeof(data));
+ failure("%s", msg);
+ assertEqualInt(ARCHIVE_OK,
+ archive_write_data_block(a, buff, buff_size, buff_size * 2 + 300));
+
+ failure("%s", msg);
+ assertEqualIntA(a, 0, archive_write_finish_entry(a));
+
+ /* Test the entry on disk. */
+ assert(0 == stat(archive_entry_pathname(ae), &st));
+ assertEqualInt(st.st_size, 8 * buff_size);
+ fd = open(archive_entry_pathname(ae), O_RDONLY);
+ if (!assert(fd >= 0))
+ return;
+
+ /* Check 100-byte gap at beginning */
+ assertEqualInt(100, read(fd, buff, 100));
+ failure("%s", msg);
+ for (p = buff; p < buff + 100; ++p) {
+ failure("offset: %d, %s", (int)(p - buff), msg);
+ if (!assertEqualInt(0, *p))
+ break;
+ }
+
+ /* Check first block. */
+ assertEqualInt(buff_size, read(fd, buff, buff_size));
+ failure("%s", msg);
+ assertEqualMem(buff, data, sizeof(data));
+ for (p = buff + sizeof(data); p < buff + buff_size; ++p) {
+ failure("offset: %d, %s", (int)(p - buff), msg);
+ if (!assertEqualInt(0, *p))
+ break;
+ }
+
+ /* Check 100-byte gap */
+ assertEqualInt(100, read(fd, buff, 100));
+ failure("%s", msg);
+ for (p = buff; p < buff + 100; ++p) {
+ failure("offset: %d, %s", (int)(p - buff), msg);
+ if (!assertEqualInt(0, *p))
+ break;
+ }
+
+ /* Check second block. */
+ assertEqualInt(buff_size, read(fd, buff, buff_size));
+ for (p = buff; p < buff + buff_size; ++p) {
+ failure("offset: %d, %s", (int)(p - buff), msg);
+ if (p == buff + buff_size / 2 - 3) {
+ assertEqualMem(p, data, sizeof(data));
+ p += sizeof(data);
+ } else if (!assertEqualInt(0, *p))
+ break;
+ }
+
+ /* Check 100-byte gap */
+ assertEqualInt(100, read(fd, buff, 100));
+ failure("%s", msg);
+ for (p = buff; p < buff + 100; ++p) {
+ failure("offset: %d, %s", (int)(p - buff), msg);
+ if (!assertEqualInt(0, *p))
+ break;
+ }
+
+ /* Check third block. */
+ assertEqualInt(buff_size, read(fd, buff, buff_size));
+ for (p = buff; p < buff + buff_size - sizeof(data); ++p) {
+ failure("offset: %d, %s", (int)(p - buff), msg);
+ if (!assertEqualInt(0, *p))
+ break;
+ }
+ failure("%s", msg);
+ assertEqualMem(buff + buff_size - sizeof(data), data, sizeof(data));
+
+ /* Check another block size beyond last we wrote. */
+ assertEqualInt(buff_size, read(fd, buff, buff_size));
+ failure("%s", msg);
+ for (p = buff; p < buff + buff_size; ++p) {
+ failure("offset: %d, %s", (int)(p - buff), msg);
+ if (!assertEqualInt(0, *p))
+ break;
+ }
+
+
+ /* XXX more XXX */
+
+ assertEqualInt(0, close(fd));
+ free(buff);
+}
+
+DEFINE_TEST(test_write_disk_sparse)
+{
+ struct archive *ad;
+
+
+ /*
+ * The return values, etc, of the write data functions
+ * shouldn't change regardless of whether we've requested
+ * sparsification. (The performance and pattern of actual
+ * write calls to the disk should vary, of course, but the
+ * client program shouldn't see any difference.)
+ */
+ assert((ad = archive_write_disk_new()) != NULL);
+ archive_write_disk_set_options(ad, 0);
+ verify_write_data(ad, 0);
+ verify_write_data_block(ad, 0);
+ assertEqualInt(0, archive_write_finish(ad));
+
+ assert((ad = archive_write_disk_new()) != NULL);
+ archive_write_disk_set_options(ad, ARCHIVE_EXTRACT_SPARSE);
+ verify_write_data(ad, 1);
+ verify_write_data_block(ad, 1);
+ assertEqualInt(0, archive_write_finish(ad));
+
+}
diff --git a/lib/libauditd/Makefile b/lib/libauditd/Makefile
new file mode 100644
index 0000000..48ec4b1
--- /dev/null
+++ b/lib/libauditd/Makefile
@@ -0,0 +1,22 @@
+#
+# $FreeBSD$
+#
+
+OPENBSMDIR= ${.CURDIR}/../../contrib/openbsm
+LIBAUDITDDIR= ${OPENBSMDIR}/libauditd
+LIBBSMDIR= ${OPENBSMDIR}/libbsm
+
+LIB= auditd
+
+.PATH: ${LIBAUDITDDIR}
+
+SRCS= auditd_lib.c
+
+#
+# Must use BSM include files from within the contrib area, not the system.
+#
+CFLAGS+= -I${OPENBSMDIR} -I${LIBBSMDIR}
+
+NO_MAN=
+
+.include <bsd.lib.mk>
diff --git a/lib/libbsm/Makefile b/lib/libbsm/Makefile
index 8f3b828..e978b7f 100644
--- a/lib/libbsm/Makefile
+++ b/lib/libbsm/Makefile
@@ -15,11 +15,14 @@ SHLIB_MAJOR= 2
SRCS= bsm_audit.c \
bsm_class.c \
bsm_control.c \
+ bsm_domain.c \
+ bsm_errno.c \
bsm_event.c \
bsm_flags.c \
bsm_io.c \
bsm_mask.c \
bsm_notify.c \
+ bsm_socket_type.c \
bsm_token.c \
bsm_user.c \
bsm_wrappers.c
@@ -35,11 +38,14 @@ INCSDIR= ${INCLUDEDIR}/bsm
MAN= libbsm.3 \
au_class.3 \
au_control.3 \
+ au_domain.3 \
+ au_errno.3 \
au_event.3 \
au_free_token.3 \
au_io.3 \
au_mask.3 \
au_open.3 \
+ au_socket_type.3 \
au_token.3 \
au_user.3 \
audit_submit.3
@@ -79,6 +85,11 @@ MLINKS= libbsm.3 bsm.3 \
au_control.3 getacpol.3 \
au_control.3 au_poltostr.3 \
au_control.3 au_strtopol.3 \
+ au_domain.3 au_bsm_to_domain.3 \
+ au_domain.3 au_domain_to_bsm.3 \
+ au_errno.3 au_bsm_to_errno.3 \
+ au_errno.3 au_errno_to_bsm.3 \
+ au_errno.3 au_strerror.3 \
au_event.3 setauevent.3 \
au_event.3 endauevent.3 \
au_event.3 getauevent.3 \
@@ -99,6 +110,8 @@ MLINKS= libbsm.3 bsm.3 \
au_open.3 au_close_buffer.3 \
au_open.3 au_close_token.3 \
au_open.3 au_write.3 \
+ au_socket_type.3 au_bsm_to_socket_type.3 \
+ au_socket_type.3 au_socket_type_to_bsm.3 \
au_token.3 au_to_arg32.3 \
au_token.3 au_to_arg64.3 \
au_token.3 au_to_arg.3 \
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
diff --git a/lib/libelf/README b/lib/libelf/README
new file mode 100644
index 0000000..726fcc9
--- /dev/null
+++ b/lib/libelf/README
@@ -0,0 +1,12 @@
+# $FreeBSD$
+# $NetBSD$
+
+libelf: a BSD-licensed implementation of the ELF(3)/GELF(3) API.
+
+Documentation:
+ * Manual page elf.3 contains an overview of the library. Other
+ manual pages document individual APIs in the library.
+ * A tutorial "libelf by Example" is available at:
+ http://people.freebsd.org/~jkoshy/download/libelf/article.html
+
+For ongoing development please see http://elftoolchain.sourceforge.net/
diff --git a/lib/libmagic/Makefile b/lib/libmagic/Makefile
index 97d2752..fc604d2 100644
--- a/lib/libmagic/Makefile
+++ b/lib/libmagic/Makefile
@@ -19,9 +19,9 @@ MAGICPATH?= /usr/share/misc
CFLAGS+= -DMAGIC='"${MAGICPATH}/magic"' -DHAVE_CONFIG_H
CFLAGS+= -I${.CURDIR} -I${CONTRDIR}
-CLEANFILES+= magic magic.mgc magic.mime.mgc
+CLEANFILES+= magic magic.mgc
-FILES= magic magic.mgc ${CONTRDIR}/magic.mime magic.mime.mgc
+FILES= magic magic.mgc
FILESDIR= ${MAGICPATH}
MAGFILES= ${CONTRDIR}/Header\
@@ -34,9 +34,6 @@ magic: ${MAGFILES}
magic.mgc: mkmagic magic
./mkmagic magic
-magic.mime.mgc: mkmagic magic.mime
- ./mkmagic ${CONTRDIR}/magic.mime
-
CLEANFILES+= mkmagic
build-tools: mkmagic
mkmagic: apprentice.c funcs.c magic.c print.c
diff --git a/lib/libmd/mdX.3 b/lib/libmd/mdX.3
index c0567c5..03f50f1 100644
--- a/lib/libmd/mdX.3
+++ b/lib/libmd/mdX.3
@@ -164,11 +164,6 @@ argument is non-null it must point to at least 33 characters of buffer space.
.%O RFC 1321
.Re
.Rs
-.%A RSA Laboratories
-.%T Frequently Asked Questions About today's Cryptography
-.%O \&<http://www.rsa.com/rsalabs/faq/>
-.Re
-.Rs
.%A H. Dobbertin
.%T Alf Swindles Ann
.%J CryptoBytes
diff --git a/lib/libpmc/libpmc.c b/lib/libpmc/libpmc.c
index 21bd995..b1d6653 100644
--- a/lib/libpmc/libpmc.c
+++ b/lib/libpmc/libpmc.c
@@ -152,6 +152,11 @@ static const struct pmc_event_descr core2_event_table[] =
__PMC_EV_ALIAS_CORE2()
};
+static const struct pmc_event_descr corei7_event_table[] =
+{
+ __PMC_EV_ALIAS_COREI7()
+};
+
/*
* PMC_MDEP_TABLE(NAME, PRIMARYCLASS, ADDITIONAL_CLASSES...)
*
@@ -165,6 +170,7 @@ static const struct pmc_event_descr core2_event_table[] =
PMC_MDEP_TABLE(atom, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC);
PMC_MDEP_TABLE(core, IAP, PMC_CLASS_TSC);
PMC_MDEP_TABLE(core2, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC);
+PMC_MDEP_TABLE(corei7, IAP, PMC_CLASS_IAF, PMC_CLASS_TSC);
PMC_MDEP_TABLE(k7, K7, PMC_CLASS_TSC);
PMC_MDEP_TABLE(k8, K8, PMC_CLASS_TSC);
PMC_MDEP_TABLE(p4, P4, PMC_CLASS_TSC);
@@ -194,6 +200,7 @@ PMC_CLASS_TABLE_DESC(iaf, IAF, iaf, iaf);
PMC_CLASS_TABLE_DESC(atom, IAP, atom, iap);
PMC_CLASS_TABLE_DESC(core, IAP, core, iap);
PMC_CLASS_TABLE_DESC(core2, IAP, core2, iap);
+PMC_CLASS_TABLE_DESC(corei7, IAP, corei7, iap);
#endif
#if defined(__i386__)
PMC_CLASS_TABLE_DESC(k7, K7, k7, k7);
@@ -448,6 +455,7 @@ static struct pmc_event_alias core2_aliases[] = {
EV_ALIAS(NULL, NULL)
};
#define atom_aliases core2_aliases
+#define corei7_aliases core2_aliases
#define IAF_KW_OS "os"
#define IAF_KW_USR "usr"
@@ -604,7 +612,8 @@ iap_allocate_pmc(enum pmc_event pe, char *ctrspec,
return (-1);
} else if (cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM ||
cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2 ||
- cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2EXTREME) {
+ cpu_info.pm_cputype == PMC_CPU_INTEL_CORE2EXTREME ||
+ cpu_info.pm_cputype == PMC_CPU_INTEL_COREI7) {
if (KWMATCH(p, IAP_KW_SNOOPRESPONSE)) {
n = pmc_parse_mask(iap_snoopresponse_mask, p,
&evmask);
@@ -2278,6 +2287,10 @@ pmc_event_names_of_class(enum pmc_class cl, const char ***eventnames,
ev = core2_event_table;
count = PMC_EVENT_TABLE_SIZE(core2);
break;
+ case PMC_CPU_INTEL_COREI7:
+ ev = corei7_event_table;
+ count = PMC_EVENT_TABLE_SIZE(corei7);
+ break;
}
break;
case PMC_CLASS_TSC:
@@ -2462,6 +2475,11 @@ pmc_init(void)
pmc_class_table[n++] = &iaf_class_table_descr;
pmc_class_table[n] = &core2_class_table_descr;
break;
+ case PMC_CPU_INTEL_COREI7:
+ PMC_MDEP_INIT(corei7);
+ pmc_class_table[n++] = &iaf_class_table_descr;
+ pmc_class_table[n] = &corei7_class_table_descr;
+ break;
case PMC_CPU_INTEL_PIV:
PMC_MDEP_INIT(p4);
pmc_class_table[n] = &p4_class_table_descr;
@@ -2560,6 +2578,10 @@ _pmc_name_of_event(enum pmc_event pe, enum pmc_cputype cpu)
ev = core2_event_table;
evfence = core2_event_table + PMC_EVENT_TABLE_SIZE(core2);
break;
+ case PMC_CPU_INTEL_COREI7:
+ ev = corei7_event_table;
+ evfence = corei7_event_table + PMC_EVENT_TABLE_SIZE(corei7);
+ break;
default: /* Unknown CPU type. */
break;
}
diff --git a/lib/libstand/bootp.c b/lib/libstand/bootp.c
index 4ddfa6c..401b691 100644
--- a/lib/libstand/bootp.c
+++ b/lib/libstand/bootp.c
@@ -496,7 +496,7 @@ static struct dhcp_opt vndr_opt[] = { /* Vendor Specific Options */
{94, __BYTES, "network-interface"},
{97, __BYTES, "machine-identifier"},
#else /* default (empty) table */
- {0, 0, ""}, /* prefix */
+ {0, 0, "dhcp.vendor."}, /* prefix */
#endif
{0, __TXT, "%soption-%d"}
};
diff --git a/lib/libusb20/libusb20.c b/lib/libusb20/libusb20.c
index f9c99cb..e9ef1fc 100644
--- a/lib/libusb20/libusb20.c
+++ b/lib/libusb20/libusb20.c
@@ -486,6 +486,8 @@ libusb20_dev_close(struct libusb20_device *pdev)
pdev->is_opened = 0;
+ pdev->claimed_interfaces = 0;
+
return (error);
}
diff --git a/lib/libusb20/libusb20_desc.c b/lib/libusb20/libusb20_desc.c
index bba4d25..e0d2c54 100644
--- a/lib/libusb20/libusb20_desc.c
+++ b/lib/libusb20/libusb20_desc.c
@@ -238,23 +238,37 @@ const uint8_t *
libusb20_desc_foreach(const struct libusb20_me_struct *pdesc,
const uint8_t *psubdesc)
{
- const void *end;
+ const uint8_t *start;
+ const uint8_t *end;
+ const uint8_t *desc_next;
- if (pdesc == NULL) {
+ /* be NULL safe */
+ if (pdesc == NULL)
return (NULL);
- }
- end = LIBUSB20_ADD_BYTES(pdesc->ptr, pdesc->len);
- if (psubdesc == NULL) {
- psubdesc = LIBUSB20_ADD_BYTES(pdesc->ptr, 0);
- } else {
- psubdesc = LIBUSB20_ADD_BYTES(psubdesc, psubdesc[0]);
- }
- return (((((const void *)psubdesc) >= ((void *)(pdesc->ptr))) &&
- (((const void *)psubdesc) < end) &&
- (LIBUSB20_ADD_BYTES(psubdesc, psubdesc[0]) >= ((void *)(pdesc->ptr))) &&
- (LIBUSB20_ADD_BYTES(psubdesc, psubdesc[0]) <= end) &&
- (psubdesc[0] >= 3)) ? psubdesc : NULL);
+ start = (const uint8_t *)pdesc->ptr;
+ end = LIBUSB20_ADD_BYTES(start, pdesc->len);
+
+ /* get start of next descriptor */
+ if (psubdesc == NULL)
+ psubdesc = start;
+ else
+ psubdesc = psubdesc + psubdesc[0];
+
+ /* check that the next USB descriptor is within the range */
+ if ((psubdesc < start) || (psubdesc >= end))
+ return (NULL); /* out of range, or EOD */
+
+ /* check start of the second next USB descriptor, if any */
+ desc_next = psubdesc + psubdesc[0];
+ if ((desc_next < start) || (desc_next > end))
+ return (NULL); /* out of range */
+
+ /* check minimum descriptor length */
+ if (psubdesc[0] < 3)
+ return (NULL); /* too short descriptor */
+
+ return (psubdesc); /* return start of next descriptor */
}
/*------------------------------------------------------------------------*
diff --git a/lib/libusbhid/Makefile b/lib/libusbhid/Makefile
index 23b4068..d681302 100644
--- a/lib/libusbhid/Makefile
+++ b/lib/libusbhid/Makefile
@@ -15,7 +15,7 @@ MLINKS= usbhid.3 libusbhid.3 usbhid.3 hid_get_report_desc.3 \
usbhid.3 hid_init.3 \
usbhid.3 hid_get_data.3 usbhid.3 hid_set_data.3
-SRCS= descr.c parse.c usage.c data.c
+SRCS= descr.c descr_compat.c parse.c usage.c data.c
INCS= usbhid.h
diff --git a/lib/libusbhid/descr.c b/lib/libusbhid/descr.c
index 4afdb61..cc1737b 100644
--- a/lib/libusbhid/descr.c
+++ b/lib/libusbhid/descr.c
@@ -39,21 +39,83 @@ __FBSDID("$FreeBSD$");
#include <sys/time.h>
#include <sys/ioctl.h>
-#include <dev/usb/usb.h>
+#include <dev/usb2/include/usb2_ioctl.h>
#include "usbhid.h"
#include "usbvar.h"
+int
+hid_set_immed(int fd, int enable)
+{
+ int ret;
+ ret = ioctl(fd, USB_SET_IMMED, &enable);
+ if (ret < 0)
+ ret = hid_set_immed_compat7(fd, enable);
+ return (ret);
+}
+
+int
+hid_get_report_id(int fd)
+{
+ int temp = -1;
+ int ret;
+
+ ret = ioctl(fd, USB_GET_REPORT_ID, &temp);
+ if (ret < 0)
+ ret = hid_get_report_id_compat7(fd);
+ else
+ ret = temp;
+
+ return (ret);
+}
+
report_desc_t
hid_get_report_desc(int fd)
{
- struct usb_ctl_report_desc rep;
+ struct usb2_gen_descriptor ugd;
+ report_desc_t rep;
+ void *data;
- rep.ucrd_size = 0;
- if (ioctl(fd, USB_GET_REPORT_DESC, &rep) < 0)
+ memset(&ugd, 0, sizeof(ugd));
+
+ /* get actual length first */
+ ugd.ugd_data = NULL;
+ ugd.ugd_maxlen = 65535;
+ if (ioctl(fd, USB_GET_REPORT_DESC, &ugd) < 0) {
+ /* could not read descriptor */
+ /* try FreeBSD 7 compat code */
+ return (hid_get_report_desc_compat7(fd));
+ }
+
+ /*
+ * NOTE: The kernel will return a failure if
+ * "ugd_actlen" is zero.
+ */
+ data = malloc(ugd.ugd_actlen);
+ if (data == NULL)
+ return (NULL);
+
+ /* fetch actual descriptor */
+ ugd.ugd_data = data;
+ ugd.ugd_maxlen = ugd.ugd_actlen;
+ if (ioctl(fd, USB_GET_REPORT_DESC, &ugd) < 0) {
+ /* could not read descriptor */
+ free(data);
return (NULL);
+ }
+
+ /* check END_COLLECTION */
+ if (((unsigned char *)ugd.ugd_data)[ugd.ugd_actlen -1] != 0xC0) {
+ /* invalid end byte */
+ free(data);
+ return (NULL);
+ }
+
+ rep = hid_use_report_desc(data, ugd.ugd_actlen);
+
+ free(data);
- return hid_use_report_desc(rep.ucrd_data, (unsigned int)rep.ucrd_size);
+ return (rep);
}
report_desc_t
diff --git a/lib/libusbhid/descr_compat.c b/lib/libusbhid/descr_compat.c
new file mode 100644
index 0000000..3cbcdbf
--- /dev/null
+++ b/lib/libusbhid/descr_compat.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 1999 Lennart Augustsson <augustss@netbsd.org>
+ * 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.
+ *
+ * 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 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)
+ * 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.
+ */
+
+/*
+ * This file contains fallback-compatibility code for the old FreeBSD
+ * USB stack.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+
+#include <dev/usb/usb.h>
+
+#include "usbhid.h"
+#include "usbvar.h"
+
+int
+hid_set_immed_compat7(int fd, int enable)
+{
+ return (ioctl(fd, USB_SET_IMMED, &enable));
+}
+
+int
+hid_get_report_id_compat7(int fd)
+{
+ int temp = -1;
+
+ if (ioctl(fd, USB_GET_REPORT_ID, &temp) < 0)
+ return (-1);
+
+ return (temp);
+}
+
+report_desc_t
+hid_get_report_desc_compat7(int fd)
+{
+ struct usb_ctl_report_desc rep;
+
+ rep.ucrd_size = 0;
+ if (ioctl(fd, USB_GET_REPORT_DESC, &rep) < 0)
+ return (NULL);
+
+ return (hid_use_report_desc(rep.ucrd_data, (unsigned int)rep.ucrd_size));
+}
diff --git a/lib/libusbhid/usbhid.3 b/lib/libusbhid/usbhid.3
index a11709b..b4951f2 100644
--- a/lib/libusbhid/usbhid.3
+++ b/lib/libusbhid/usbhid.3
@@ -26,12 +26,13 @@
.\"
.\" $FreeBSD$
.\"
-.Dd December 29, 2001
+.Dd January 27, 2009
.Dt USBHID 3
.Os
.Sh NAME
.Nm usbhid ,
.Nm hid_get_report_desc ,
+.Nm hid_get_report_id ,
.Nm hid_use_report_desc ,
.Nm hid_dispose_report_desc ,
.Nm hid_start_parse ,
@@ -51,6 +52,10 @@
.In usbhid.h
.Ft report_desc_t
.Fn hid_get_report_desc "int file"
+.Ft int
+.Fn hid_get_report_id "int file"
+.Ft int
+.Fn hid_set_immed "int fd" "int enable"
.Ft report_desc_t
.Fn hid_use_report_desc "unsigned char *data" "unsigned int size"
.Ft void
@@ -94,7 +99,15 @@ which contains the data layout information and then use this information.
The routines can be divided into four parts: extraction of the descriptor,
parsing of the descriptor, translating to/from symbolic names, and
data manipulation.
+.Ss Synchronous HID operation
+Synchronous HID operation can be enabled or disabled by a call to
+.Fn hid_set_immed .
+If the second argument is zero synchronous HID operation is disabled.
+Else synchronous HID operation is enabled.
+The function returns a negative value on failure.
.Ss Descriptor Functions
+The report descriptor ID can be obtained by calling
+.Fn hid_get_report_id .
A report descriptor can be obtained by calling
.Fn hid_get_report_desc
with a file descriptor obtained by opening a
diff --git a/lib/libusbhid/usbhid.h b/lib/libusbhid/usbhid.h
index af3228f..b8751cd 100644
--- a/lib/libusbhid/usbhid.h
+++ b/lib/libusbhid/usbhid.h
@@ -87,6 +87,8 @@ __BEGIN_DECLS
report_desc_t hid_get_report_desc(int file);
report_desc_t hid_use_report_desc(unsigned char *data, unsigned int size);
void hid_dispose_report_desc(report_desc_t);
+int hid_get_report_id(int file);
+int hid_set_immed(int fd, int enable);
/* Parsing of a HID report descriptor, parse.c: */
hid_data_t hid_start_parse(report_desc_t d, int kindset, int id);
diff --git a/lib/libusbhid/usbvar.h b/lib/libusbhid/usbvar.h
index 7ed04e5..b8fbf37 100644
--- a/lib/libusbhid/usbvar.h
+++ b/lib/libusbhid/usbvar.h
@@ -34,3 +34,8 @@ struct report_desc {
unsigned char data[1];
};
+/* internal backwards compatibility functions */
+
+int hid_set_immed_compat7(int fd, int enable);
+int hid_get_report_id_compat7(int fd);
+report_desc_t hid_get_report_desc_compat7(int fd);
diff --git a/lib/msun/src/e_rem_pio2.c b/lib/msun/src/e_rem_pio2.c
index f68df9a..f94efe5 100644
--- a/lib/msun/src/e_rem_pio2.c
+++ b/lib/msun/src/e_rem_pio2.c
@@ -49,7 +49,7 @@ pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */
pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
#ifdef INLINE_REM_PIO2
-extern inline
+extern __gnu89_inline
#endif
int
__ieee754_rem_pio2(double x, double *y)
diff --git a/lib/msun/src/e_rem_pio2f.c b/lib/msun/src/e_rem_pio2f.c
index e07694c..7ec7b95 100644
--- a/lib/msun/src/e_rem_pio2f.c
+++ b/lib/msun/src/e_rem_pio2f.c
@@ -41,7 +41,7 @@ pio2_1 = 1.57079631090164184570e+00, /* 0x3FF921FB, 0x50000000 */
pio2_1t = 1.58932547735281966916e-08; /* 0x3E5110b4, 0x611A6263 */
#ifdef INLINE_REM_PIO2F
-extern inline
+extern __gnu89_inline
#endif
int
__ieee754_rem_pio2f(float x, double *y)
diff --git a/lib/msun/src/k_cosf.c b/lib/msun/src/k_cosf.c
index 30c301a..5084e85 100644
--- a/lib/msun/src/k_cosf.c
+++ b/lib/msun/src/k_cosf.c
@@ -31,7 +31,7 @@ C2 = -0x16c087e80f1e27.0p-62, /* -0.00138867637746099294692 */
C3 = 0x199342e0ee5069.0p-68; /* 0.0000243904487962774090654 */
#ifdef INLINE_KERNEL_COSDF
-extern inline
+extern __gnu89_inline
#endif
float
__kernel_cosdf(double x)
diff --git a/lib/msun/src/k_sinf.c b/lib/msun/src/k_sinf.c
index e390b50..c1b1d85 100644
--- a/lib/msun/src/k_sinf.c
+++ b/lib/msun/src/k_sinf.c
@@ -30,7 +30,7 @@ S3 = -0x1a00f9e2cae774.0p-65, /* -0.000198393348360966317347 */
S4 = 0x16cd878c3b46a7.0p-71; /* 0.0000027183114939898219064 */
#ifdef INLINE_KERNEL_SINDF
-extern inline
+extern __gnu89_inline
#endif
float
__kernel_sindf(double x)
diff --git a/lib/msun/src/k_tanf.c b/lib/msun/src/k_tanf.c
index f8152e2..d8b1ebf 100644
--- a/lib/msun/src/k_tanf.c
+++ b/lib/msun/src/k_tanf.c
@@ -33,7 +33,7 @@ T[] = {
};
#ifdef INLINE_KERNEL_TANDF
-extern inline
+extern __gnu89_inline
#endif
float
__kernel_tandf(double x, int iy)
diff --git a/lib/msun/src/math.h b/lib/msun/src/math.h
index 374f95f..521ee3f 100644
--- a/lib/msun/src/math.h
+++ b/lib/msun/src/math.h
@@ -55,8 +55,8 @@ extern const union __nan_un {
#ifdef __MATH_BUILTIN_CONSTANTS
#define HUGE_VALF __builtin_huge_valf()
#define HUGE_VALL __builtin_huge_vall()
-#define INFINITY __builtin_inf()
-#define NAN __builtin_nan("")
+#define INFINITY __builtin_inff()
+#define NAN __builtin_nanf("")
#else
#define HUGE_VALF (float)HUGE_VAL
#define HUGE_VALL (long double)HUGE_VAL
@@ -70,12 +70,12 @@ extern const union __nan_un {
/* XXX We need a <machine/math.h>. */
#if defined(__ia64__) || defined(__sparc64__)
-#define FP_FAST_FMA
+#define FP_FAST_FMA 1
#endif
#ifdef __ia64__
-#define FP_FAST_FMAL
+#define FP_FAST_FMAL 1
#endif
-#define FP_FAST_FMAF
+#define FP_FAST_FMAF 1
/* Symbolic constants to classify floating point numbers. */
#define FP_INFINITE 0x01
OpenPOWER on IntegriCloud