summaryrefslogtreecommitdiffstats
path: root/lib/libc
diff options
context:
space:
mode:
authorngie <ngie@FreeBSD.org>2015-11-16 02:00:12 +0000
committerngie <ngie@FreeBSD.org>2015-11-16 02:00:12 +0000
commitfd9367ff35d3ef67f52f8612ba6df3c487b90f4d (patch)
tree68c676723f5f9cd1d66be903cfdce6b37dcc3719 /lib/libc
parent3d588fbc9bc229fdd93d6aaf6340583c2bcaca9f (diff)
parentb708fe19431dfeacfe97dbc276190934bd53b483 (diff)
downloadFreeBSD-src-fd9367ff35d3ef67f52f8612ba6df3c487b90f4d.zip
FreeBSD-src-fd9367ff35d3ef67f52f8612ba6df3c487b90f4d.tar.gz
MFhead @ r290899
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/gen/getgrent.c15
-rw-r--r--lib/libc/gen/getpwent.c10
-rw-r--r--lib/libc/iconv/bsd_iconv.c44
-rw-r--r--lib/libc/iconv/citrus_esdb.c2
-rw-r--r--lib/libc/locale/ascii.c22
-rw-r--r--lib/libc/locale/big5.c32
-rw-r--r--lib/libc/locale/collate.c768
-rw-r--r--lib/libc/locale/collate.h107
-rw-r--r--lib/libc/locale/collcmp.c9
-rw-r--r--lib/libc/locale/euc.c438
-rw-r--r--lib/libc/locale/gb18030.c28
-rw-r--r--lib/libc/locale/gb2312.c31
-rw-r--r--lib/libc/locale/gbk.c28
-rw-r--r--lib/libc/locale/isctype.c4
-rw-r--r--lib/libc/locale/iswctype.c8
-rw-r--r--lib/libc/locale/mblocal.h23
-rw-r--r--lib/libc/locale/mbsnrtowcs.c10
-rw-r--r--lib/libc/locale/mskanji.c42
-rw-r--r--lib/libc/locale/nl_langinfo.c30
-rw-r--r--lib/libc/locale/none.c12
-rw-r--r--lib/libc/locale/rune.c107
-rw-r--r--lib/libc/locale/setrunelocale.c64
-rw-r--r--lib/libc/locale/table.c20
-rw-r--r--lib/libc/locale/utf8.c4
-rw-r--r--lib/libc/locale/wcsnrtombs.c12
-rw-r--r--lib/libc/locale/wctype.c4
-rw-r--r--lib/libc/net/getnameinfo.c16
-rw-r--r--lib/libc/resolv/res_data.c91
-rw-r--r--lib/libc/rpc/clnt_bcast.c9
-rw-r--r--lib/libc/rpc/clnt_vc.c3
-rw-r--r--lib/libc/rpc/getnetconfig.c11
-rw-r--r--lib/libc/rpc/mt_misc.c3
-rw-r--r--lib/libc/rpc/rpc_soc.c3
-rw-r--r--lib/libc/rpc/rpcb_clnt.c24
-rw-r--r--lib/libc/rpc/svc.c6
-rw-r--r--lib/libc/rpc/svc_dg.c3
-rw-r--r--lib/libc/rpc/svc_simple.c6
-rw-r--r--lib/libc/rpc/svc_vc.c6
-rw-r--r--lib/libc/sparc64/fpu/fpu.c2
-rw-r--r--lib/libc/stdio/fdopen.c4
-rw-r--r--lib/libc/stdio/findfp.c1
-rw-r--r--lib/libc/stdio/fmemopen.c3
-rw-r--r--lib/libc/stdio/fopen.c4
-rw-r--r--lib/libc/stdio/freopen.c5
-rw-r--r--lib/libc/stdio/ftell.c30
-rw-r--r--lib/libc/stdio/stdio.c2
-rw-r--r--lib/libc/string/strcoll.c108
-rw-r--r--lib/libc/string/strxfrm.c64
-rw-r--r--lib/libc/string/wcscoll.c213
-rw-r--r--lib/libc/string/wcsxfrm.c84
-rw-r--r--lib/libc/sys/cpuset.25
-rw-r--r--lib/libc/sys/cpuset_getaffinity.25
-rw-r--r--lib/libc/sys/ptrace.24
-rw-r--r--lib/libc/tests/Makefile1
-rw-r--r--lib/libc/tests/Makefile.netbsd-tests2
-rw-r--r--lib/libc/tests/c063/Makefile30
-rw-r--r--lib/libc/tests/gen/Makefile27
-rw-r--r--lib/libc/tests/gen/arc4random_test.c9
-rw-r--r--lib/libc/tests/gen/fmtcheck_test.c105
-rw-r--r--lib/libc/tests/gen/fmtmsg_test.c252
-rw-r--r--lib/libc/tests/gen/fnmatch_test.c188
-rw-r--r--lib/libc/tests/gen/fnmatch_testcases.h176
-rw-r--r--lib/libc/tests/gen/ftw_test.c127
-rw-r--r--lib/libc/tests/gen/popen_test.c251
-rw-r--r--lib/libc/tests/gen/posix_spawn_test.c103
-rw-r--r--lib/libc/tests/gen/test-fnmatch.c102
-rw-r--r--lib/libc/tests/gen/wordexp_test.c360
-rw-r--r--lib/libc/tests/locale/Makefile26
-rw-r--r--lib/libc/tests/locale/btowc_test.c71
-rw-r--r--lib/libc/tests/locale/c16rtomb_test.c166
-rw-r--r--lib/libc/tests/locale/iswctype_test.c122
-rw-r--r--lib/libc/tests/locale/mblen_test.c116
-rw-r--r--lib/libc/tests/locale/mbrlen_test.c126
-rw-r--r--lib/libc/tests/locale/mbrtoc16_test.c214
-rw-r--r--lib/libc/tests/locale/mbrtowc_test.c165
-rw-r--r--lib/libc/tests/locale/mbsnrtowcs_test.c195
-rw-r--r--lib/libc/tests/locale/mbsrtowcs_test.c153
-rw-r--r--lib/libc/tests/locale/mbstowcs_test.c111
-rw-r--r--lib/libc/tests/locale/mbtowc_test.c122
-rw-r--r--lib/libc/tests/locale/towctrans_test.c90
-rw-r--r--lib/libc/tests/locale/wcrtomb_test.c135
-rw-r--r--lib/libc/tests/locale/wcsnrtombs_test.c195
-rw-r--r--lib/libc/tests/locale/wcsrtombs_test.c156
-rw-r--r--lib/libc/tests/locale/wcstombs_test.c130
-rw-r--r--lib/libc/tests/locale/wctomb_test.c113
-rw-r--r--lib/libc/tests/net/Makefile19
-rw-r--r--lib/libc/tests/net/ether_test.c192
-rw-r--r--lib/libc/tests/net/eui64_aton_test.c104
-rw-r--r--lib/libc/tests/net/eui64_ntoa_test.c64
-rw-r--r--lib/libc/tests/net/test-eui64.h55
-rw-r--r--lib/libc/tests/setjmp/Makefile8
-rw-r--r--lib/libc/tests/ssp/Makefile12
-rw-r--r--lib/libc/tests/stdio/Makefile30
-rw-r--r--lib/libc/tests/stdio/fdopen_test.c225
-rw-r--r--lib/libc/tests/stdio/fmemopen2_test.c33
-rw-r--r--lib/libc/tests/stdio/fopen_test.c205
-rw-r--r--lib/libc/tests/stdio/freopen_test.c224
-rw-r--r--lib/libc/tests/stdio/getdelim_test.c236
-rw-r--r--lib/libc/tests/stdio/mkostemp_test.c185
-rw-r--r--lib/libc/tests/stdio/open_memstream_test.c201
-rw-r--r--lib/libc/tests/stdio/open_wmemstream_test.c201
-rw-r--r--lib/libc/tests/stdio/perror_test.c107
-rw-r--r--lib/libc/tests/stdio/print_positional_test.c156
-rw-r--r--lib/libc/tests/stdio/printbasic_test.c158
-rw-r--r--lib/libc/tests/stdio/printfloat_test.c390
-rw-r--r--lib/libc/tests/stdio/scanfloat_test.c316
-rw-r--r--lib/libc/tests/stdlib/Makefile8
-rw-r--r--lib/libc/tests/stdlib/heapsort_test.c71
-rw-r--r--lib/libc/tests/stdlib/mergesort_test.c71
-rw-r--r--lib/libc/tests/stdlib/qsort_test.c71
-rw-r--r--lib/libc/tests/stdlib/test-sort.h273
-rw-r--r--lib/libc/tests/string/Makefile45
-rw-r--r--lib/libc/tests/string/stpncpy_test.c110
-rw-r--r--lib/libc/tests/string/strerror_test.c206
-rw-r--r--lib/libc/tests/string/wcscasecmp_test.c128
-rw-r--r--lib/libc/tests/string/wcsnlen_test.c104
-rw-r--r--lib/libc/tests/tls_dso/Makefile2
117 files changed, 9960 insertions, 978 deletions
diff --git a/lib/libc/gen/getgrent.c b/lib/libc/gen/getgrent.c
index 31d2af1..2179fb2 100644
--- a/lib/libc/gen/getgrent.c
+++ b/lib/libc/gen/getgrent.c
@@ -660,14 +660,13 @@ __getgroupmembership(const char *uname, gid_t agroup, gid_t *groups,
NS_FALLBACK_CB(getgroupmembership_fallback)
{ NULL, NULL, NULL }
};
- int rv;
assert(uname != NULL);
/* groups may be NULL if just sizing when invoked with maxgrp = 0 */
assert(grpcnt != NULL);
*grpcnt = 0;
- rv = _nsdispatch(NULL, dtab, NSDB_GROUP, "getgroupmembership",
+ (void)_nsdispatch(NULL, dtab, NSDB_GROUP, "getgroupmembership",
defaultsrc, uname, agroup, groups, maxgrp, grpcnt);
/* too many groups found? */
@@ -1239,14 +1238,13 @@ compat_setgrent(void *retval, void *mdata, va_list ap)
int rv, stayopen;
#define set_setent(x, y) do { \
- unsigned int i; \
- \
- for (i = 0; i < (sizeof(x)/sizeof(x[0])) - 1; i++) \
+ int i; \
+ for (i = 0; i < (int)(nitems(x) - 1); i++) \
x[i].mdata = (void *)y; \
} while (0)
rv = compat_getstate(&st);
- if (rv != 0)
+ if (rv != 0)
return (NS_UNAVAIL);
switch ((enum constants)mdata) {
case SETGRENT:
@@ -1309,9 +1307,8 @@ compat_group(void *retval, void *mdata, va_list ap)
int rv, stayopen, *errnop;
#define set_lookup_type(x, y) do { \
- unsigned int i; \
- \
- for (i = 0; i < (sizeof(x)/sizeof(x[0])) - 1; i++) \
+ int i; \
+ for (i = 0; i < (int)(nitems(x) - 1); i++) \
x[i].mdata = (void *)y; \
} while (0)
diff --git a/lib/libc/gen/getpwent.c b/lib/libc/gen/getpwent.c
index 6546f587..8617ecc 100644
--- a/lib/libc/gen/getpwent.c
+++ b/lib/libc/gen/getpwent.c
@@ -1607,10 +1607,9 @@ compat_redispatch(struct compat_state *st, enum nss_lookup_type how,
{ NULL, NULL, NULL }
};
void *discard;
- int rv, e;
- unsigned int i;
+ int e, i, rv;
- for (i = 0; i < sizeof(dtab)/sizeof(dtab[0]) - 1; i++)
+ for (i = 0; i < (int)(nitems(dtab) - 1); i++)
dtab[i].mdata = (void *)lookup_how;
more:
pwd_init(pwd);
@@ -1703,9 +1702,8 @@ compat_setpwent(void *retval, void *mdata, va_list ap)
int rv, stayopen;
#define set_setent(x, y) do { \
- unsigned int i; \
- \
- for (i = 0; i < (sizeof(x)/sizeof(x[0])) - 1; i++) \
+ int i; \
+ for (i = 0; i < (int)(nitems(x) - 1); i++) \
x[i].mdata = (void *)y; \
} while (0)
diff --git a/lib/libc/iconv/bsd_iconv.c b/lib/libc/iconv/bsd_iconv.c
index e032a5b..e9ff688 100644
--- a/lib/libc/iconv/bsd_iconv.c
+++ b/lib/libc/iconv/bsd_iconv.c
@@ -207,43 +207,51 @@ __bsd_iconvlist(int (*do_one) (unsigned int, const char * const *,
const char * const *np;
char *curitem, *curkey, *slashpos;
size_t sz;
- unsigned int i, j;
+ unsigned int i, j, n;
i = 0;
+ names = NULL;
- if (__bsd___iconv_get_list(&list, &sz, true))
+ if (__bsd___iconv_get_list(&list, &sz, true)) {
list = NULL;
+ goto out;
+ }
qsort((void *)list, sz, sizeof(char *), qsort_helper);
while (i < sz) {
j = 0;
slashpos = strchr(list[i], '/');
- curkey = (char *)malloc(slashpos - list[i] + 2);
- names = (char **)malloc(sz * sizeof(char *));
- if ((curkey == NULL) || (names == NULL)) {
- __bsd___iconv_free_list(list, sz);
- return;
- }
- strlcpy(curkey, list[i], slashpos - list[i] + 1);
+ names = malloc(sz * sizeof(char *));
+ if (names == NULL)
+ goto out;
+ curkey = strndup(list[i], slashpos - list[i]);
+ if (curkey == NULL)
+ goto out;
names[j++] = curkey;
for (; (i < sz) && (memcmp(curkey, list[i], strlen(curkey)) == 0); i++) {
slashpos = strchr(list[i], '/');
- curitem = (char *)malloc(strlen(slashpos) + 1);
- if (curitem == NULL) {
- __bsd___iconv_free_list(list, sz);
- return;
- }
- strlcpy(curitem, &slashpos[1], strlen(slashpos) + 1);
- if (strcmp(curkey, curitem) == 0) {
+ if (strcmp(curkey, &slashpos[1]) == 0)
continue;
- }
+ curitem = strdup(&slashpos[1]);
+ if (curitem == NULL)
+ goto out;
names[j++] = curitem;
}
np = (const char * const *)names;
do_one(j, np, data);
+ for (n = 0; n < j; n++)
+ free(names[n]);
free(names);
+ names = NULL;
}
- __bsd___iconv_free_list(list, sz);
+out:
+ if (names != NULL) {
+ for (n = 0; n < j; n++)
+ free(names[n]);
+ free(names);
+ }
+ if (list != NULL)
+ __bsd___iconv_free_list(list, sz);
}
__inline const char *
diff --git a/lib/libc/iconv/citrus_esdb.c b/lib/libc/iconv/citrus_esdb.c
index 578cbc1..ed404a6 100644
--- a/lib/libc/iconv/citrus_esdb.c
+++ b/lib/libc/iconv/citrus_esdb.c
@@ -328,7 +328,7 @@ _citrus_esdb_get_list(char ***rlist, size_t *rnum, bool sorted)
(int)_region_size(&data),
(const char *)_region_head(&data));
if ((p = strchr(buf1, '/')) != NULL)
- memcpy(buf1, p + 1, strlen(p) - 1);
+ memmove(buf1, p + 1, strlen(p) - 1);
if ((p = strstr(buf1, ".esdb")) != NULL)
*p = '\0';
snprintf(buf, sizeof(buf), "%s/%.*s", buf1,
diff --git a/lib/libc/locale/ascii.c b/lib/libc/locale/ascii.c
index 784814d..3e625e4 100644
--- a/lib/libc/locale/ascii.c
+++ b/lib/libc/locale/ascii.c
@@ -1,4 +1,6 @@
-/*-
+/*
+ * Copyright 2013 Garrett D'Amore <garrett@damore.org>
+ * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved.
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
@@ -34,6 +36,8 @@
* 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.
+ *
+ * @(#)none.c 8.1 (Berkeley) 6/4/93
*/
#include <sys/cdefs.h>
@@ -61,7 +65,7 @@ static size_t _ascii_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
size_t, size_t, mbstate_t * __restrict);
int
-_ascii_init(struct xlocale_ctype *l,_RuneLocale *rl)
+_ascii_init(struct xlocale_ctype *l, _RuneLocale *rl)
{
l->__mbrtowc = _ascii_mbrtowc;
@@ -78,7 +82,6 @@ _ascii_init(struct xlocale_ctype *l,_RuneLocale *rl)
static int
_ascii_mbsinit(const mbstate_t *ps __unused)
{
-
/*
* Encoding is not state dependent - we are always in the
* initial state.
@@ -90,7 +93,6 @@ static size_t
_ascii_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
mbstate_t * __restrict ps __unused)
{
-
if (s == NULL)
/* Reset to initial shift state (no-op) */
return (0);
@@ -130,13 +132,12 @@ _ascii_mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src,
size_t nchr;
if (dst == NULL) {
- for (s = *src; nms > 0 && *s != '\0'; s++, nms--) {
- if (*s & 0x80) {
- errno = EILSEQ;
- return ((size_t)-1);
- }
+ s = memchr(*src, '\0', nms);
+ if (*s & 0x80) {
+ errno = EILSEQ;
+ return ((size_t)-1);
}
- return (s - *src);
+ return (s != NULL ? s - *src : nms);
}
s = *src;
@@ -189,4 +190,3 @@ _ascii_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
*src = s;
return (nchr);
}
-
diff --git a/lib/libc/locale/big5.c b/lib/libc/locale/big5.c
index 4b37265..c1f94d3 100644
--- a/lib/libc/locale/big5.c
+++ b/lib/libc/locale/big5.c
@@ -1,4 +1,6 @@
/*-
+ * Copyright 2013 Garrett D'Amore <garrett@damore.org>
+ * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved.
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
@@ -19,11 +21,7 @@
* 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. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. 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.
*
@@ -61,6 +59,12 @@ static size_t _BIG5_mbrtowc(wchar_t * __restrict, const char * __restrict,
static int _BIG5_mbsinit(const mbstate_t *);
static size_t _BIG5_wcrtomb(char * __restrict, wchar_t,
mbstate_t * __restrict);
+static size_t _BIG5_mbsnrtowcs(wchar_t * __restrict,
+ const char ** __restrict, size_t, size_t,
+ mbstate_t * __restrict);
+static size_t _BIG5_wcsnrtombs(char * __restrict,
+ const wchar_t ** __restrict, size_t, size_t,
+ mbstate_t * __restrict);
typedef struct {
wchar_t ch;
@@ -72,6 +76,8 @@ _BIG5_init(struct xlocale_ctype *l, _RuneLocale *rl)
l->__mbrtowc = _BIG5_mbrtowc;
l->__wcrtomb = _BIG5_wcrtomb;
+ l->__mbsnrtowcs = _BIG5_mbsnrtowcs;
+ l->__wcsnrtombs = _BIG5_wcsnrtombs;
l->__mbsinit = _BIG5_mbsinit;
l->runes = rl;
l->__mb_cur_max = 2;
@@ -147,7 +153,7 @@ _BIG5_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
wc = (wc << 8) | (*s++ & 0xff);
if (pwc != NULL)
*pwc = wc;
- return (2);
+ return (2);
} else {
if (pwc != NULL)
*pwc = wc;
@@ -178,3 +184,17 @@ _BIG5_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
*s = wc & 0xff;
return (1);
}
+
+static size_t
+_BIG5_mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src,
+ size_t nms, size_t len, mbstate_t * __restrict ps)
+{
+ return (__mbsnrtowcs_std(dst, src, nms, len, ps, _BIG5_mbrtowc));
+}
+
+static size_t
+_BIG5_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
+ size_t nwc, size_t len, mbstate_t * __restrict ps)
+{
+ return (__wcsnrtombs_std(dst, src, nwc, len, ps, _BIG5_wcrtomb));
+}
diff --git a/lib/libc/locale/collate.c b/lib/libc/locale/collate.c
index 56513f4..d0ed152 100644
--- a/lib/libc/locale/collate.c
+++ b/lib/libc/locale/collate.c
@@ -1,4 +1,6 @@
/*-
+ * Copyright 2014 Garrett D'Amore <garrett@damore.org>
+ * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
* at Electronni Visti IA, Kiev, Ukraine.
* All rights reserved.
@@ -28,66 +30,57 @@
* 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.
+ *
+ * Adapted to xlocale by John Marino <draco@marino.st>
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "namespace.h"
-#include <arpa/inet.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <wchar.h>
#include <errno.h>
#include <unistd.h>
-#include <sysexits.h>
+#include <fcntl.h>
#include "un-namespace.h"
#include "collate.h"
#include "setlocale.h"
#include "ldpart.h"
-
#include "libc_private.h"
-/*
- * To avoid modifying the original (single-threaded) code too much, we'll just
- * define the old globals as fields inside the table.
- *
- * We also modify the collation table test functions to search the thread-local
- * table first and the global table second.
- */
-#define __collate_substitute_nontrivial (table->__collate_substitute_nontrivial)
-#define __collate_substitute_table_ptr (table->__collate_substitute_table_ptr)
-#define __collate_char_pri_table_ptr (table->__collate_char_pri_table_ptr)
-#define __collate_chain_pri_table (table->__collate_chain_pri_table)
-int __collate_load_error;
-
-
struct xlocale_collate __xlocale_global_collate = {
- {{0}, "C"}, 1, 0
+ {{0}, "C"}, 1, 0, 0, 0
};
- struct xlocale_collate __xlocale_C_collate = {
- {{0}, "C"}, 1, 0
+struct xlocale_collate __xlocale_C_collate = {
+ {{0}, "C"}, 1, 0, 0, 0
};
-void __collate_err(int ex, const char *f) __dead2;
-
-int
+static int
__collate_load_tables_l(const char *encoding, struct xlocale_collate *table);
static void
destruct_collate(void *t)
{
struct xlocale_collate *table = t;
- if (__collate_chain_pri_table) {
- free(__collate_chain_pri_table);
+ if (table->map && (table->maplen > 0)) {
+ (void) munmap(table->map, table->maplen);
}
free(t);
}
void *
-__collate_load(const char *encoding, locale_t unused)
+__collate_load(const char *encoding, __unused locale_t unused)
{
if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) {
return &__xlocale_C_collate;
@@ -109,237 +102,602 @@ __collate_load(const char *encoding, locale_t unused)
int
__collate_load_tables(const char *encoding)
{
- int ret = __collate_load_tables_l(encoding, &__xlocale_global_collate);
- __collate_load_error = __xlocale_global_collate.__collate_load_error;
- return ret;
+
+ return (__collate_load_tables_l(encoding, &__xlocale_global_collate));
}
int
__collate_load_tables_l(const char *encoding, struct xlocale_collate *table)
{
- FILE *fp;
- int i, saverr, chains;
- uint32_t u32;
- char strbuf[STR_LEN], buf[PATH_MAX];
- void *TMP_substitute_table, *TMP_char_pri_table, *TMP_chain_pri_table;
+ int i, chains, z;
+ char *buf;
+ char *TMP;
+ char *map;
+ collate_info_t *info;
+ struct stat sbuf;
+ int fd;
+
+ table->__collate_load_error = 1;
/* 'encoding' must be already checked. */
if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) {
- table->__collate_load_error = 1;
return (_LDP_CACHE);
}
- /* 'PathLocale' must be already set & checked. */
- /* Range checking not needed, encoding has fixed size */
- (void)strcpy(buf, _PathLocale);
- (void)strcat(buf, "/");
- (void)strcat(buf, encoding);
- (void)strcat(buf, "/LC_COLLATE");
- if ((fp = fopen(buf, "re")) == NULL)
+ asprintf(&buf, "%s/%s/LC_COLLATE", _PathLocale, encoding);
+ if (buf == NULL)
return (_LDP_ERROR);
- if (fread(strbuf, sizeof(strbuf), 1, fp) != 1) {
- saverr = errno;
- (void)fclose(fp);
- errno = saverr;
+ if ((fd = _open(buf, O_RDONLY)) < 0) {
+ free(buf);
return (_LDP_ERROR);
}
- chains = -1;
- if (strcmp(strbuf, COLLATE_VERSION) == 0)
- chains = 0;
- else if (strcmp(strbuf, COLLATE_VERSION1_2) == 0)
- chains = 1;
- if (chains < 0) {
- (void)fclose(fp);
- errno = EFTYPE;
+ free(buf);
+ if (_fstat(fd, &sbuf) < 0) {
+ (void) _close(fd);
return (_LDP_ERROR);
}
- if (chains) {
- if (fread(&u32, sizeof(u32), 1, fp) != 1) {
- saverr = errno;
- (void)fclose(fp);
- errno = saverr;
- return (_LDP_ERROR);
- }
- if ((chains = (int)ntohl(u32)) < 1) {
- (void)fclose(fp);
- errno = EFTYPE;
- return (_LDP_ERROR);
- }
- } else
- chains = TABLE_SIZE;
-
- if ((TMP_substitute_table =
- malloc(sizeof(__collate_substitute_table))) == NULL) {
- saverr = errno;
- (void)fclose(fp);
- errno = saverr;
+ if (sbuf.st_size < (COLLATE_STR_LEN + sizeof (info))) {
+ (void) _close(fd);
+ errno = EINVAL;
return (_LDP_ERROR);
}
- if ((TMP_char_pri_table =
- malloc(sizeof(__collate_char_pri_table))) == NULL) {
- saverr = errno;
- free(TMP_substitute_table);
- (void)fclose(fp);
- errno = saverr;
+ map = mmap(NULL, sbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ (void) _close(fd);
+ if ((TMP = map) == NULL) {
return (_LDP_ERROR);
}
- if ((TMP_chain_pri_table =
- malloc(sizeof(*__collate_chain_pri_table) * chains)) == NULL) {
- saverr = errno;
- free(TMP_substitute_table);
- free(TMP_char_pri_table);
- (void)fclose(fp);
- errno = saverr;
+
+ if (strncmp(TMP, COLLATE_VERSION, COLLATE_STR_LEN) != 0) {
+ (void) munmap(map, sbuf.st_size);
+ errno = EINVAL;
return (_LDP_ERROR);
}
+ TMP += COLLATE_STR_LEN;
-#define FREAD(a, b, c, d) \
-{ \
- if (fread(a, b, c, d) != c) { \
- saverr = errno; \
- free(TMP_substitute_table); \
- free(TMP_char_pri_table); \
- free(TMP_chain_pri_table); \
- (void)fclose(d); \
- errno = saverr; \
- return (_LDP_ERROR); \
- } \
-}
+ info = (void *)TMP;
+ TMP += sizeof (*info);
+
+ if ((info->directive_count < 1) ||
+ (info->directive_count >= COLL_WEIGHTS_MAX) ||
+ ((chains = info->chain_count) < 0)) {
+ (void) munmap(map, sbuf.st_size);
+ errno = EINVAL;
+ return (_LDP_ERROR);
+ }
- FREAD(TMP_substitute_table, sizeof(__collate_substitute_table), 1, fp);
- FREAD(TMP_char_pri_table, sizeof(__collate_char_pri_table), 1, fp);
- FREAD(TMP_chain_pri_table,
- sizeof(*__collate_chain_pri_table), chains, fp);
- (void)fclose(fp);
-
- if (__collate_substitute_table_ptr != NULL)
- free(__collate_substitute_table_ptr);
- __collate_substitute_table_ptr = TMP_substitute_table;
- if (__collate_char_pri_table_ptr != NULL)
- free(__collate_char_pri_table_ptr);
- __collate_char_pri_table_ptr = TMP_char_pri_table;
- for (i = 0; i < UCHAR_MAX + 1; i++) {
- __collate_char_pri_table[i].prim =
- ntohl(__collate_char_pri_table[i].prim);
- __collate_char_pri_table[i].sec =
- ntohl(__collate_char_pri_table[i].sec);
+ i = (sizeof (collate_char_t) * (UCHAR_MAX + 1)) +
+ (sizeof (collate_chain_t) * chains) +
+ (sizeof (collate_large_t) * info->large_count);
+ for (z = 0; z < info->directive_count; z++) {
+ i += sizeof (collate_subst_t) * info->subst_count[z];
}
- if (__collate_chain_pri_table != NULL)
- free(__collate_chain_pri_table);
- __collate_chain_pri_table = TMP_chain_pri_table;
- for (i = 0; i < chains; i++) {
- __collate_chain_pri_table[i].prim =
- ntohl(__collate_chain_pri_table[i].prim);
- __collate_chain_pri_table[i].sec =
- ntohl(__collate_chain_pri_table[i].sec);
+ if (i != (sbuf.st_size - (TMP - map))) {
+ (void) munmap(map, sbuf.st_size);
+ errno = EINVAL;
+ return (_LDP_ERROR);
}
- __collate_substitute_nontrivial = 0;
- for (i = 0; i < UCHAR_MAX + 1; i++) {
- if (__collate_substitute_table[i][0] != i ||
- __collate_substitute_table[i][1] != 0) {
- __collate_substitute_nontrivial = 1;
- break;
+
+ table->info = info;
+ table->char_pri_table = (void *)TMP;
+ TMP += sizeof (collate_char_t) * (UCHAR_MAX + 1);
+
+ for (z = 0; z < info->directive_count; z++) {
+ if (info->subst_count[z] > 0) {
+ table->subst_table[z] = (void *)TMP;
+ TMP += info->subst_count[z] * sizeof (collate_subst_t);
+ } else {
+ table->subst_table[z] = NULL;
}
}
- table->__collate_load_error = 0;
+ if (chains > 0) {
+ table->chain_pri_table = (void *)TMP;
+ TMP += chains * sizeof (collate_chain_t);
+ } else
+ table->chain_pri_table = NULL;
+ if (info->large_count > 0)
+ table->large_pri_table = (void *)TMP;
+ else
+ table->large_pri_table = NULL;
+
+ table->__collate_load_error = 0;
return (_LDP_LOADED);
}
-u_char *
-__collate_substitute(struct xlocale_collate *table, const u_char *s)
+static const int32_t *
+substsearch(struct xlocale_collate *table, const wchar_t key, int pass)
{
- int dest_len, len, nlen;
- int delta = strlen(s);
- u_char *dest_str = NULL;
-
- if (s == NULL || *s == '\0')
- return (__collate_strdup(""));
- delta += delta / 8;
- dest_str = malloc(dest_len = delta);
- if (dest_str == NULL)
- __collate_err(EX_OSERR, __func__);
- len = 0;
- while (*s) {
- nlen = len + strlen(__collate_substitute_table[*s]);
- if (dest_len <= nlen) {
- dest_str = reallocf(dest_str, dest_len = nlen + delta);
- if (dest_str == NULL)
- __collate_err(EX_OSERR, __func__);
+ const collate_subst_t *p;
+ int n = table->info->subst_count[pass];
+
+ if (n == 0)
+ return (NULL);
+
+ if (pass >= table->info->directive_count)
+ return (NULL);
+
+ if (!(key & COLLATE_SUBST_PRIORITY))
+ return (NULL);
+
+ p = table->subst_table[pass] + (key & ~COLLATE_SUBST_PRIORITY);
+ assert(p->key == key);
+ return (p->pri);
+}
+
+static collate_chain_t *
+chainsearch(struct xlocale_collate *table, const wchar_t *key, int *len)
+{
+ int low = 0;
+ int high = table->info->chain_count - 1;;
+ int next, compar, l;
+ collate_chain_t *p;
+ collate_chain_t *tab = table->chain_pri_table;
+
+ if (high < 0)
+ return (NULL);
+
+ while (low <= high) {
+ next = (low + high) / 2;
+ p = tab + next;
+ compar = *key - *p->str;
+ if (compar == 0) {
+ l = wcsnlen(p->str, COLLATE_STR_LEN);
+ compar = wcsncmp(key, p->str, l);
+ if (compar == 0) {
+ *len = l;
+ return (p);
+ }
}
- (void)strcpy(dest_str + len, __collate_substitute_table[*s++]);
- len = nlen;
+ if (compar > 0)
+ low = next + 1;
+ else
+ high = next - 1;
+ }
+ return (NULL);
+}
+
+static collate_large_t *
+largesearch(struct xlocale_collate *table, const wchar_t key)
+{
+ int low = 0;
+ int high = table->info->large_count - 1;
+ int next, compar;
+ collate_large_t *p;
+ collate_large_t *tab = table->large_pri_table;
+
+ if (high < 0)
+ return (NULL);
+
+ while (low <= high) {
+ next = (low + high) / 2;
+ p = tab + next;
+ compar = key - p->val;
+ if (compar == 0)
+ return (p);
+ if (compar > 0)
+ low = next + 1;
+ else
+ high = next - 1;
}
- return (dest_str);
+ return (NULL);
}
void
-__collate_lookup(struct xlocale_collate *table, const u_char *t, int *len, int *prim, int *sec)
+_collate_lookup(struct xlocale_collate *table, const wchar_t *t, int *len,
+ int *pri, int which, const int **state)
{
- struct __collate_st_chain_pri *p2;
+ collate_chain_t *p2;
+ collate_large_t *match;
+ int p, l;
+ const int *sptr;
+
+ /*
+ * If this is the "last" pass for the UNDEFINED, then
+ * we just return the priority itself.
+ */
+ if (which >= table->info->directive_count) {
+ *pri = *t;
+ *len = 1;
+ *state = NULL;
+ return;
+ }
+
+ /*
+ * If we have remaining substitution data from a previous
+ * call, consume it first.
+ */
+ if ((sptr = *state) != NULL) {
+ *pri = *sptr;
+ sptr++;
+ if ((sptr == *state) || (sptr == NULL))
+ *state = NULL;
+ else
+ *state = sptr;
+ *len = 0;
+ return;
+ }
+ /* No active substitutions */
*len = 1;
- *prim = *sec = 0;
- for (p2 = __collate_chain_pri_table; p2->str[0] != '\0'; p2++) {
- if (*t == p2->str[0] &&
- strncmp(t, p2->str, strlen(p2->str)) == 0) {
- *len = strlen(p2->str);
- *prim = p2->prim;
- *sec = p2->sec;
- return;
+
+ /*
+ * Check for composites such as dipthongs that collate as a
+ * single element (aka chains or collating-elements).
+ */
+ if (((p2 = chainsearch(table, t, &l)) != NULL) &&
+ ((p = p2->pri[which]) >= 0)) {
+
+ *len = l;
+ *pri = p;
+
+ } else if (*t <= UCHAR_MAX) {
+
+ /*
+ * Character is a small (8-bit) character.
+ * We just look these up directly for speed.
+ */
+ *pri = table->char_pri_table[*t].pri[which];
+
+ } else if ((table->info->large_count > 0) &&
+ ((match = largesearch(table, *t)) != NULL)) {
+
+ /*
+ * Character was found in the extended table.
+ */
+ *pri = match->pri.pri[which];
+
+ } else {
+ /*
+ * Character lacks a specific definition.
+ */
+ if (table->info->directive[which] & DIRECTIVE_UNDEFINED) {
+ /* Mask off sign bit to prevent ordering confusion. */
+ *pri = (*t & COLLATE_MAX_PRIORITY);
+ } else {
+ *pri = table->info->undef_pri[which];
+ }
+ /* No substitutions for undefined characters! */
+ return;
+ }
+
+ /*
+ * Try substituting (expanding) the character. We are
+ * currently doing this *after* the chain compression. I
+ * think it should not matter, but this way might be slightly
+ * faster.
+ *
+ * We do this after the priority search, as this will help us
+ * to identify a single key value. In order for this to work,
+ * its important that the priority assigned to a given element
+ * to be substituted be unique for that level. The localedef
+ * code ensures this for us.
+ */
+ if ((sptr = substsearch(table, *pri, which)) != NULL) {
+ if ((*pri = *sptr) > 0) {
+ sptr++;
+ *state = *sptr ? sptr : NULL;
}
}
- *prim = __collate_char_pri_table[*t].prim;
- *sec = __collate_char_pri_table[*t].sec;
+
}
-u_char *
-__collate_strdup(u_char *s)
+/*
+ * This is the meaty part of wcsxfrm & strxfrm. Note that it does
+ * NOT NULL terminate. That is left to the caller.
+ */
+size_t
+_collate_wxfrm(struct xlocale_collate *table, const wchar_t *src, wchar_t *xf,
+ size_t room)
{
- u_char *t = strdup(s);
+ int pri;
+ int len;
+ const wchar_t *t;
+ wchar_t *tr = NULL;
+ int direc;
+ int pass;
+ const int32_t *state;
+ size_t want = 0;
+ size_t need = 0;
+ int ndir = table->info->directive_count;
+
+ assert(src);
+
+ for (pass = 0; pass <= ndir; pass++) {
+
+ state = NULL;
+
+ if (pass != 0) {
+ /* insert level separator from the previous pass */
+ if (room) {
+ *xf++ = 1;
+ room--;
+ }
+ want++;
+ }
+
+ /* special pass for undefined */
+ if (pass == ndir) {
+ direc = DIRECTIVE_FORWARD | DIRECTIVE_UNDEFINED;
+ } else {
+ direc = table->info->directive[pass];
+ }
- if (t == NULL)
- __collate_err(EX_OSERR, __func__);
- return (t);
+ t = src;
+
+ if (direc & DIRECTIVE_BACKWARD) {
+ wchar_t *bp, *fp, c;
+ free(tr);
+ if ((tr = wcsdup(t)) == NULL) {
+ errno = ENOMEM;
+ goto fail;
+ }
+ bp = tr;
+ fp = tr + wcslen(tr) - 1;
+ while (bp < fp) {
+ c = *bp;
+ *bp++ = *fp;
+ *fp-- = c;
+ }
+ t = (const wchar_t *)tr;
+ }
+
+ if (direc & DIRECTIVE_POSITION) {
+ while (*t || state) {
+ _collate_lookup(table, t, &len, &pri, pass, &state);
+ t += len;
+ if (pri <= 0) {
+ if (pri < 0) {
+ errno = EINVAL;
+ goto fail;
+ }
+ pri = COLLATE_MAX_PRIORITY;
+ }
+ if (room) {
+ *xf++ = pri;
+ room--;
+ }
+ want++;
+ need = want;
+ }
+ } else {
+ while (*t || state) {
+ _collate_lookup(table, t, &len, &pri, pass, &state);
+ t += len;
+ if (pri <= 0) {
+ if (pri < 0) {
+ errno = EINVAL;
+ goto fail;
+ }
+ continue;
+ }
+ if (room) {
+ *xf++ = pri;
+ room--;
+ }
+ want++;
+ need = want;
+ }
+ }
+ }
+ free(tr);
+ return (need);
+
+fail:
+ free(tr);
+ return ((size_t)(-1));
}
-void
-__collate_err(int ex, const char *f)
+/*
+ * In the non-POSIX case, we transform each character into a string of
+ * characters representing the character's priority. Since char is usually
+ * signed, we are limited by 7 bits per byte. To avoid zero, we need to add
+ * XFRM_OFFSET, so we can't use a full 7 bits. For simplicity, we choose 6
+ * bits per byte.
+ *
+ * It turns out that we sometimes have real priorities that are
+ * 31-bits wide. (But: be careful using priorities where the high
+ * order bit is set -- i.e. the priority is negative. The sort order
+ * may be surprising!)
+ *
+ * TODO: This would be a good area to optimize somewhat. It turns out
+ * that real prioririties *except for the last UNDEFINED pass* are generally
+ * very small. We need the localedef code to precalculate the max
+ * priority for us, and ideally also give us a mask, and then we could
+ * severely limit what we expand to.
+ */
+#define XFRM_BYTES 6
+#define XFRM_OFFSET ('0') /* make all printable characters */
+#define XFRM_SHIFT 6
+#define XFRM_MASK ((1 << XFRM_SHIFT) - 1)
+#define XFRM_SEP ('.') /* chosen to be less than XFRM_OFFSET */
+
+static int
+xfrm(struct xlocale_collate *table, unsigned char *p, int pri, int pass)
{
- const char *s;
- int serrno = errno;
-
- s = _getprogname();
- _write(STDERR_FILENO, s, strlen(s));
- _write(STDERR_FILENO, ": ", 2);
- s = f;
- _write(STDERR_FILENO, s, strlen(s));
- _write(STDERR_FILENO, ": ", 2);
- s = strerror(serrno);
- _write(STDERR_FILENO, s, strlen(s));
- _write(STDERR_FILENO, "\n", 1);
- exit(ex);
+ /* we use unsigned to ensure zero fill on right shift */
+ uint32_t val = (uint32_t)table->info->pri_count[pass];
+ int nc = 0;
+
+ while (val) {
+ *p = (pri & XFRM_MASK) + XFRM_OFFSET;
+ pri >>= XFRM_SHIFT;
+ val >>= XFRM_SHIFT;
+ p++;
+ nc++;
+ }
+ return (nc);
}
-#ifdef COLLATE_DEBUG
-void
-__collate_print_tables()
+size_t
+_collate_sxfrm(struct xlocale_collate *table, const wchar_t *src, char *xf,
+ size_t room)
{
- int i;
- struct __collate_st_chain_pri *p2;
-
- printf("Substitute table:\n");
- for (i = 0; i < UCHAR_MAX + 1; i++)
- if (i != *__collate_substitute_table[i])
- printf("\t'%c' --> \"%s\"\n", i,
- __collate_substitute_table[i]);
- printf("Chain priority table:\n");
- for (p2 = __collate_chain_pri_table; p2->str[0] != '\0'; p2++)
- printf("\t\"%s\" : %d %d\n", p2->str, p2->prim, p2->sec);
- printf("Char priority table:\n");
- for (i = 0; i < UCHAR_MAX + 1; i++)
- printf("\t'%c' : %d %d\n", i, __collate_char_pri_table[i].prim,
- __collate_char_pri_table[i].sec);
+ int pri;
+ int len;
+ const wchar_t *t;
+ wchar_t *tr = NULL;
+ int direc;
+ int pass;
+ const int32_t *state;
+ size_t want = 0;
+ size_t need = 0;
+ int b;
+ uint8_t buf[XFRM_BYTES];
+ int ndir = table->info->directive_count;
+
+ assert(src);
+
+ for (pass = 0; pass <= ndir; pass++) {
+
+ state = NULL;
+
+ if (pass != 0) {
+ /* insert level separator from the previous pass */
+ if (room) {
+ *xf++ = XFRM_SEP;
+ room--;
+ }
+ want++;
+ }
+
+ /* special pass for undefined */
+ if (pass == ndir) {
+ direc = DIRECTIVE_FORWARD | DIRECTIVE_UNDEFINED;
+ } else {
+ direc = table->info->directive[pass];
+ }
+
+ t = src;
+
+ if (direc & DIRECTIVE_BACKWARD) {
+ wchar_t *bp, *fp, c;
+ free(tr);
+ if ((tr = wcsdup(t)) == NULL) {
+ errno = ENOMEM;
+ goto fail;
+ }
+ bp = tr;
+ fp = tr + wcslen(tr) - 1;
+ while (bp < fp) {
+ c = *bp;
+ *bp++ = *fp;
+ *fp-- = c;
+ }
+ t = (const wchar_t *)tr;
+ }
+
+ if (direc & DIRECTIVE_POSITION) {
+ while (*t || state) {
+
+ _collate_lookup(table, t, &len, &pri, pass, &state);
+ t += len;
+ if (pri <= 0) {
+ if (pri < 0) {
+ errno = EINVAL;
+ goto fail;
+ }
+ pri = COLLATE_MAX_PRIORITY;
+ }
+
+ b = xfrm(table, buf, pri, pass);
+ want += b;
+ if (room) {
+ while (b) {
+ b--;
+ if (room) {
+ *xf++ = buf[b];
+ room--;
+ }
+ }
+ }
+ need = want;
+ }
+ } else {
+ while (*t || state) {
+ _collate_lookup(table, t, &len, &pri, pass, &state);
+ t += len;
+ if (pri <= 0) {
+ if (pri < 0) {
+ errno = EINVAL;
+ goto fail;
+ }
+ continue;
+ }
+
+ b = xfrm(table, buf, pri, pass);
+ want += b;
+ if (room) {
+
+ while (b) {
+ b--;
+ if (room) {
+ *xf++ = buf[b];
+ room--;
+ }
+ }
+ }
+ need = want;
+ }
+ }
+ }
+ free(tr);
+ return (need);
+
+fail:
+ free(tr);
+ return ((size_t)(-1));
+}
+
+/*
+ * __collate_equiv_value returns the primary collation value for the given
+ * collating symbol specified by str and len. Zero or negative is returned
+ * if the collating symbol was not found. This function is used by bracket
+ * code in the TRE regex library.
+ */
+int
+__collate_equiv_value(locale_t locale, const wchar_t *str, size_t len)
+{
+ int32_t e;
+
+ if (len < 1 || len >= COLLATE_STR_LEN)
+ return (-1);
+
+ FIX_LOCALE(locale);
+ struct xlocale_collate *table =
+ (struct xlocale_collate*)locale->components[XLC_COLLATE];
+
+ if (table->__collate_load_error)
+ return ((len == 1 && *str <= UCHAR_MAX) ? *str : -1);
+
+ if (len == 1) {
+ e = -1;
+ if (*str <= UCHAR_MAX)
+ e = table->char_pri_table[*str].pri[0];
+ else if (table->info->large_count > 0) {
+ collate_large_t *match_large;
+ match_large = largesearch(table, *str);
+ if (match_large)
+ e = match_large->pri.pri[0];
+ }
+ if (e == 0)
+ return (1);
+ return (e > 0 ? e : 0);
+ }
+ if (table->info->chain_count > 0) {
+ wchar_t name[COLLATE_STR_LEN];
+ collate_chain_t *match_chain;
+ int clen;
+
+ wcsncpy (name, str, len);
+ name[len] = 0;
+ match_chain = chainsearch(table, name, &clen);
+ if (match_chain) {
+ e = match_chain->pri[0];
+ if (e == 0)
+ return (1);
+ return (e < 0 ? -e : e);
+ }
+ }
+ return (0);
}
-#endif
diff --git a/lib/libc/locale/collate.h b/lib/libc/locale/collate.h
index ad034d4..9812589 100644
--- a/lib/libc/locale/collate.h
+++ b/lib/libc/locale/collate.h
@@ -1,4 +1,5 @@
/*-
+ * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
* at Electronni Visti IA, Kiev, Ukraine.
* All rights reserved.
@@ -40,42 +41,98 @@
#include <limits.h>
#include "xlocale_private.h"
-#define STR_LEN 10
-#define TABLE_SIZE 100
-#define COLLATE_VERSION "1.0\n"
-#define COLLATE_VERSION1_2 "1.2\n"
+/*
+ * Work around buildworld bootstrapping from older systems whose limits.h
+ * sets COLL_WEIGHTS_MAX to 0.
+ */
+#if COLL_WEIGHTS_MAX == 0
+#undef COLL_WEIGHTS_MAX
+#define COLL_WEIGHTS_MAX 10
+#endif
-struct __collate_st_char_pri {
- int prim, sec;
-};
-struct __collate_st_chain_pri {
- u_char str[STR_LEN];
- int prim, sec;
-};
+#define COLLATE_STR_LEN 24 /* should be 64-bit multiple */
+#define COLLATE_VERSION "BSD 1.0\n"
+
+#define COLLATE_MAX_PRIORITY (0x7fffffff) /* max signed value */
+#define COLLATE_SUBST_PRIORITY (0x40000000) /* bit indicates subst table */
-#define __collate_substitute_table (*__collate_substitute_table_ptr)
-#define __collate_char_pri_table (*__collate_char_pri_table_ptr)
+#define DIRECTIVE_UNDEF 0x00
+#define DIRECTIVE_FORWARD 0x01
+#define DIRECTIVE_BACKWARD 0x02
+#define DIRECTIVE_POSITION 0x04
+#define DIRECTIVE_UNDEFINED 0x08 /* special last weight for UNDEFINED */
+
+#define DIRECTIVE_DIRECTION_MASK (DIRECTIVE_FORWARD | DIRECTIVE_BACKWARD)
+
+/*
+ * The collate file format is as follows:
+ *
+ * char version[COLLATE_STR_LEN]; // must be COLLATE_VERSION
+ * collate_info_t info; // see below, includes padding
+ * collate_char_pri_t char_data[256]; // 8 bit char values
+ * collate_subst_t subst[*]; // 0 or more substitutions
+ * collate_chain_pri_t chains[*]; // 0 or more chains
+ * collate_large_pri_t large[*]; // extended char priorities
+ *
+ * Note that all structures must be 32-bit aligned, as each structure
+ * contains 32-bit member fields. The entire file is mmap'd, so its
+ * critical that alignment be observed. It is not generally safe to
+ * use any 64-bit values in the structures.
+ */
+
+typedef struct collate_info {
+ uint8_t directive_count;
+ uint8_t directive[COLL_WEIGHTS_MAX];
+ int32_t pri_count[COLL_WEIGHTS_MAX];
+ int32_t flags;
+ int32_t chain_count;
+ int32_t large_count;
+ int32_t subst_count[COLL_WEIGHTS_MAX];
+ int32_t undef_pri[COLL_WEIGHTS_MAX];
+} collate_info_t;
+
+typedef struct collate_char {
+ int32_t pri[COLL_WEIGHTS_MAX];
+} collate_char_t;
+
+typedef struct collate_chain {
+ wchar_t str[COLLATE_STR_LEN];
+ int32_t pri[COLL_WEIGHTS_MAX];
+} collate_chain_t;
+
+typedef struct collate_large {
+ int32_t val;
+ collate_char_t pri;
+} collate_large_t;
+
+typedef struct collate_subst {
+ int32_t key;
+ int32_t pri[COLLATE_STR_LEN];
+} collate_subst_t;
struct xlocale_collate {
struct xlocale_component header;
int __collate_load_error;
- int __collate_substitute_nontrivial;
+ char * map;
+ size_t maplen;
- u_char (*__collate_substitute_table_ptr)[UCHAR_MAX + 1][STR_LEN];
- struct __collate_st_char_pri (*__collate_char_pri_table_ptr)[UCHAR_MAX + 1];
- struct __collate_st_chain_pri *__collate_chain_pri_table;
+ collate_info_t *info;
+ collate_char_t *char_pri_table;
+ collate_large_t *large_pri_table;
+ collate_chain_t *chain_pri_table;
+ collate_subst_t *subst_table[COLL_WEIGHTS_MAX];
};
-
__BEGIN_DECLS
-u_char *__collate_strdup(u_char *);
-u_char *__collate_substitute(struct xlocale_collate *, const u_char *);
int __collate_load_tables(const char *);
-void __collate_lookup(struct xlocale_collate *, const u_char *, int *, int *, int *);
-int __collate_range_cmp(struct xlocale_collate *, int, int);
-#ifdef COLLATE_DEBUG
-void __collate_print_tables(void);
-#endif
+int __collate_equiv_value(locale_t, const wchar_t *, size_t);
+void _collate_lookup(struct xlocale_collate *,const wchar_t *, int *, int *,
+ int, const int **);
+int __collate_range_cmp(struct xlocale_collate *, wchar_t, wchar_t);
+size_t _collate_wxfrm(struct xlocale_collate *, const wchar_t *, wchar_t *,
+ size_t);
+size_t _collate_sxfrm(struct xlocale_collate *, const wchar_t *, char *,
+ size_t);
__END_DECLS
#endif /* !_COLLATE_H_ */
diff --git a/lib/libc/locale/collcmp.c b/lib/libc/locale/collcmp.c
index aa17afd..102fbfb 100644
--- a/lib/libc/locale/collcmp.c
+++ b/lib/libc/locale/collcmp.c
@@ -33,6 +33,7 @@
__FBSDID("$FreeBSD$");
#include <string.h>
+#include <wchar.h>
#include <xlocale.h>
#include "collate.h"
@@ -40,13 +41,15 @@ __FBSDID("$FreeBSD$");
* Compare two characters using collate
*/
-int __collate_range_cmp(struct xlocale_collate *table, int c1, int c2)
+int __collate_range_cmp(struct xlocale_collate *table, wchar_t c1, wchar_t c2)
{
- static char s1[2], s2[2];
+ wchar_t s1[2], s2[2];
s1[0] = c1;
+ s1[1] = 0;
s2[0] = c2;
+ s2[1] = 0;
struct _xlocale l = {{0}};
l.components[XLC_COLLATE] = (struct xlocale_component *)table;
- return (strcoll_l(s1, s2, &l));
+ return (wcscoll_l(s1, s2, &l));
}
diff --git a/lib/libc/locale/euc.c b/lib/libc/locale/euc.c
index 26ad413..c2a2e3b 100644
--- a/lib/libc/locale/euc.c
+++ b/lib/libc/locale/euc.c
@@ -1,4 +1,6 @@
/*-
+ * Copyright 2013 Garrett D'Amore <garrett@damore.org>
+ * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved.
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
@@ -19,11 +21,7 @@
* 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. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. 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.
*
@@ -56,17 +54,56 @@ __FBSDID("$FreeBSD$");
extern int __mb_sb_limit;
-static size_t _EUC_mbrtowc(wchar_t * __restrict, const char * __restrict,
+static size_t _EUC_mbrtowc_impl(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict, uint8_t, uint8_t, uint8_t, uint8_t);
+static size_t _EUC_wcrtomb_impl(char * __restrict, wchar_t,
+ mbstate_t * __restrict, uint8_t, uint8_t, uint8_t, uint8_t);
+
+static size_t _EUC_CN_mbrtowc(wchar_t * __restrict, const char * __restrict,
size_t, mbstate_t * __restrict);
-static int _EUC_mbsinit(const mbstate_t *);
-static size_t _EUC_wcrtomb(char * __restrict, wchar_t,
+static size_t _EUC_JP_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict);
+static size_t _EUC_KR_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict);
+static size_t _EUC_TW_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict);
+
+static size_t _EUC_CN_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict);
+static size_t _EUC_JP_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict);
+static size_t _EUC_KR_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict);
+static size_t _EUC_TW_wcrtomb(char * __restrict, wchar_t,
mbstate_t * __restrict);
-typedef struct {
- int count[4];
- wchar_t bits[4];
- wchar_t mask;
-} _EucInfo;
+static size_t _EUC_CN_mbsnrtowcs(wchar_t * __restrict,
+ const char ** __restrict, size_t, size_t,
+ mbstate_t * __restrict);
+static size_t _EUC_JP_mbsnrtowcs(wchar_t * __restrict,
+ const char ** __restrict, size_t, size_t,
+ mbstate_t * __restrict);
+static size_t _EUC_KR_mbsnrtowcs(wchar_t * __restrict,
+ const char ** __restrict, size_t, size_t,
+ mbstate_t * __restrict);
+static size_t _EUC_TW_mbsnrtowcs(wchar_t * __restrict,
+ const char ** __restrict, size_t, size_t,
+ mbstate_t * __restrict);
+
+static size_t _EUC_CN_wcsnrtombs(char * __restrict,
+ const wchar_t ** __restrict, size_t, size_t,
+ mbstate_t * __restrict);
+static size_t _EUC_JP_wcsnrtombs(char * __restrict,
+ const wchar_t ** __restrict, size_t, size_t,
+ mbstate_t * __restrict);
+static size_t _EUC_KR_wcsnrtombs(char * __restrict,
+ const wchar_t ** __restrict, size_t, size_t,
+ mbstate_t * __restrict);
+static size_t _EUC_TW_wcsnrtombs(char * __restrict,
+ const wchar_t ** __restrict, size_t, size_t,
+ mbstate_t * __restrict);
+
+static int _EUC_mbsinit(const mbstate_t *);
typedef struct {
wchar_t ch;
@@ -74,94 +111,218 @@ typedef struct {
int want;
} _EucState;
+static int
+_EUC_mbsinit(const mbstate_t *ps)
+{
+
+ return (ps == NULL || ((const _EucState *)ps)->want == 0);
+}
+
+/*
+ * EUC-CN uses CS0, CS1 and CS2 (4 bytes).
+ */
int
-_EUC_init(struct xlocale_ctype *l, _RuneLocale *rl)
+_EUC_CN_init(struct xlocale_ctype *l, _RuneLocale *rl)
{
- _EucInfo *ei;
- int x, new__mb_cur_max;
- char *v, *e;
+ l->__mbrtowc = _EUC_CN_mbrtowc;
+ l->__wcrtomb = _EUC_CN_wcrtomb;
+ l->__mbsnrtowcs = _EUC_CN_mbsnrtowcs;
+ l->__wcsnrtombs = _EUC_CN_wcsnrtombs;
+ l->__mbsinit = _EUC_mbsinit;
- if (rl->__variable == NULL)
- return (EFTYPE);
+ l->runes = rl;
+ l->__mb_cur_max = 4;
+ l->__mb_sb_limit = 256;
+ return (0);
+}
- v = (char *)rl->__variable;
+static size_t
+_EUC_CN_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s,
+ size_t n, mbstate_t * __restrict ps)
+{
+ return (_EUC_mbrtowc_impl(pwc, s, n, ps, SS2, 4, 0, 0));
+}
- while (*v == ' ' || *v == '\t')
- ++v;
+static size_t
+_EUC_CN_mbsnrtowcs(wchar_t * __restrict dst,
+ const char ** __restrict src,
+ size_t nms, size_t len, mbstate_t * __restrict ps)
+{
+ return (__mbsnrtowcs_std(dst, src, nms, len, ps, _EUC_CN_mbrtowc));
+}
- if ((ei = malloc(sizeof(_EucInfo))) == NULL)
- return (errno == 0 ? ENOMEM : errno);
+static size_t
+_EUC_CN_wcrtomb(char * __restrict s, wchar_t wc,
+ mbstate_t * __restrict ps)
+{
+ return (_EUC_wcrtomb_impl(s, wc, ps, SS2, 4, 0, 0));
+}
- new__mb_cur_max = 0;
- for (x = 0; x < 4; ++x) {
- ei->count[x] = (int)strtol(v, &e, 0);
- if (v == e || !(v = e)) {
- free(ei);
- return (EFTYPE);
- }
- if (new__mb_cur_max < ei->count[x])
- new__mb_cur_max = ei->count[x];
- while (*v == ' ' || *v == '\t')
- ++v;
- ei->bits[x] = (int)strtol(v, &e, 0);
- if (v == e || !(v = e)) {
- free(ei);
- return (EFTYPE);
- }
- while (*v == ' ' || *v == '\t')
- ++v;
- }
- ei->mask = (int)strtol(v, &e, 0);
- if (v == e || !(v = e)) {
- free(ei);
- return (EFTYPE);
- }
- rl->__variable = ei;
- rl->__variable_len = sizeof(_EucInfo);
- l->runes = rl;
- l->__mb_cur_max = new__mb_cur_max;
- l->__mbrtowc = _EUC_mbrtowc;
- l->__wcrtomb = _EUC_wcrtomb;
+static size_t
+_EUC_CN_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
+ size_t nwc, size_t len, mbstate_t * __restrict ps)
+{
+ return (__wcsnrtombs_std(dst, src, nwc, len, ps, _EUC_CN_wcrtomb));
+}
+
+/*
+ * EUC-KR uses only CS0 and CS1.
+ */
+int
+_EUC_KR_init(struct xlocale_ctype *l, _RuneLocale *rl)
+{
+ l->__mbrtowc = _EUC_KR_mbrtowc;
+ l->__wcrtomb = _EUC_KR_wcrtomb;
+ l->__mbsnrtowcs = _EUC_KR_mbsnrtowcs;
+ l->__wcsnrtombs = _EUC_KR_wcsnrtombs;
l->__mbsinit = _EUC_mbsinit;
- l->__mb_sb_limit = 256;
+
+ l->runes = rl;
+ l->__mb_cur_max = 2;
+ l->__mb_sb_limit = 128;
return (0);
}
-static int
-_EUC_mbsinit(const mbstate_t *ps)
+static size_t
+_EUC_KR_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s,
+ size_t n, mbstate_t * __restrict ps)
{
+ return (_EUC_mbrtowc_impl(pwc, s, n, ps, 0, 0, 0, 0));
+}
- return (ps == NULL || ((const _EucState *)ps)->want == 0);
+static size_t
+_EUC_KR_mbsnrtowcs(wchar_t * __restrict dst,
+ const char ** __restrict src,
+ size_t nms, size_t len, mbstate_t * __restrict ps)
+{
+ return (__mbsnrtowcs_std(dst, src, nms, len, ps, _EUC_KR_mbrtowc));
}
-#define CEI ((_EucInfo *)(_CurrentRuneLocale->__variable))
+static size_t
+_EUC_KR_wcrtomb(char * __restrict s, wchar_t wc,
+ mbstate_t * __restrict ps)
+{
+ return (_EUC_wcrtomb_impl(s, wc, ps, 0, 0, 0, 0));
+}
-#define _SS2 0x008e
-#define _SS3 0x008f
+static size_t
+_EUC_KR_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
+ size_t nwc, size_t len, mbstate_t * __restrict ps)
+{
+ return (__wcsnrtombs_std(dst, src, nwc, len, ps, _EUC_KR_wcrtomb));
+}
-#define GR_BITS 0x80808080 /* XXX: to be fixed */
+/*
+ * EUC-JP uses CS0, CS1, CS2, and CS3.
+ */
+int
+_EUC_JP_init(struct xlocale_ctype *l, _RuneLocale *rl)
+{
+ l->__mbrtowc = _EUC_JP_mbrtowc;
+ l->__wcrtomb = _EUC_JP_wcrtomb;
+ l->__mbsnrtowcs = _EUC_JP_mbsnrtowcs;
+ l->__wcsnrtombs = _EUC_JP_wcsnrtombs;
+ l->__mbsinit = _EUC_mbsinit;
-static __inline int
-_euc_set(u_int c)
+ l->runes = rl;
+ l->__mb_cur_max = 3;
+ l->__mb_sb_limit = 196;
+ return (0);
+}
+
+static size_t
+_EUC_JP_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s,
+ size_t n, mbstate_t * __restrict ps)
{
+ return (_EUC_mbrtowc_impl(pwc, s, n, ps, SS2, 2, SS3, 3));
+}
- c &= 0xff;
- return ((c & 0x80) ? c == _SS3 ? 3 : c == _SS2 ? 2 : 1 : 0);
+static size_t
+_EUC_JP_mbsnrtowcs(wchar_t * __restrict dst,
+ const char ** __restrict src,
+ size_t nms, size_t len, mbstate_t * __restrict ps)
+{
+ return (__mbsnrtowcs_std(dst, src, nms, len, ps, _EUC_JP_mbrtowc));
}
static size_t
-_EUC_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
+_EUC_JP_wcrtomb(char * __restrict s, wchar_t wc,
mbstate_t * __restrict ps)
{
+ return (_EUC_wcrtomb_impl(s, wc, ps, SS2, 2, SS3, 3));
+}
+
+static size_t
+_EUC_JP_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
+ size_t nwc, size_t len, mbstate_t * __restrict ps)
+{
+ return (__wcsnrtombs_std(dst, src, nwc, len, ps, _EUC_JP_wcrtomb));
+}
+
+/*
+ * EUC-TW uses CS0, CS1, and CS2.
+ */
+int
+_EUC_TW_init(struct xlocale_ctype *l, _RuneLocale *rl)
+{
+ l->__mbrtowc = _EUC_TW_mbrtowc;
+ l->__wcrtomb = _EUC_TW_wcrtomb;
+ l->__mbsnrtowcs = _EUC_TW_mbsnrtowcs;
+ l->__wcsnrtombs = _EUC_TW_wcsnrtombs;
+ l->__mbsinit = _EUC_mbsinit;
+
+ l->runes = rl;
+ l->__mb_cur_max = 4;
+ l->__mb_sb_limit = 256;
+ return (0);
+}
+
+static size_t
+_EUC_TW_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s,
+ size_t n, mbstate_t * __restrict ps)
+{
+ return (_EUC_mbrtowc_impl(pwc, s, n, ps, SS2, 4, 0, 0));
+}
+
+static size_t
+_EUC_TW_mbsnrtowcs(wchar_t * __restrict dst,
+ const char ** __restrict src,
+ size_t nms, size_t len, mbstate_t * __restrict ps)
+{
+ return (__mbsnrtowcs_std(dst, src, nms, len, ps, _EUC_TW_mbrtowc));
+}
+
+static size_t
+_EUC_TW_wcrtomb(char * __restrict s, wchar_t wc,
+ mbstate_t * __restrict ps)
+{
+ return (_EUC_wcrtomb_impl(s, wc, ps, SS2, 4, 0, 0));
+}
+
+static size_t
+_EUC_TW_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
+ size_t nwc, size_t len, mbstate_t * __restrict ps)
+{
+ return (__wcsnrtombs_std(dst, src, nwc, len, ps, _EUC_TW_wcrtomb));
+}
+
+/*
+ * Common EUC code.
+ */
+
+static size_t
+_EUC_mbrtowc_impl(wchar_t * __restrict pwc, const char * __restrict s,
+ size_t n, mbstate_t * __restrict ps,
+ uint8_t cs2, uint8_t cs2width, uint8_t cs3, uint8_t cs3width)
+{
_EucState *es;
- int i, set, want;
- wchar_t wc;
- const char *os;
+ int i, want;
+ wchar_t wc = 0;
+ unsigned char ch, chs;
es = (_EucState *)ps;
- if (es->want < 0 || es->want > MB_CUR_MAX || es->set < 0 ||
- es->set > 3) {
+ if (es->want < 0 || es->want > MB_CUR_MAX) {
errno = EINVAL;
return ((size_t)-1);
}
@@ -176,58 +337,61 @@ _EUC_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
/* Incomplete multibyte sequence */
return ((size_t)-2);
- os = s;
-
if (es->want == 0) {
- want = CEI->count[set = _euc_set(*s)];
- if (set == 2 || set == 3) {
- --want;
- if (--n == 0) {
- /* Incomplete multibyte sequence */
- es->set = set;
- es->want = want;
- es->ch = 0;
- return ((size_t)-2);
- }
- ++s;
- if (*s == '\0') {
- errno = EILSEQ;
- return ((size_t)-1);
- }
+ /* Fast path for plain ASCII (CS0) */
+ if (((ch = (unsigned char)*s) & 0x80) == 0) {
+ if (pwc != NULL)
+ *pwc = ch;
+ return (ch != '\0' ? 1 : 0);
}
- wc = (unsigned char)*s++;
+
+ if (ch >= 0xa1) {
+ /* CS1 */
+ want = 2;
+ } else if (ch == cs2) {
+ want = cs2width;
+ } else if (ch == cs3) {
+ want = cs3width;
+ } else {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+
+
+ es->want = want;
+ es->ch = 0;
} else {
- set = es->set;
want = es->want;
wc = es->ch;
}
- for (i = (es->want == 0) ? 1 : 0; i < MIN(want, n); i++) {
- if (*s == '\0') {
- errno = EILSEQ;
- return ((size_t)-1);
- }
- wc = (wc << 8) | (unsigned char)*s++;
+
+ for (i = 0; i < MIN(want, n); i++) {
+ wc <<= 8;
+ chs = *s;
+ wc |= chs;
+ s++;
}
if (i < want) {
/* Incomplete multibyte sequence */
- es->set = set;
es->want = want - i;
es->ch = wc;
+ errno = EILSEQ;
return ((size_t)-2);
}
- wc = (wc & ~CEI->mask) | CEI->bits[set];
if (pwc != NULL)
*pwc = wc;
es->want = 0;
- return (wc == L'\0' ? 0 : s - os);
+ return (wc == L'\0' ? 0 : want);
}
static size_t
-_EUC_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
+_EUC_wcrtomb_impl(char * __restrict s, wchar_t wc,
+ mbstate_t * __restrict ps,
+ uint8_t cs2, uint8_t cs2width, uint8_t cs3, uint8_t cs3width)
{
_EucState *es;
- wchar_t m, nm;
int i, len;
+ wchar_t nm;
es = (_EucState *)ps;
@@ -240,34 +404,52 @@ _EUC_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
/* Reset to initial shift state (no-op) */
return (1);
- m = wc & CEI->mask;
- nm = wc & ~m;
+ if ((wc & ~0x7f) == 0) {
+ /* Fast path for plain ASCII (CS0) */
+ *s = (char)wc;
+ return (1);
+ }
- if (m == CEI->bits[1]) {
-CodeSet1:
- /* Codeset 1: The first byte must have 0x80 in it. */
- i = len = CEI->count[1];
- while (i-- > 0)
- *s++ = (nm >> (i << 3)) | 0x80;
+ /* Determine the "length" */
+ if ((unsigned)wc > 0xffffff) {
+ len = 4;
+ } else if ((unsigned)wc > 0xffff) {
+ len = 3;
+ } else if ((unsigned)wc > 0xff) {
+ len = 2;
} else {
- if (m == CEI->bits[0])
- i = len = CEI->count[0];
- else if (m == CEI->bits[2]) {
- i = len = CEI->count[2];
- *s++ = _SS2;
- --i;
- /* SS2 designates G2 into GR */
- nm |= GR_BITS;
- } else if (m == CEI->bits[3]) {
- i = len = CEI->count[3];
- *s++ = _SS3;
- --i;
- /* SS3 designates G3 into GR */
- nm |= GR_BITS;
- } else
- goto CodeSet1; /* Bletch */
- while (i-- > 0)
- *s++ = (nm >> (i << 3)) & 0xff;
+ len = 1;
+ }
+
+ if (len > MB_CUR_MAX) {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+
+ /* This first check excludes CS1, which is implicitly valid. */
+ if ((wc < 0xa100) || (wc > 0xffff)) {
+ /* Check for valid CS2 or CS3 */
+ nm = (wc >> ((len - 1) * 8));
+ if (nm == cs2) {
+ if (len != cs2width) {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ } else if (nm == cs3) {
+ if (len != cs3width) {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ } else {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ }
+
+ /* Stash the bytes, least significant last */
+ for (i = len - 1; i >= 0; i--) {
+ s[i] = (wc & 0xff);
+ wc >>= 8;
}
return (len);
}
diff --git a/lib/libc/locale/gb18030.c b/lib/libc/locale/gb18030.c
index 9214385..d87b6f7 100644
--- a/lib/libc/locale/gb18030.c
+++ b/lib/libc/locale/gb18030.c
@@ -1,4 +1,6 @@
/*-
+ * Copyright 2013 Garrett D'Amore <garrett@damore.org>
+ * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2002-2004 Tim J. Robbins
* All rights reserved.
*
@@ -28,6 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
+
/*
* PRC National Standard GB 18030-2000 encoding of Chinese text.
*
@@ -49,6 +52,13 @@ static size_t _GB18030_mbrtowc(wchar_t * __restrict, const char * __restrict,
static int _GB18030_mbsinit(const mbstate_t *);
static size_t _GB18030_wcrtomb(char * __restrict, wchar_t,
mbstate_t * __restrict);
+static size_t _GB18030_mbsnrtowcs(wchar_t * __restrict,
+ const char ** __restrict, size_t, size_t,
+ mbstate_t * __restrict);
+static size_t _GB18030_wcsnrtombs(char * __restrict,
+ const wchar_t ** __restrict, size_t, size_t,
+ mbstate_t * __restrict);
+
typedef struct {
int count;
@@ -62,6 +72,8 @@ _GB18030_init(struct xlocale_ctype *l, _RuneLocale *rl)
l->__mbrtowc = _GB18030_mbrtowc;
l->__wcrtomb = _GB18030_wcrtomb;
l->__mbsinit = _GB18030_mbsinit;
+ l->__mbsnrtowcs = _GB18030_mbsnrtowcs;
+ l->__wcsnrtombs = _GB18030_wcsnrtombs;
l->runes = rl;
l->__mb_cur_max = 4;
l->__mb_sb_limit = 128;
@@ -222,3 +234,19 @@ ilseq:
errno = EILSEQ;
return ((size_t)-1);
}
+
+static size_t
+_GB18030_mbsnrtowcs(wchar_t * __restrict dst,
+ const char ** __restrict src, size_t nms, size_t len,
+ mbstate_t * __restrict ps)
+{
+ return (__mbsnrtowcs_std(dst, src, nms, len, ps, _GB18030_mbrtowc));
+}
+
+static size_t
+_GB18030_wcsnrtombs(char * __restrict dst,
+ const wchar_t ** __restrict src, size_t nwc, size_t len,
+ mbstate_t * __restrict ps)
+{
+ return (__wcsnrtombs_std(dst, src, nwc, len, ps, _GB18030_wcrtomb));
+}
diff --git a/lib/libc/locale/gb2312.c b/lib/libc/locale/gb2312.c
index 5fbc07d..032a3e2 100644
--- a/lib/libc/locale/gb2312.c
+++ b/lib/libc/locale/gb2312.c
@@ -1,4 +1,6 @@
/*-
+ * Copyright 2013 Garrett D'Amore <garrett@damore.org>
+ * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2004 Tim J. Robbins. All rights reserved.
* Copyright (c) 2003 David Xu <davidxu@freebsd.org>
* All rights reserved.
@@ -45,6 +47,13 @@ static size_t _GB2312_mbrtowc(wchar_t * __restrict, const char * __restrict,
static int _GB2312_mbsinit(const mbstate_t *);
static size_t _GB2312_wcrtomb(char * __restrict, wchar_t,
mbstate_t * __restrict);
+static size_t _GB2312_mbsnrtowcs(wchar_t * __restrict,
+ const char ** __restrict, size_t, size_t,
+ mbstate_t * __restrict);
+static size_t _GB2312_wcsnrtombs(char * __restrict,
+ const wchar_t ** __restrict, size_t, size_t,
+ mbstate_t * __restrict);
+
typedef struct {
int count;
@@ -59,6 +68,8 @@ _GB2312_init(struct xlocale_ctype *l, _RuneLocale *rl)
l->__mbrtowc = _GB2312_mbrtowc;
l->__wcrtomb = _GB2312_wcrtomb;
l->__mbsinit = _GB2312_mbsinit;
+ l->__mbsnrtowcs = _GB2312_mbsnrtowcs;
+ l->__wcsnrtombs = _GB2312_wcsnrtombs;
l->__mb_cur_max = 2;
l->__mb_sb_limit = 128;
return (0);
@@ -71,7 +82,7 @@ _GB2312_mbsinit(const mbstate_t *ps)
return (ps == NULL || ((const _GB2312State *)ps)->count == 0);
}
-static __inline int
+static int
_GB2312_check(const char *str, size_t n)
{
const u_char *s = (const u_char *)str;
@@ -90,7 +101,7 @@ _GB2312_check(const char *str, size_t n)
} else if (s[0] & 0x80) {
/* Invalid multibyte sequence */
return (-1);
- }
+ }
return (1);
}
@@ -158,3 +169,19 @@ _GB2312_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
*s = wc & 0xff;
return (1);
}
+
+static size_t
+_GB2312_mbsnrtowcs(wchar_t * __restrict dst,
+ const char ** __restrict src, size_t nms, size_t len,
+ mbstate_t * __restrict ps)
+{
+ return (__mbsnrtowcs_std(dst, src, nms, len, ps, _GB2312_mbrtowc));
+}
+
+static size_t
+_GB2312_wcsnrtombs(char * __restrict dst,
+ const wchar_t ** __restrict src, size_t nwc, size_t len,
+ mbstate_t * __restrict ps)
+{
+ return (__wcsnrtombs_std(dst, src, nwc, len, ps, _GB2312_wcrtomb));
+}
diff --git a/lib/libc/locale/gbk.c b/lib/libc/locale/gbk.c
index 43269c7..c3d16f6 100644
--- a/lib/libc/locale/gbk.c
+++ b/lib/libc/locale/gbk.c
@@ -1,4 +1,6 @@
/*-
+ * Copyright 2013 Garrett D'Amore <garrett@damore.org>
+ * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved.
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
@@ -54,6 +56,12 @@ static size_t _GBK_mbrtowc(wchar_t * __restrict, const char * __restrict,
static int _GBK_mbsinit(const mbstate_t *);
static size_t _GBK_wcrtomb(char * __restrict, wchar_t,
mbstate_t * __restrict);
+static size_t _GBK_mbsnrtowcs(wchar_t * __restrict,
+ const char ** __restrict, size_t, size_t,
+ mbstate_t * __restrict);
+static size_t _GBK_wcsnrtombs(char * __restrict,
+ const wchar_t ** __restrict, size_t, size_t,
+ mbstate_t * __restrict);
typedef struct {
wchar_t ch;
@@ -66,6 +74,8 @@ _GBK_init(struct xlocale_ctype *l, _RuneLocale *rl)
l->__mbrtowc = _GBK_mbrtowc;
l->__wcrtomb = _GBK_wcrtomb;
l->__mbsinit = _GBK_mbsinit;
+ l->__mbsnrtowcs = _GBK_mbsnrtowcs;
+ l->__wcsnrtombs = _GBK_wcsnrtombs;
l->runes = rl;
l->__mb_cur_max = 2;
l->__mb_sb_limit = 128;
@@ -79,7 +89,7 @@ _GBK_mbsinit(const mbstate_t *ps)
return (ps == NULL || ((const _GBKState *)ps)->ch == 0);
}
-static __inline int
+static int
_gbk_check(u_int c)
{
@@ -140,7 +150,7 @@ _GBK_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
wc = (wc << 8) | (*s++ & 0xff);
if (pwc != NULL)
*pwc = wc;
- return (2);
+ return (2);
} else {
if (pwc != NULL)
*pwc = wc;
@@ -171,3 +181,17 @@ _GBK_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
*s = wc & 0xff;
return (1);
}
+
+static size_t
+_GBK_mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src,
+ size_t nms, size_t len, mbstate_t * __restrict ps)
+{
+ return (__mbsnrtowcs_std(dst, src, nms, len, ps, _GBK_mbrtowc));
+}
+
+static size_t
+_GBK_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
+ size_t nwc, size_t len, mbstate_t * __restrict ps)
+{
+ return (__wcsnrtombs_std(dst, src, nwc, len, ps, _GBK_wcrtomb));
+}
diff --git a/lib/libc/locale/isctype.c b/lib/libc/locale/isctype.c
index 2550534..8f93f19 100644
--- a/lib/libc/locale/isctype.c
+++ b/lib/libc/locale/isctype.c
@@ -54,7 +54,7 @@ digittoint(int c)
int
isalnum(int c)
{
- return (__sbistype(c, _CTYPE_A|_CTYPE_D));
+ return (__sbistype(c, _CTYPE_A|_CTYPE_N));
}
#undef isalpha
@@ -124,7 +124,7 @@ islower(int c)
int
isnumber(int c)
{
- return (__sbistype(c, _CTYPE_D));
+ return (__sbistype(c, _CTYPE_N));
}
#undef isphonogram
diff --git a/lib/libc/locale/iswctype.c b/lib/libc/locale/iswctype.c
index 59d432c..dad0621 100644
--- a/lib/libc/locale/iswctype.c
+++ b/lib/libc/locale/iswctype.c
@@ -44,7 +44,7 @@ __FBSDID("$FreeBSD$");
int
iswalnum(wint_t wc)
{
- return (__istype(wc, _CTYPE_A|_CTYPE_D));
+ return (__istype(wc, _CTYPE_A|_CTYPE_N));
}
#undef iswalpha
@@ -79,7 +79,7 @@ iswcntrl(wint_t wc)
int
iswdigit(wint_t wc)
{
- return (__isctype(wc, _CTYPE_D));
+ return (__istype(wc, _CTYPE_D));
}
#undef iswgraph
@@ -114,7 +114,7 @@ iswlower(wint_t wc)
int
iswnumber(wint_t wc)
{
- return (__istype(wc, _CTYPE_D));
+ return (__istype(wc, _CTYPE_N));
}
#undef iswphonogram
@@ -170,7 +170,7 @@ iswupper(wint_t wc)
int
iswxdigit(wint_t wc)
{
- return (__isctype(wc, _CTYPE_X));
+ return (__istype(wc, _CTYPE_X));
}
#undef towlower
diff --git a/lib/libc/locale/mblocal.h b/lib/libc/locale/mblocal.h
index d172764..75eab96 100644
--- a/lib/libc/locale/mblocal.h
+++ b/lib/libc/locale/mblocal.h
@@ -1,4 +1,6 @@
/*-
+ * Copyright 2013 Garrett D'Amore <garrett@damore.org>
+ * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2004 Tim J. Robbins.
* All rights reserved.
*
@@ -37,6 +39,8 @@
#include <runetype.h>
#include "xlocale_private.h"
+#define SS2 0x008e
+#define SS3 0x008f
/*
* Conversion function pointers for current encoding.
@@ -62,18 +66,25 @@ extern struct xlocale_ctype __xlocale_global_ctype;
* Rune initialization function prototypes.
*/
int _none_init(struct xlocale_ctype *, _RuneLocale *);
-int _ascii_init(struct xlocale_ctype *, _RuneLocale *);
int _UTF8_init(struct xlocale_ctype *, _RuneLocale *);
-int _EUC_init(struct xlocale_ctype *, _RuneLocale *);
+int _EUC_CN_init(struct xlocale_ctype *, _RuneLocale *);
+int _EUC_JP_init(struct xlocale_ctype *, _RuneLocale *);
+int _EUC_KR_init(struct xlocale_ctype *, _RuneLocale *);
+int _EUC_TW_init(struct xlocale_ctype *, _RuneLocale *);
int _GB18030_init(struct xlocale_ctype *, _RuneLocale *);
int _GB2312_init(struct xlocale_ctype *, _RuneLocale *);
int _GBK_init(struct xlocale_ctype *, _RuneLocale *);
int _BIG5_init(struct xlocale_ctype *, _RuneLocale *);
int _MSKanji_init(struct xlocale_ctype *, _RuneLocale *);
+int _ascii_init(struct xlocale_ctype *, _RuneLocale *);
-extern size_t __mbsnrtowcs_std(wchar_t * __restrict, const char ** __restrict,
- size_t, size_t, mbstate_t * __restrict);
-extern size_t __wcsnrtombs_std(char * __restrict, const wchar_t ** __restrict,
- size_t, size_t, mbstate_t * __restrict);
+typedef size_t (*mbrtowc_pfn_t)(wchar_t * __restrict,
+ const char * __restrict, size_t, mbstate_t * __restrict);
+typedef size_t (*wcrtomb_pfn_t)(char * __restrict, wchar_t,
+ mbstate_t * __restrict);
+size_t __mbsnrtowcs_std(wchar_t * __restrict, const char ** __restrict,
+ size_t, size_t, mbstate_t * __restrict, mbrtowc_pfn_t);
+size_t __wcsnrtombs_std(char * __restrict, const wchar_t ** __restrict,
+ size_t, size_t, mbstate_t * __restrict, wcrtomb_pfn_t);
#endif /* _MBLOCAL_H_ */
diff --git a/lib/libc/locale/mbsnrtowcs.c b/lib/libc/locale/mbsnrtowcs.c
index 15b48dd7..9e6baad 100644
--- a/lib/libc/locale/mbsnrtowcs.c
+++ b/lib/libc/locale/mbsnrtowcs.c
@@ -1,4 +1,6 @@
/*-
+ * Copyright 2013 Garrett D'Amore <garrett@damore.org>
+ * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2002-2004 Tim J. Robbins.
*
* Copyright (c) 2011 The FreeBSD Foundation
@@ -56,20 +58,20 @@ mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src,
size_t
__mbsnrtowcs_std(wchar_t * __restrict dst, const char ** __restrict src,
- size_t nms, size_t len, mbstate_t * __restrict ps)
+ size_t nms, size_t len, mbstate_t * __restrict ps,
+ mbrtowc_pfn_t pmbrtowc)
{
const char *s;
size_t nchr;
wchar_t wc;
size_t nb;
- struct xlocale_ctype *ct = XLOCALE_CTYPE(__get_locale());
s = *src;
nchr = 0;
if (dst == NULL) {
for (;;) {
- if ((nb = ct->__mbrtowc(&wc, s, nms, ps)) == (size_t)-1)
+ if ((nb = pmbrtowc(&wc, s, nms, ps)) == (size_t)-1)
/* Invalid sequence - mbrtowc() sets errno. */
return ((size_t)-1);
else if (nb == 0 || nb == (size_t)-2)
@@ -82,7 +84,7 @@ __mbsnrtowcs_std(wchar_t * __restrict dst, const char ** __restrict src,
}
while (len-- > 0) {
- if ((nb = ct->__mbrtowc(dst, s, nms, ps)) == (size_t)-1) {
+ if ((nb = pmbrtowc(dst, s, nms, ps)) == (size_t)-1) {
*src = s;
return ((size_t)-1);
} else if (nb == (size_t)-2) {
diff --git a/lib/libc/locale/mskanji.c b/lib/libc/locale/mskanji.c
index 9fdd080..dc2d0e1 100644
--- a/lib/libc/locale/mskanji.c
+++ b/lib/libc/locale/mskanji.c
@@ -1,4 +1,6 @@
/*
+ * Copyright 2013 Garrett D'Amore <garrett@damore.org>
+ * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved.
*
* ja_JP.SJIS locale table for BSD4.4/rune
@@ -28,14 +30,14 @@
* 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.
+ * 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.
*/
#if defined(LIBC_SCCS) && !defined(lint)
@@ -59,6 +61,12 @@ static size_t _MSKanji_mbrtowc(wchar_t * __restrict, const char * __restrict,
static int _MSKanji_mbsinit(const mbstate_t *);
static size_t _MSKanji_wcrtomb(char * __restrict, wchar_t,
mbstate_t * __restrict);
+static size_t _MSKanji_mbsnrtowcs(wchar_t * __restrict,
+ const char ** __restrict, size_t, size_t,
+ mbstate_t * __restrict);
+static size_t _MSKanji_wcsnrtombs(char * __restrict,
+ const wchar_t ** __restrict, size_t, size_t,
+ mbstate_t * __restrict);
typedef struct {
wchar_t ch;
@@ -70,6 +78,8 @@ _MSKanji_init(struct xlocale_ctype *l, _RuneLocale *rl)
l->__mbrtowc = _MSKanji_mbrtowc;
l->__wcrtomb = _MSKanji_wcrtomb;
+ l->__mbsnrtowcs = _MSKanji_mbsnrtowcs;
+ l->__wcsnrtombs = _MSKanji_wcsnrtombs;
l->__mbsinit = _MSKanji_mbsinit;
l->runes = rl;
l->__mb_cur_max = 2;
@@ -163,3 +173,19 @@ _MSKanji_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
*s++ = wc >> (i << 3);
return (len);
}
+
+static size_t
+_MSKanji_mbsnrtowcs(wchar_t * __restrict dst,
+ const char ** __restrict src, size_t nms,
+ size_t len, mbstate_t * __restrict ps)
+{
+ return (__mbsnrtowcs_std(dst, src, nms, len, ps, _MSKanji_mbrtowc));
+}
+
+static size_t
+_MSKanji_wcsnrtombs(char * __restrict dst,
+ const wchar_t ** __restrict src, size_t nwc,
+ size_t len, mbstate_t * __restrict ps)
+{
+ return (__wcsnrtombs_std(dst, src, nwc, len, ps, _MSKanji_wcrtomb));
+}
diff --git a/lib/libc/locale/nl_langinfo.c b/lib/libc/locale/nl_langinfo.c
index 3e8fe7c..e3b370a 100644
--- a/lib/libc/locale/nl_langinfo.c
+++ b/lib/libc/locale/nl_langinfo.c
@@ -37,7 +37,10 @@ __FBSDID("$FreeBSD$");
#include <locale.h>
#include <stdlib.h>
#include <string.h>
+#include <runetype.h>
+#include <wchar.h>
+#include "mblocal.h"
#include "lnumeric.h"
#include "lmessages.h"
#include "lmonetary.h"
@@ -54,14 +57,25 @@ nl_langinfo_l(nl_item item, locale_t loc)
switch (item) {
case CODESET:
- ret = "";
- if ((s = querylocale(LC_CTYPE_MASK, loc)) != NULL) {
- if ((cs = strchr(s, '.')) != NULL)
- ret = cs + 1;
- else if (strcmp(s, "C") == 0 ||
- strcmp(s, "POSIX") == 0)
- ret = "US-ASCII";
- }
+ s = XLOCALE_CTYPE(loc)->runes->__encoding;
+ if (strcmp(s, "EUC-CN") == 0)
+ ret = "eucCN";
+ else if (strcmp(s, "EUC-JP") == 0)
+ ret = "eucJP";
+ else if (strcmp(s, "EUC-KR") == 0)
+ ret = "eucKR";
+ else if (strcmp(s, "EUC-TW") == 0)
+ ret = "eucTW";
+ else if (strcmp(s, "BIG5") == 0)
+ ret = "Big5";
+ else if (strcmp(s, "MSKanji") == 0)
+ ret = "SJIS";
+ else if (strcmp(s, "NONE") == 0)
+ ret = "US-ASCII";
+ else if (strncmp(s, "NONE:", 5) == 0)
+ ret = (char *)(s + 5);
+ else
+ ret = (char *)s;
break;
case D_T_FMT:
ret = (char *) __get_current_time_locale(loc)->c_fmt;
diff --git a/lib/libc/locale/none.c b/lib/libc/locale/none.c
index cacfd73..c4695fd 100644
--- a/lib/libc/locale/none.c
+++ b/lib/libc/locale/none.c
@@ -1,4 +1,6 @@
/*-
+ * Copyright 2013 Garrett D'Amore <garrett@damore.org>
+ * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved.
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
@@ -187,16 +189,6 @@ _none_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
/* setup defaults */
-size_t (*__mbrtowc)(wchar_t * __restrict, const char * __restrict, size_t,
- mbstate_t * __restrict) = _none_mbrtowc;
-int (*__mbsinit)(const mbstate_t *) = _none_mbsinit;
-size_t (*__mbsnrtowcs)(wchar_t * __restrict, const char ** __restrict,
- size_t, size_t, mbstate_t * __restrict) = _none_mbsnrtowcs;
-size_t (*__wcrtomb)(char * __restrict, wchar_t, mbstate_t * __restrict) =
- _none_wcrtomb;
-size_t (*__wcsnrtombs)(char * __restrict, const wchar_t ** __restrict,
- size_t, size_t, mbstate_t * __restrict) = _none_wcsnrtombs;
-
struct xlocale_ctype __xlocale_global_ctype = {
{{0}, "C"},
(_RuneLocale*)&_DefaultRuneLocale,
diff --git a/lib/libc/locale/rune.c b/lib/libc/locale/rune.c
index f72ba74..00ef19b 100644
--- a/lib/libc/locale/rune.c
+++ b/lib/libc/locale/rune.c
@@ -1,4 +1,6 @@
/*-
+ * Copyright 2014 Garrett D'Amore <garrett@damore.org>
+ * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
*
@@ -45,14 +47,15 @@ __FBSDID("$FreeBSD$");
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
#include "un-namespace.h"
#include "runefile.h"
-_RuneLocale *_Read_RuneMagi(FILE *);
-
_RuneLocale *
-_Read_RuneMagi(FILE *fp)
+_Read_RuneMagi(const char *fname)
{
char *fdata, *data;
void *lastp;
@@ -67,119 +70,77 @@ _Read_RuneMagi(FILE *fp)
_FileRuneEntry *maplower_ext_ranges;
_FileRuneEntry *mapupper_ext_ranges;
int runetype_ext_len = 0;
+ int fd;
- if (_fstat(fileno(fp), &sb) < 0)
+ if ((fd = _open(fname, O_RDONLY)) < 0) {
+ errno = EINVAL;
return (NULL);
+ }
- if ((size_t)sb.st_size < sizeof(_FileRuneLocale)) {
- errno = EFTYPE;
+ if (_fstat(fd, &sb) < 0) {
+ (void) _close(fd);
+ errno = EINVAL;
return (NULL);
}
- if ((fdata = malloc(sb.st_size)) == NULL)
- return (NULL);
-
- errno = 0;
- rewind(fp); /* Someone might have read the magic number once already */
- if (errno) {
- saverr = errno;
- free(fdata);
- errno = saverr;
+ if ((size_t)sb.st_size < sizeof (_FileRuneLocale)) {
+ (void) _close(fd);
+ errno = EINVAL;
return (NULL);
}
- if (fread(fdata, sb.st_size, 1, fp) != 1) {
- saverr = errno;
- free(fdata);
- errno = saverr;
+
+ fdata = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ (void) _close(fd);
+ if (fdata == NULL) {
+ errno = EINVAL;
return (NULL);
}
- frl = (_FileRuneLocale *)fdata;
+ frl = (_FileRuneLocale *)(void *)fdata;
lastp = fdata + sb.st_size;
variable = frl + 1;
- if (memcmp(frl->magic, _FILE_RUNE_MAGIC_1, sizeof(frl->magic))) {
- free(fdata);
- errno = EFTYPE;
- return (NULL);
- }
-
- frl->variable_len = ntohl(frl->variable_len);
- frl->runetype_ext_nranges = ntohl(frl->runetype_ext_nranges);
- frl->maplower_ext_nranges = ntohl(frl->maplower_ext_nranges);
- frl->mapupper_ext_nranges = ntohl(frl->mapupper_ext_nranges);
-
- for (x = 0; x < _CACHED_RUNES; ++x) {
- frl->runetype[x] = ntohl(frl->runetype[x]);
- frl->maplower[x] = ntohl(frl->maplower[x]);
- frl->mapupper[x] = ntohl(frl->mapupper[x]);
+ if (memcmp(frl->magic, _FILE_RUNE_MAGIC_1, sizeof (frl->magic))) {
+ goto invalid;
}
runetype_ext_ranges = (_FileRuneEntry *)variable;
variable = runetype_ext_ranges + frl->runetype_ext_nranges;
if (variable > lastp) {
- free(fdata);
- errno = EFTYPE;
- return (NULL);
+ goto invalid;
}
maplower_ext_ranges = (_FileRuneEntry *)variable;
variable = maplower_ext_ranges + frl->maplower_ext_nranges;
if (variable > lastp) {
- free(fdata);
- errno = EFTYPE;
- return (NULL);
+ goto invalid;
}
mapupper_ext_ranges = (_FileRuneEntry *)variable;
variable = mapupper_ext_ranges + frl->mapupper_ext_nranges;
if (variable > lastp) {
- free(fdata);
- errno = EFTYPE;
- return (NULL);
+ goto invalid;
}
frr = runetype_ext_ranges;
for (x = 0; x < frl->runetype_ext_nranges; ++x) {
uint32_t *types;
- frr[x].min = ntohl(frr[x].min);
- frr[x].max = ntohl(frr[x].max);
- frr[x].map = ntohl(frr[x].map);
if (frr[x].map == 0) {
int len = frr[x].max - frr[x].min + 1;
types = variable;
variable = types + len;
runetype_ext_len += len;
if (variable > lastp) {
- free(fdata);
- errno = EFTYPE;
- return (NULL);
+ goto invalid;
}
- while (len-- > 0)
- types[len] = ntohl(types[len]);
}
}
- frr = maplower_ext_ranges;
- for (x = 0; x < frl->maplower_ext_nranges; ++x) {
- frr[x].min = ntohl(frr[x].min);
- frr[x].max = ntohl(frr[x].max);
- frr[x].map = ntohl(frr[x].map);
- }
-
- frr = mapupper_ext_ranges;
- for (x = 0; x < frl->mapupper_ext_nranges; ++x) {
- frr[x].min = ntohl(frr[x].min);
- frr[x].max = ntohl(frr[x].max);
- frr[x].map = ntohl(frr[x].map);
- }
if ((char *)variable + frl->variable_len > (char *)lastp) {
- free(fdata);
- errno = EFTYPE;
- return (NULL);
+ goto invalid;
}
/*
@@ -192,7 +153,7 @@ _Read_RuneMagi(FILE *fp)
frl->variable_len);
if (data == NULL) {
saverr = errno;
- free(fdata);
+ munmap(fdata, sb.st_size);
errno = saverr;
return (NULL);
}
@@ -202,7 +163,6 @@ _Read_RuneMagi(FILE *fp)
memcpy(rl->__magic, _RUNE_MAGIC_1, sizeof(rl->__magic));
memcpy(rl->__encoding, frl->encoding, sizeof(rl->__encoding));
- rl->__invalid_rune = 0;
rl->__variable_len = frl->variable_len;
rl->__runetype_ext.__nranges = frl->runetype_ext_nranges;
@@ -265,7 +225,7 @@ _Read_RuneMagi(FILE *fp)
}
memcpy(rl->__variable, variable, rl->__variable_len);
- free(fdata);
+ munmap(fdata, sb.st_size);
/*
* Go out and zero pointers that should be zero.
@@ -283,4 +243,9 @@ _Read_RuneMagi(FILE *fp)
rl->__mapupper_ext.__ranges = NULL;
return (rl);
+
+invalid:
+ munmap(fdata, sb.st_size);
+ errno = EINVAL;
+ return (NULL);
}
diff --git a/lib/libc/locale/setrunelocale.c b/lib/libc/locale/setrunelocale.c
index 0a0943f..1ebfc38 100644
--- a/lib/libc/locale/setrunelocale.c
+++ b/lib/libc/locale/setrunelocale.c
@@ -63,23 +63,15 @@ _Thread_local const _RuneLocale *_ThreadRuneLocale;
extern int __mb_sb_limit;
-extern _RuneLocale *_Read_RuneMagi(FILE *);
+extern _RuneLocale *_Read_RuneMagi(const char *);
static int __setrunelocale(struct xlocale_ctype *l, const char *);
-#define __collate_substitute_nontrivial (table->__collate_substitute_nontrivial)
-#define __collate_substitute_table_ptr (table->__collate_substitute_table_ptr)
-#define __collate_char_pri_table_ptr (table->__collate_char_pri_table_ptr)
-#define __collate_chain_pri_table (table->__collate_chain_pri_table)
-
-
static void
destruct_ctype(void *v)
{
struct xlocale_ctype *l = v;
- if (strcmp(l->runes->__encoding, "EUC") == 0)
- free(l->runes->__variable);
if (&_DefaultRuneLocale != l->runes)
free(l->runes);
free(l);
@@ -95,12 +87,7 @@ __getCurrentRuneLocale(void)
static void
free_runes(_RuneLocale *rl)
{
-
- /* FIXME: The "EUC" check here is a hideous abstraction violation. */
if ((rl != &_DefaultRuneLocale) && (rl)) {
- if (strcmp(rl->__encoding, "EUC") == 0) {
- free(rl->__variable);
- }
free(rl);
}
}
@@ -108,10 +95,9 @@ free_runes(_RuneLocale *rl)
static int
__setrunelocale(struct xlocale_ctype *l, const char *encoding)
{
- FILE *fp;
- char name[PATH_MAX];
_RuneLocale *rl;
- int saverr, ret;
+ int ret;
+ char *path;
struct xlocale_ctype saved = *l;
/*
@@ -124,37 +110,39 @@ __setrunelocale(struct xlocale_ctype *l, const char *encoding)
}
/* Range checking not needed, encoding length already checked before */
- (void) strcpy(name, _PathLocale);
- (void) strcat(name, "/");
- (void) strcat(name, encoding);
- (void) strcat(name, "/LC_CTYPE");
-
- if ((fp = fopen(name, "re")) == NULL)
- return (errno == 0 ? ENOENT : errno);
-
- if ((rl = _Read_RuneMagi(fp)) == NULL) {
- saverr = (errno == 0 ? EFTYPE : errno);
- (void)fclose(fp);
- return (saverr);
+ asprintf(&path, "%s/%s/LC_CTYPE", _PathLocale, encoding);
+ if (path == NULL)
+ return (0);
+
+ if ((rl = _Read_RuneMagi(path)) == NULL) {
+ free(path);
+ errno = EINVAL;
+ return (errno);
}
- (void)fclose(fp);
+ free(path);
l->__mbrtowc = NULL;
l->__mbsinit = NULL;
- l->__mbsnrtowcs = __mbsnrtowcs_std;
+ l->__mbsnrtowcs = NULL;
l->__wcrtomb = NULL;
- l->__wcsnrtombs = __wcsnrtombs_std;
+ l->__wcsnrtombs = NULL;
rl->__sputrune = NULL;
rl->__sgetrune = NULL;
- if (strcmp(rl->__encoding, "NONE") == 0)
- ret = _none_init(l, rl);
- else if (strcmp(rl->__encoding, "ASCII") == 0)
+ if (strcmp(rl->__encoding, "NONE:US-ASCII") == 0)
ret = _ascii_init(l, rl);
+ else if (strncmp(rl->__encoding, "NONE", 4) == 0)
+ ret = _none_init(l, rl);
else if (strcmp(rl->__encoding, "UTF-8") == 0)
ret = _UTF8_init(l, rl);
- else if (strcmp(rl->__encoding, "EUC") == 0)
- ret = _EUC_init(l, rl);
+ else if (strcmp(rl->__encoding, "EUC-CN") == 0)
+ ret = _EUC_CN_init(l, rl);
+ else if (strcmp(rl->__encoding, "EUC-JP") == 0)
+ ret = _EUC_JP_init(l, rl);
+ else if (strcmp(rl->__encoding, "EUC-KR") == 0)
+ ret = _EUC_KR_init(l, rl);
+ else if (strcmp(rl->__encoding, "EUC-TW") == 0)
+ ret = _EUC_TW_init(l, rl);
else if (strcmp(rl->__encoding, "GB18030") == 0)
ret = _GB18030_init(l, rl);
else if (strcmp(rl->__encoding, "GB2312") == 0)
@@ -211,7 +199,7 @@ __set_thread_rune_locale(locale_t loc)
#endif
void *
-__ctype_load(const char *locale, locale_t unused)
+__ctype_load(const char *locale, locale_t unused __unused)
{
struct xlocale_ctype *l = calloc(sizeof(struct xlocale_ctype), 1);
diff --git a/lib/libc/locale/table.c b/lib/libc/locale/table.c
index e89d479..80b19f5 100644
--- a/lib/libc/locale/table.c
+++ b/lib/libc/locale/table.c
@@ -101,16 +101,16 @@ const _RuneLocale _DefaultRuneLocale = {
_CTYPE_P|_CTYPE_R|_CTYPE_G,
_CTYPE_P|_CTYPE_R|_CTYPE_G,
_CTYPE_P|_CTYPE_R|_CTYPE_G,
- /*30*/ _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|0,
- _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|1,
- _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|2,
- _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|3,
- _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|4,
- _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|5,
- _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|6,
- _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|7,
- /*38*/ _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|8,
- _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|9,
+ /*30*/ _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|_CTYPE_N|0,
+ _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|_CTYPE_N|1,
+ _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|_CTYPE_N|2,
+ _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|_CTYPE_N|3,
+ _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|_CTYPE_N|4,
+ _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|_CTYPE_N|5,
+ _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|_CTYPE_N|6,
+ _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|_CTYPE_N|7,
+ /*38*/ _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|_CTYPE_N|8,
+ _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|_CTYPE_N|9,
_CTYPE_P|_CTYPE_R|_CTYPE_G,
_CTYPE_P|_CTYPE_R|_CTYPE_G,
_CTYPE_P|_CTYPE_R|_CTYPE_G,
diff --git a/lib/libc/locale/utf8.c b/lib/libc/locale/utf8.c
index 8ccfdb1..e096b87 100644
--- a/lib/libc/locale/utf8.c
+++ b/lib/libc/locale/utf8.c
@@ -1,4 +1,5 @@
/*-
+ * Copyright 2013 Garrett D'Amore <garrett@damore.org>
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2002-2004 Tim J. Robbins
* All rights reserved.
@@ -70,7 +71,7 @@ _UTF8_init(struct xlocale_ctype *l, _RuneLocale *rl)
l->__mbsnrtowcs = _UTF8_mbsnrtowcs;
l->__wcsnrtombs = _UTF8_wcsnrtombs;
l->runes = rl;
- l->__mb_cur_max = 6;
+ l->__mb_cur_max = 4;
/*
* UCS-4 encoding used as the internal representation, so
* slots 0x0080-0x00FF are occuped and must be excluded
@@ -165,6 +166,7 @@ _UTF8_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
wch = (unsigned char)*s++ & mask;
else
wch = us->ch;
+
for (i = (us->want == 0) ? 1 : 0; i < MIN(want, n); i++) {
if ((*s & 0xc0) != 0x80) {
/*
diff --git a/lib/libc/locale/wcsnrtombs.c b/lib/libc/locale/wcsnrtombs.c
index 2f3bf1e..ce77ebb 100644
--- a/lib/libc/locale/wcsnrtombs.c
+++ b/lib/libc/locale/wcsnrtombs.c
@@ -1,4 +1,6 @@
/*-
+ * Copyright 2013 Garrett D'Amore <garrett@damore.org>
+ * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2002-2004 Tim J. Robbins.
* All rights reserved.
*
@@ -57,21 +59,21 @@ wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src, size_t nwc,
size_t
__wcsnrtombs_std(char * __restrict dst, const wchar_t ** __restrict src,
- size_t nwc, size_t len, mbstate_t * __restrict ps)
+ size_t nwc, size_t len, mbstate_t * __restrict ps,
+ wcrtomb_pfn_t pwcrtomb)
{
mbstate_t mbsbak;
char buf[MB_LEN_MAX];
const wchar_t *s;
size_t nbytes;
size_t nb;
- struct xlocale_ctype *l = XLOCALE_CTYPE(__get_locale());
s = *src;
nbytes = 0;
if (dst == NULL) {
while (nwc-- > 0) {
- if ((nb = l->__wcrtomb(buf, *s, ps)) == (size_t)-1)
+ if ((nb = pwcrtomb(buf, *s, ps)) == (size_t)-1)
/* Invalid character - wcrtomb() sets errno. */
return ((size_t)-1);
else if (*s == L'\0')
@@ -85,7 +87,7 @@ __wcsnrtombs_std(char * __restrict dst, const wchar_t ** __restrict src,
while (len > 0 && nwc-- > 0) {
if (len > (size_t)MB_CUR_MAX) {
/* Enough space to translate in-place. */
- if ((nb = l->__wcrtomb(dst, *s, ps)) == (size_t)-1) {
+ if ((nb = pwcrtomb(dst, *s, ps)) == (size_t)-1) {
*src = s;
return ((size_t)-1);
}
@@ -98,7 +100,7 @@ __wcsnrtombs_std(char * __restrict dst, const wchar_t ** __restrict src,
* character is too long for the buffer.
*/
mbsbak = *ps;
- if ((nb = l->__wcrtomb(buf, *s, ps)) == (size_t)-1) {
+ if ((nb = pwcrtomb(buf, *s, ps)) == (size_t)-1) {
*src = s;
return ((size_t)-1);
}
diff --git a/lib/libc/locale/wctype.c b/lib/libc/locale/wctype.c
index de880b4..e207121 100644
--- a/lib/libc/locale/wctype.c
+++ b/lib/libc/locale/wctype.c
@@ -73,9 +73,10 @@ wctype_l(const char *property, locale_t locale)
"ideogram\0" /* BSD extension */
"special\0" /* BSD extension */
"phonogram\0" /* BSD extension */
+ "number\0" /* BSD extension */
"rune\0"; /* BSD extension */
static const wctype_t propmasks[] = {
- _CTYPE_A|_CTYPE_D,
+ _CTYPE_A|_CTYPE_N,
_CTYPE_A,
_CTYPE_B,
_CTYPE_C,
@@ -90,6 +91,7 @@ wctype_l(const char *property, locale_t locale)
_CTYPE_I,
_CTYPE_T,
_CTYPE_Q,
+ _CTYPE_N,
0xFFFFFF00L
};
size_t len1, len2;
diff --git a/lib/libc/net/getnameinfo.c b/lib/libc/net/getnameinfo.c
index c813189..4b7aecb 100644
--- a/lib/libc/net/getnameinfo.c
+++ b/lib/libc/net/getnameinfo.c
@@ -122,7 +122,8 @@ getnameinfo(const struct sockaddr *sa, socklen_t salen,
afd = find_afd(sa->sa_family);
if (afd == NULL)
return (EAI_FAMILY);
- if (sa->sa_family == PF_LOCAL) {
+ switch (sa->sa_family) {
+ case PF_LOCAL:
/*
* PF_LOCAL uses variable sa->sa_len depending on the
* content length of sun_path. Require 1 byte in
@@ -132,8 +133,17 @@ getnameinfo(const struct sockaddr *sa, socklen_t salen,
salen <= afd->a_socklen -
sizeofmember(struct sockaddr_un, sun_path))
return (EAI_FAIL);
- } else if (salen != afd->a_socklen)
- return (EAI_FAIL);
+ break;
+ case PF_LINK:
+ if (salen <= afd->a_socklen -
+ sizeofmember(struct sockaddr_dl, sdl_data))
+ return (EAI_FAIL);
+ break;
+ default:
+ if (salen != afd->a_socklen)
+ return (EAI_FAIL);
+ break;
+ }
return ((*afd->a_func)(afd, sa, salen, host, hostlen,
serv, servlen, flags));
diff --git a/lib/libc/resolv/res_data.c b/lib/libc/resolv/res_data.c
index f020838..e2f905f 100644
--- a/lib/libc/resolv/res_data.c
+++ b/lib/libc/resolv/res_data.c
@@ -77,9 +77,10 @@ const char *_res_sectioncodes[] = {
int res_ourserver_p(const res_state, const struct sockaddr_in *);
-int
+__noinline int
res_init(void) {
extern int __res_vinit(res_state, int);
+ res_state statp = &_res;
/*
* These three fields used to be statically initialized. This made
@@ -100,14 +101,14 @@ res_init(void) {
* set in RES_DEFAULT). Our solution is to declare such applications
* "broken". They could fool us by setting RES_INIT but none do (yet).
*/
- if (!_res.retrans)
- _res.retrans = RES_TIMEOUT;
- if (!_res.retry)
- _res.retry = RES_DFLRETRY;
- if (!(_res.options & RES_INIT))
- _res.options = RES_DEFAULT;
-
- return (__res_vinit(&_res, 1));
+ if (!statp->retrans)
+ statp->retrans = RES_TIMEOUT;
+ if (!statp->retry)
+ statp->retry = RES_DFLRETRY;
+ if (!(statp->options & RES_INIT))
+ statp->options = RES_DEFAULT;
+
+ return (__res_vinit(statp, 1));
}
void
@@ -122,10 +123,11 @@ fp_query(const u_char *msg, FILE *file) {
void
fp_nquery(const u_char *msg, int len, FILE *file) {
- if ((_res.options & RES_INIT) == 0U && res_init() == -1)
+ res_state statp = &_res;
+ if ((statp->options & RES_INIT) == 0U && res_init() == -1)
return;
- res_pquery(&_res, msg, len, file);
+ res_pquery(statp, msg, len, file);
}
int
@@ -138,23 +140,25 @@ res_mkquery(int op, /*!< opcode of query */
u_char *buf, /*!< buffer to put query */
int buflen) /*!< size of buffer */
{
- if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
- RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ res_state statp = &_res;
+ if ((statp->options & RES_INIT) == 0U && res_init() == -1) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
return (-1);
}
- return (res_nmkquery(&_res, op, dname, class, type,
+ return (res_nmkquery(statp, op, dname, class, type,
data, datalen,
newrr_in, buf, buflen));
}
int
res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) {
- if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
- RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ res_state statp = &_res;
+ if ((statp->options & RES_INIT) == 0U && res_init() == -1) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
return (-1);
}
- return (res_nmkupdate(&_res, rrecp_in, buf, buflen));
+ return (res_nmkupdate(statp, rrecp_in, buf, buflen));
}
int
@@ -163,11 +167,12 @@ res_query(const char *name, /*!< domain name */
u_char *answer, /*!< buffer to put answer */
int anslen) /*!< size of answer buffer */
{
- if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
- RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ res_state statp = &_res;
+ if ((statp->options & RES_INIT) == 0U && res_init() == -1) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
return (-1);
}
- return (res_nquery(&_res, name, class, type, answer, anslen));
+ return (res_nquery(statp, name, class, type, answer, anslen));
}
#ifndef _LIBC
@@ -189,12 +194,13 @@ res_isourserver(const struct sockaddr_in *inp) {
int
res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
- if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
+ res_state statp = &_res;
+ if ((statp->options & RES_INIT) == 0U && res_init() == -1) {
/* errno should have been set by res_init() in this case. */
return (-1);
}
- return (res_nsend(&_res, buf, buflen, ans, anssiz));
+ return (res_nsend(statp, buf, buflen, ans, anssiz));
}
#ifndef _LIBC
@@ -202,12 +208,13 @@ int
res_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key,
u_char *ans, int anssiz)
{
- if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
+ res_state statp = &_res;
+ if ((statp->options & RES_INIT) == 0U && res_init() == -1) {
/* errno should have been set by res_init() in this case. */
return (-1);
}
- return (res_nsendsigned(&_res, buf, buflen, key, ans, anssiz));
+ return (res_nsendsigned(statp, buf, buflen, key, ans, anssiz));
}
#endif
@@ -218,12 +225,13 @@ res_close(void) {
int
res_update(ns_updrec *rrecp_in) {
- if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
- RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ res_state statp = &_res;
+ if ((statp->options & RES_INIT) == 0U && res_init() == -1) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
return (-1);
}
- return (res_nupdate(&_res, rrecp_in, NULL));
+ return (res_nupdate(statp, rrecp_in, NULL));
}
int
@@ -232,12 +240,13 @@ res_search(const char *name, /*!< domain name */
u_char *answer, /*!< buffer to put answer */
int anslen) /*!< size of answer */
{
- if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
- RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ res_state statp = &_res;
+ if ((statp->options & RES_INIT) == 0U && res_init() == -1) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
return (-1);
}
- return (res_nsearch(&_res, name, class, type, answer, anslen));
+ return (res_nsearch(statp, name, class, type, answer, anslen));
}
int
@@ -247,24 +256,26 @@ res_querydomain(const char *name,
u_char *answer, /*!< buffer to put answer */
int anslen) /*!< size of answer */
{
- if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
- RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ res_state statp = &_res;
+ if ((statp->options & RES_INIT) == 0U && res_init() == -1) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
return (-1);
}
- return (res_nquerydomain(&_res, name, domain,
+ return (res_nquerydomain(statp, name, domain,
class, type,
answer, anslen));
}
u_int
res_randomid(void) {
- if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
- RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ res_state statp = &_res;
+ if ((statp->options & RES_INIT) == 0U && res_init() == -1) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
return (-1);
}
- return (res_nrandomid(&_res));
+ return (res_nrandomid(statp));
}
int
@@ -284,13 +295,15 @@ hostalias(const char *name) {
int
local_hostname_length(const char *hostname) {
int len_host, len_domain;
+ res_state statp;
- if (!*_res.defdname)
+ statp = &_res;
+ if (!*statp->defdname)
res_init();
len_host = strlen(hostname);
- len_domain = strlen(_res.defdname);
+ len_domain = strlen(statp->defdname);
if (len_host > len_domain &&
- !strcasecmp(hostname + len_host - len_domain, _res.defdname) &&
+ !strcasecmp(hostname + len_host - len_domain, statp->defdname) &&
hostname[len_host - len_domain - 1] == '.')
return (len_host - len_domain - 1);
return (0);
diff --git a/lib/libc/rpc/clnt_bcast.c b/lib/libc/rpc/clnt_bcast.c
index 7242aa4..a194ba6 100644
--- a/lib/libc/rpc/clnt_bcast.c
+++ b/lib/libc/rpc/clnt_bcast.c
@@ -636,13 +636,10 @@ rpc_broadcast_exp(rpcprog_t prog, rpcvers_t vers, rpcproc_t proc,
} /* The giant for loop */
done_broad:
- if (inbuf)
- (void) free(inbuf);
- if (outbuf)
- (void) free(outbuf);
+ free(inbuf);
+ free(outbuf);
#ifdef PORTMAP
- if (outbuf_pmap)
- (void) free(outbuf_pmap);
+ free(outbuf_pmap);
#endif /* PORTMAP */
for (i = 0; i < fdlistno; i++) {
(void)_close(fdlist[i].fd);
diff --git a/lib/libc/rpc/clnt_vc.c b/lib/libc/rpc/clnt_vc.c
index e463165..aa16b96 100644
--- a/lib/libc/rpc/clnt_vc.c
+++ b/lib/libc/rpc/clnt_vc.c
@@ -651,8 +651,7 @@ clnt_vc_destroy(CLIENT *cl)
(void)_close(ct->ct_fd);
}
XDR_DESTROY(&(ct->ct_xdrs));
- if (ct->ct_addr.buf)
- free(ct->ct_addr.buf);
+ free(ct->ct_addr.buf);
mem_free(ct, sizeof(struct ct_data));
if (cl->cl_netid && cl->cl_netid[0])
mem_free(cl->cl_netid, strlen(cl->cl_netid) +1);
diff --git a/lib/libc/rpc/getnetconfig.c b/lib/libc/rpc/getnetconfig.c
index c1e22da..6d668bf 100644
--- a/lib/libc/rpc/getnetconfig.c
+++ b/lib/libc/rpc/getnetconfig.c
@@ -164,8 +164,7 @@ __nc_error(void)
if ((nc_addr = (int *)thr_getspecific(nc_key)) == NULL) {
nc_addr = (int *)malloc(sizeof (int));
if (thr_setspecific(nc_key, (void *) nc_addr) != 0) {
- if (nc_addr)
- free(nc_addr);
+ free(nc_addr);
return (&nc_error);
}
*nc_addr = 0;
@@ -417,7 +416,7 @@ endnetconfig(void *handlep)
while (q != NULL) {
p = q->next;
- if (q->ncp->nc_lookups != NULL) free(q->ncp->nc_lookups);
+ free(q->ncp->nc_lookups);
free(q->ncp);
free(q->linep);
free(q);
@@ -537,8 +536,7 @@ freenetconfigent(struct netconfig *netconfigp)
{
if (netconfigp != NULL) {
free(netconfigp->nc_netid); /* holds all netconfigp's strings */
- if (netconfigp->nc_lookups != NULL)
- free(netconfigp->nc_lookups);
+ free(netconfigp->nc_lookups);
free(netconfigp);
}
return;
@@ -628,8 +626,7 @@ parse_ncp(char *stringp, struct netconfig *ncp)
} else {
char *cp; /* tmp string */
- if (ncp->nc_lookups != NULL) /* from last visit */
- free(ncp->nc_lookups);
+ free(ncp->nc_lookups); /* from last visit */
ncp->nc_lookups = NULL;
ncp->nc_nlookups = 0;
while ((cp = tokenp) != NULL) {
diff --git a/lib/libc/rpc/mt_misc.c b/lib/libc/rpc/mt_misc.c
index 2e17c27..0ec4d8a 100644
--- a/lib/libc/rpc/mt_misc.c
+++ b/lib/libc/rpc/mt_misc.c
@@ -106,8 +106,7 @@ __rpc_createerr(void)
rce_addr = (struct rpc_createerr *)
malloc(sizeof (struct rpc_createerr));
if (thr_setspecific(rce_key, (void *) rce_addr) != 0) {
- if (rce_addr)
- free(rce_addr);
+ free(rce_addr);
return (&rpc_createerr);
}
memset(rce_addr, 0, sizeof (struct rpc_createerr));
diff --git a/lib/libc/rpc/rpc_soc.c b/lib/libc/rpc/rpc_soc.c
index 8fc91ff..11fc803 100644
--- a/lib/libc/rpc/rpc_soc.c
+++ b/lib/libc/rpc/rpc_soc.c
@@ -432,8 +432,7 @@ clntunix_create(struct sockaddr_un *raddr, u_long prog, u_long vers, int *sockp,
if ((raddr->sun_len == 0) ||
((svcaddr = malloc(sizeof(struct netbuf))) == NULL ) ||
((svcaddr->buf = malloc(sizeof(struct sockaddr_un))) == NULL)) {
- if (svcaddr != NULL)
- free(svcaddr);
+ free(svcaddr);
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
rpc_createerr.cf_error.re_errno = errno;
return(cl);
diff --git a/lib/libc/rpc/rpcb_clnt.c b/lib/libc/rpc/rpcb_clnt.c
index d53d908..49300ed 100644
--- a/lib/libc/rpc/rpcb_clnt.c
+++ b/lib/libc/rpc/rpcb_clnt.c
@@ -179,8 +179,7 @@ delete_cache(struct netbuf *addr)
free(cptr->ac_netid);
free(cptr->ac_taddr->buf);
free(cptr->ac_taddr);
- if (cptr->ac_uaddr)
- free(cptr->ac_uaddr);
+ free(cptr->ac_uaddr);
if (prevptr)
prevptr->ac_next = cptr->ac_next;
else
@@ -216,14 +215,10 @@ add_cache(const char *host, const char *netid, struct netbuf *taddr,
ad_cache->ac_taddr->buf = (char *) malloc(taddr->len);
if (ad_cache->ac_taddr->buf == NULL) {
out:
- if (ad_cache->ac_host)
- free(ad_cache->ac_host);
- if (ad_cache->ac_netid)
- free(ad_cache->ac_netid);
- if (ad_cache->ac_uaddr)
- free(ad_cache->ac_uaddr);
- if (ad_cache->ac_taddr)
- free(ad_cache->ac_taddr);
+ free(ad_cache->ac_host);
+ free(ad_cache->ac_netid);
+ free(ad_cache->ac_uaddr);
+ free(ad_cache->ac_taddr);
free(ad_cache);
return;
}
@@ -256,8 +251,7 @@ out:
free(cptr->ac_netid);
free(cptr->ac_taddr->buf);
free(cptr->ac_taddr);
- if (cptr->ac_uaddr)
- free(cptr->ac_uaddr);
+ free(cptr->ac_uaddr);
if (prevptr) {
prevptr->ac_next = NULL;
@@ -798,10 +792,8 @@ __rpcb_findaddr_timed(rpcprog_t program, rpcvers_t version,
malloc(remote.len)) == NULL)) {
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
clnt_geterr(client, &rpc_createerr.cf_error);
- if (address) {
- free(address);
- address = NULL;
- }
+ free(address);
+ address = NULL;
goto error;
}
memcpy(address->buf, remote.buf, remote.len);
diff --git a/lib/libc/rpc/svc.c b/lib/libc/rpc/svc.c
index 38cbb79..d68fa9f 100644
--- a/lib/libc/rpc/svc.c
+++ b/lib/libc/rpc/svc.c
@@ -198,8 +198,7 @@ svc_reg(SVCXPRT *xprt, const rpcprog_t prog, const rpcvers_t vers,
rwlock_wrlock(&svc_lock);
if ((s = svc_find(prog, vers, &prev, netid)) != NULL) {
- if (netid)
- free(netid);
+ free(netid);
if (s->sc_dispatch == dispatch)
goto rpcb_it; /* he is registering another xptr */
rwlock_unlock(&svc_lock);
@@ -207,8 +206,7 @@ svc_reg(SVCXPRT *xprt, const rpcprog_t prog, const rpcvers_t vers,
}
s = mem_alloc(sizeof (struct svc_callout));
if (s == NULL) {
- if (netid)
- free(netid);
+ free(netid);
rwlock_unlock(&svc_lock);
return (FALSE);
}
diff --git a/lib/libc/rpc/svc_dg.c b/lib/libc/rpc/svc_dg.c
index 1957d64..5d9baaa 100644
--- a/lib/libc/rpc/svc_dg.c
+++ b/lib/libc/rpc/svc_dg.c
@@ -406,8 +406,7 @@ svc_dg_destroy(SVCXPRT *xprt)
(void) mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.maxlen);
if (xprt->xp_ltaddr.buf)
(void) mem_free(xprt->xp_ltaddr.buf, xprt->xp_ltaddr.maxlen);
- if (xprt->xp_tp)
- (void) free(xprt->xp_tp);
+ free(xprt->xp_tp);
svc_xprt_free(xprt);
}
diff --git a/lib/libc/rpc/svc_simple.c b/lib/libc/rpc/svc_simple.c
index 4713efc..9ce3f8d 100644
--- a/lib/libc/rpc/svc_simple.c
+++ b/lib/libc/rpc/svc_simple.c
@@ -166,10 +166,8 @@ rpc_reg(rpcprog_t prognum, rpcvers_t versnum, rpcproc_t procnum,
if (((xdrbuf = malloc((unsigned)recvsz)) == NULL) ||
((netid = strdup(nconf->nc_netid)) == NULL)) {
warnx(rpc_reg_err, rpc_reg_msg, __no_mem_str);
- if (xdrbuf != NULL)
- free(xdrbuf);
- if (netid != NULL)
- free(netid);
+ free(xdrbuf);
+ free(netid);
SVC_DESTROY(svcxprt);
break;
}
diff --git a/lib/libc/rpc/svc_vc.c b/lib/libc/rpc/svc_vc.c
index ca4b93e..bafb725 100644
--- a/lib/libc/rpc/svc_vc.c
+++ b/lib/libc/rpc/svc_vc.c
@@ -394,10 +394,8 @@ __svc_vc_dodestroy(SVCXPRT *xprt)
mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.maxlen);
if (xprt->xp_ltaddr.buf)
mem_free(xprt->xp_ltaddr.buf, xprt->xp_ltaddr.maxlen);
- if (xprt->xp_tp)
- free(xprt->xp_tp);
- if (xprt->xp_netid)
- free(xprt->xp_netid);
+ free(xprt->xp_tp);
+ free(xprt->xp_netid);
svc_xprt_free(xprt);
}
diff --git a/lib/libc/sparc64/fpu/fpu.c b/lib/libc/sparc64/fpu/fpu.c
index 431207f..e01701c 100644
--- a/lib/libc/sparc64/fpu/fpu.c
+++ b/lib/libc/sparc64/fpu/fpu.c
@@ -270,7 +270,7 @@ __fpu_execute(struct utrapframe *uf, struct fpemu *fe, u_int32_t insn,
u_long tstate)
{
struct fpn *fp;
- int opf, rs1, rs2, rd, type, mask, cx, cond;
+ int opf, rs1, rs2, rd, type, mask, cx, cond __unused;
u_long reg, fsr;
u_int space[4];
diff --git a/lib/libc/stdio/fdopen.c b/lib/libc/stdio/fdopen.c
index b936998..fbe37e8 100644
--- a/lib/libc/stdio/fdopen.c
+++ b/lib/libc/stdio/fdopen.c
@@ -91,7 +91,9 @@ fdopen(int fd, const char *mode)
* O_APPEND bit set, assert __SAPP so that __swrite() caller
* will _sseek() to the end before write.
*/
- if ((oflags & O_APPEND) && !(fdflags & O_APPEND))
+ if (fdflags & O_APPEND)
+ fp->_flags2 |= __S2OAP;
+ else if (oflags & O_APPEND)
fp->_flags |= __SAPP;
fp->_file = fd;
fp->_cookie = fp;
diff --git a/lib/libc/stdio/findfp.c b/lib/libc/stdio/findfp.c
index 0eabe82..b8bb5af 100644
--- a/lib/libc/stdio/findfp.c
+++ b/lib/libc/stdio/findfp.c
@@ -155,6 +155,7 @@ found:
/* fp->_fl_mutex = NULL; */ /* once set always set (reused) */
fp->_orientation = 0;
memset(&fp->_mbstate, 0, sizeof(mbstate_t));
+ fp->_flags2 = 0;
return (fp);
}
diff --git a/lib/libc/stdio/fmemopen.c b/lib/libc/stdio/fmemopen.c
index ebd3596..bcf187d 100644
--- a/lib/libc/stdio/fmemopen.c
+++ b/lib/libc/stdio/fmemopen.c
@@ -149,6 +149,9 @@ fmemopen(void * __restrict buf, size_t size, const char * __restrict mode)
return (NULL);
}
+ if (mode[0] == 'a')
+ f->_flags |= __SAPP;
+
/*
* Turn off buffering, so a write past the end of the buffer
* correctly returns a short object count.
diff --git a/lib/libc/stdio/fopen.c b/lib/libc/stdio/fopen.c
index b08e336..9ab61ba 100644
--- a/lib/libc/stdio/fopen.c
+++ b/lib/libc/stdio/fopen.c
@@ -91,7 +91,9 @@ fopen(const char * __restrict file, const char * __restrict mode)
* we can do about this. (We could set __SAPP and check in
* fseek and ftell.)
*/
- if (oflags & O_APPEND)
+ if (oflags & O_APPEND) {
+ fp->_flags2 |= __S2OAP;
(void)_sseek(fp, (fpos_t)0, SEEK_END);
+ }
return (fp);
}
diff --git a/lib/libc/stdio/freopen.c b/lib/libc/stdio/freopen.c
index 4dcd50f..e0104c8 100644
--- a/lib/libc/stdio/freopen.c
+++ b/lib/libc/stdio/freopen.c
@@ -187,6 +187,7 @@ finish:
fp->_lb._size = 0;
fp->_orientation = 0;
memset(&fp->_mbstate, 0, sizeof(mbstate_t));
+ fp->_flags2 = 0;
if (f < 0) { /* did not get it after all */
if (isopen)
@@ -240,8 +241,10 @@ finish:
* we can do about this. (We could set __SAPP and check in
* fseek and ftell.)
*/
- if (oflags & O_APPEND)
+ if (oflags & O_APPEND) {
+ fp->_flags2 |= __S2OAP;
(void) _sseek(fp, (fpos_t)0, SEEK_END);
+ }
FUNLOCKFILE(fp);
return (fp);
}
diff --git a/lib/libc/stdio/ftell.c b/lib/libc/stdio/ftell.c
index 745d500..fc792af 100644
--- a/lib/libc/stdio/ftell.c
+++ b/lib/libc/stdio/ftell.c
@@ -39,7 +39,6 @@ __FBSDID("$FreeBSD$");
#include "namespace.h"
#include <sys/types.h>
#include <errno.h>
-#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include "un-namespace.h"
@@ -88,7 +87,6 @@ _ftello(FILE *fp, fpos_t *offset)
{
fpos_t pos;
size_t n;
- int dflags;
if (fp->_seek == NULL) {
errno = ESPIPE; /* historic practice */
@@ -99,7 +97,13 @@ _ftello(FILE *fp, fpos_t *offset)
* Find offset of underlying I/O object, then
* adjust for buffered bytes.
*/
- if (fp->_flags & __SOFF)
+ if (!(fp->_flags & __SRD) && (fp->_flags & __SWR) &&
+ fp->_p != NULL && fp->_p - fp->_bf._base > 0 &&
+ ((fp->_flags & __SAPP) || (fp->_flags2 & __S2OAP))) {
+ pos = _sseek(fp, (fpos_t)0, SEEK_END);
+ if (pos == -1)
+ return (1);
+ } else if (fp->_flags & __SOFF)
pos = fp->_offset;
else {
pos = _sseek(fp, (fpos_t)0, SEEK_CUR);
@@ -119,29 +123,13 @@ _ftello(FILE *fp, fpos_t *offset)
}
if (HASUB(fp))
pos -= fp->_r; /* Can be negative at this point. */
- } else if ((fp->_flags & __SWR) && fp->_p != NULL) {
- dflags = 0;
- if (fp->_flags & __SAPP)
- dflags = O_APPEND;
- else if (fp->_file != -1 &&
- (dflags = _fcntl(fp->_file, F_GETFL)) < 0)
- return (1);
- if ((dflags & O_APPEND) &&
- (pos = _sseek(fp, (fpos_t)0, SEEK_END)) == -1) {
- if ((fp->_flags & __SOPT) || __sflush(fp) ||
- (pos = _sseek(fp, (fpos_t)0, SEEK_CUR)) == -1)
- return (1);
- else {
- *offset = pos;
- return (0);
- }
- }
+ } else if ((fp->_flags & __SWR) && fp->_p != NULL &&
+ (n = fp->_p - fp->_bf._base) > 0) {
/*
* Writing. Any buffered characters cause the
* position to be greater than that in the
* underlying object.
*/
- n = fp->_p - fp->_bf._base;
if (pos > OFF_MAX - n) {
errno = EOVERFLOW;
return (1);
diff --git a/lib/libc/stdio/stdio.c b/lib/libc/stdio/stdio.c
index 44ee0ab..5d6fb9a 100644
--- a/lib/libc/stdio/stdio.c
+++ b/lib/libc/stdio/stdio.c
@@ -117,7 +117,7 @@ _swrite(FILE *fp, char const *buf, int n)
ret = (*fp->_write)(fp->_cookie, buf, n);
/* __SOFF removed even on success in case O_APPEND mode is set. */
if (ret >= 0) {
- if ((fp->_flags & (__SAPP|__SOFF)) == (__SAPP|__SOFF) &&
+ if ((fp->_flags & __SOFF) && !(fp->_flags2 & __S2OAP) &&
fp->_offset <= OFF_MAX - ret)
fp->_offset += ret;
else
diff --git a/lib/libc/string/strcoll.c b/lib/libc/string/strcoll.c
index a918fca..7675e0a 100644
--- a/lib/libc/string/strcoll.c
+++ b/lib/libc/string/strcoll.c
@@ -1,4 +1,5 @@
/*-
+ * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
* at Electronni Visti IA, Kiev, Ukraine.
* All rights reserved.
@@ -35,63 +36,78 @@ __FBSDID("$FreeBSD$");
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
+#include <wchar.h>
#include "collate.h"
-#include <stdio.h>
+/*
+ * In order to properly handle multibyte locales, its easiest to just
+ * convert to wide characters and then use wcscoll. However if an
+ * error occurs, we gracefully fall back to simple strcmp. Caller
+ * should check errno.
+ */
int
strcoll_l(const char *s, const char *s2, locale_t locale)
{
- int len, len2, prim, prim2, sec, sec2, ret, ret2;
- const char *t, *t2;
- char *tt, *tt2;
+ int ret;
+ wchar_t *t1 = NULL, *t2 = NULL;
+ wchar_t *w1 = NULL, *w2 = NULL;
+ const char *cs1, *cs2;
+ mbstate_t mbs1;
+ mbstate_t mbs2;
+ size_t sz1, sz2;
+
+ memset(&mbs1, 0, sizeof (mbstate_t));
+ memset(&mbs2, 0, sizeof (mbstate_t));
+
+ /*
+ * The mbsrtowcs_l function can set the src pointer to null upon
+ * failure, so it should act on a copy to avoid:
+ * - sending null pointer to strcmp
+ * - having strcoll/strcoll_l change *s or *s2 to null
+ */
+ cs1 = s;
+ cs2 = s2;
+
FIX_LOCALE(locale);
struct xlocale_collate *table =
(struct xlocale_collate*)locale->components[XLC_COLLATE];
if (table->__collate_load_error)
- return strcmp(s, s2);
-
- len = len2 = 1;
- ret = ret2 = 0;
- if (table->__collate_substitute_nontrivial) {
- t = tt = __collate_substitute(table, s);
- t2 = tt2 = __collate_substitute(table, s2);
- } else {
- tt = tt2 = NULL;
- t = s;
- t2 = s2;
- }
- while(*t && *t2) {
- prim = prim2 = 0;
- while(*t && !prim) {
- __collate_lookup(table, t, &len, &prim, &sec);
- t += len;
- }
- while(*t2 && !prim2) {
- __collate_lookup(table, t2, &len2, &prim2, &sec2);
- t2 += len2;
- }
- if(!prim || !prim2)
- break;
- if(prim != prim2) {
- ret = prim - prim2;
- goto end;
- }
- if(!ret2)
- ret2 = sec - sec2;
- }
- if(!*t && *t2)
- ret = -(int)((u_char)*t2);
- else if(*t && !*t2)
- ret = (u_char)*t;
- else if(!*t && !*t2)
- ret = ret2;
- end:
- free(tt);
- free(tt2);
-
- return ret;
+ goto error;
+
+ sz1 = strlen(s) + 1;
+ sz2 = strlen(s2) + 1;
+
+ /*
+ * Simple assumption: conversion to wide format is strictly
+ * reducing, i.e. a single byte (or multibyte character)
+ * cannot result in multiple wide characters.
+ */
+ if ((t1 = malloc(sz1 * sizeof (wchar_t))) == NULL)
+ goto error;
+ w1 = t1;
+ if ((t2 = malloc(sz2 * sizeof (wchar_t))) == NULL)
+ goto error;
+ w2 = t2;
+
+ if ((mbsrtowcs_l(w1, &cs1, sz1, &mbs1, locale)) == (size_t)-1)
+ goto error;
+
+ if ((mbsrtowcs_l(w2, &cs2, sz2, &mbs2, locale)) == (size_t)-1)
+ goto error;
+
+ ret = wcscoll_l(w1, w2, locale);
+ free(t1);
+ free(t2);
+
+ return (ret);
+
+error:
+ free(t1);
+ free(t2);
+ return (strcmp(s, s2));
}
int
diff --git a/lib/libc/string/strxfrm.c b/lib/libc/string/strxfrm.c
index b758b0c..06ae639 100644
--- a/lib/libc/string/strxfrm.c
+++ b/lib/libc/string/strxfrm.c
@@ -1,4 +1,5 @@
/*-
+ * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
* at Electronni Visti IA, Kiev, Ukraine.
* All rights reserved.
@@ -35,6 +36,8 @@ __FBSDID("$FreeBSD$");
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
+#include <wchar.h>
#include "collate.h"
size_t
@@ -48,9 +51,10 @@ strxfrm(char * __restrict dest, const char * __restrict src, size_t len)
size_t
strxfrm_l(char * __restrict dest, const char * __restrict src, size_t len, locale_t locale)
{
- int prim, sec, l;
size_t slen;
- char *s, *ss;
+ size_t xlen;
+ wchar_t *wcs = NULL;
+
FIX_LOCALE(locale);
struct xlocale_collate *table =
(struct xlocale_collate*)locale->components[XLC_COLLATE];
@@ -58,32 +62,42 @@ strxfrm_l(char * __restrict dest, const char * __restrict src, size_t len, local
if (!*src) {
if (len > 0)
*dest = '\0';
- return 0;
+ return (0);
}
+ /*
+ * The conversion from multibyte to wide character strings is
+ * strictly reducing (one byte of an mbs cannot expand to more
+ * than one wide character.)
+ */
+ slen = strlen(src);
+
if (table->__collate_load_error)
- return strlcpy(dest, src, len);
-
- slen = 0;
- prim = sec = 0;
- ss = s = __collate_substitute(table, src);
- while (*s) {
- while (*s && !prim) {
- __collate_lookup(table, s, &l, &prim, &sec);
- s += l;
- }
- if (prim) {
- if (len > 1) {
- *dest++ = (char)prim;
- len--;
- }
- slen++;
- prim = 0;
- }
+ goto error;
+
+ if ((wcs = malloc((slen + 1) * sizeof (wchar_t))) == NULL)
+ goto error;
+
+ if (mbstowcs_l(wcs, src, slen + 1, locale) == (size_t)-1)
+ goto error;
+
+ if ((xlen = _collate_sxfrm(table, wcs, dest, len)) == (size_t)-1)
+ goto error;
+
+ free(wcs);
+
+ if (len > xlen) {
+ dest[xlen] = 0;
+ } else if (len) {
+ dest[len-1] = 0;
}
- free(ss);
- if (len > 0)
- *dest = '\0';
- return slen;
+ return (xlen);
+
+error:
+ /* errno should be set to ENOMEM if malloc failed */
+ free(wcs);
+ strlcpy(dest, src, len);
+
+ return (slen);
}
diff --git a/lib/libc/string/wcscoll.c b/lib/libc/string/wcscoll.c
index 3c51015..ee0e72a 100644
--- a/lib/libc/string/wcscoll.c
+++ b/lib/libc/string/wcscoll.c
@@ -1,4 +1,5 @@
/*-
+ * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2002 Tim J. Robbins
* All rights reserved.
*
@@ -38,50 +39,181 @@ __FBSDID("$FreeBSD$");
#include <wchar.h>
#include "collate.h"
-static char *__mbsdup(const wchar_t *);
-
-/*
- * Placeholder implementation of wcscoll(). Attempts to use the single-byte
- * collation ordering where possible, and falls back on wcscmp() in locales
- * with extended character sets.
- */
int
wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t locale)
{
- char *mbs1, *mbs2;
- int diff, sverrno;
+ int len1, len2, pri1, pri2, ret;
+ wchar_t *tr1 = NULL, *tr2 = NULL;
+ int direc, pass;
+
FIX_LOCALE(locale);
struct xlocale_collate *table =
(struct xlocale_collate*)locale->components[XLC_COLLATE];
- if (table->__collate_load_error || MB_CUR_MAX > 1)
+ if (table->__collate_load_error)
/*
- * Locale has no special collating order, could not be
- * loaded, or has an extended character set; do a fast binary
- * comparison.
+ * Locale has no special collating order or could not be
+ * loaded, do a fast binary comparison.
*/
return (wcscmp(ws1, ws2));
- if ((mbs1 = __mbsdup(ws1)) == NULL || (mbs2 = __mbsdup(ws2)) == NULL) {
- /*
- * Out of memory or illegal wide chars; fall back to wcscmp()
- * but leave errno indicating the error. Callers that don't
- * check for error will get a reasonable but often slightly
- * incorrect result.
- */
- sverrno = errno;
- free(mbs1);
- errno = sverrno;
- return (wcscmp(ws1, ws2));
+ ret = 0;
+
+ /*
+ * Once upon a time we had code to try to optimize this, but
+ * it turns out that you really can't make many assumptions
+ * safely. You absolutely have to run this pass by pass,
+ * because some passes will be ignored for a given character,
+ * while others will not. Simpler locales will benefit from
+ * having fewer passes, and most comparisions should resolve
+ * during the primary pass anyway.
+ *
+ * Note that we do one final extra pass at the end to pick
+ * up UNDEFINED elements. There is special handling for them.
+ */
+ for (pass = 0; pass <= table->info->directive_count; pass++) {
+
+ const int32_t *st1 = NULL;
+ const int32_t *st2 = NULL;
+ const wchar_t *w1 = ws1;
+ const wchar_t *w2 = ws2;
+ int check1, check2;
+
+ /* special pass for UNDEFINED */
+ if (pass == table->info->directive_count) {
+ direc = DIRECTIVE_FORWARD | DIRECTIVE_UNDEFINED;
+ } else {
+ direc = table->info->directive[pass];
+ }
+
+ if (direc & DIRECTIVE_BACKWARD) {
+ wchar_t *bp, *fp, c;
+ if ((tr1 = wcsdup(w1)) == NULL)
+ goto fail;
+ bp = tr1;
+ fp = tr1 + wcslen(tr1) - 1;
+ while (bp < fp) {
+ c = *bp;
+ *bp++ = *fp;
+ *fp-- = c;
+ }
+ if ((tr2 = wcsdup(w2)) == NULL)
+ goto fail;
+ bp = tr2;
+ fp = tr2 + wcslen(tr2) - 1;
+ while (bp < fp) {
+ c = *bp;
+ *bp++ = *fp;
+ *fp-- = c;
+ }
+ w1 = tr1;
+ w2 = tr2;
+ }
+
+ if (direc & DIRECTIVE_POSITION) {
+ while (*w1 && *w2) {
+ pri1 = pri2 = 0;
+ check1 = check2 = 1;
+ while ((pri1 == pri2) && (check1 || check2)) {
+ if (check1) {
+ _collate_lookup(table, w1, &len1,
+ &pri1, pass, &st1);
+ if (pri1 < 0) {
+ errno = EINVAL;
+ goto fail;
+ }
+ if (!pri1) {
+ pri1 = COLLATE_MAX_PRIORITY;
+ st1 = NULL;
+ }
+ check1 = (st1 != NULL);
+ }
+ if (check2) {
+ _collate_lookup(table, w2, &len2,
+ &pri2, pass, &st2);
+ if (pri2 < 0) {
+ errno = EINVAL;
+ goto fail;
+ }
+ if (!pri2) {
+ pri2 = COLLATE_MAX_PRIORITY;
+ st2 = NULL;
+ }
+ check2 = (st2 != NULL);
+ }
+ }
+ if (pri1 != pri2) {
+ ret = pri1 - pri2;
+ goto end;
+ }
+ w1 += len1;
+ w2 += len2;
+ }
+ } else {
+ while (*w1 && *w2) {
+ pri1 = pri2 = 0;
+ check1 = check2 = 1;
+ while ((pri1 == pri2) && (check1 || check2)) {
+ while (check1 && *w1) {
+ _collate_lookup(table, w1,
+ &len1, &pri1, pass, &st1);
+ if (pri1 > 0)
+ break;
+ if (pri1 < 0) {
+ errno = EINVAL;
+ goto fail;
+ }
+ st1 = NULL;
+ w1 += 1;
+ }
+ check1 = (st1 != NULL);
+ while (check2 && *w2) {
+ _collate_lookup(table, w2,
+ &len2, &pri2, pass, &st2);
+ if (pri2 > 0)
+ break;
+ if (pri2 < 0) {
+ errno = EINVAL;
+ goto fail;
+ }
+ st2 = NULL;
+ w2 += 1;
+ }
+ check2 = (st2 != NULL);
+ if (!pri1 || !pri2)
+ break;
+ }
+ if (!pri1 || !pri2)
+ break;
+ if (pri1 != pri2) {
+ ret = pri1 - pri2;
+ goto end;
+ }
+ w1 += len1;
+ w2 += len2;
+ }
+ }
+ if (!*w1) {
+ if (*w2) {
+ ret = -(int)*w2;
+ goto end;
+ }
+ } else {
+ ret = *w1;
+ goto end;
+ }
}
+ ret = 0;
- diff = strcoll_l(mbs1, mbs2, locale);
- sverrno = errno;
- free(mbs1);
- free(mbs2);
- errno = sverrno;
+end:
+ free(tr1);
+ free(tr2);
- return (diff);
+ return (ret);
+
+fail:
+ ret = wcscmp(ws1, ws2);
+ goto end;
}
int
@@ -89,24 +221,3 @@ wcscoll(const wchar_t *ws1, const wchar_t *ws2)
{
return wcscoll_l(ws1, ws2, __get_locale());
}
-
-static char *
-__mbsdup(const wchar_t *ws)
-{
- static const mbstate_t initial;
- mbstate_t st;
- const wchar_t *wcp;
- size_t len;
- char *mbs;
-
- wcp = ws;
- st = initial;
- if ((len = wcsrtombs(NULL, &wcp, 0, &st)) == (size_t)-1)
- return (NULL);
- if ((mbs = malloc(len + 1)) == NULL)
- return (NULL);
- st = initial;
- wcsrtombs(mbs, &ws, len + 1, &st);
-
- return (mbs);
-}
diff --git a/lib/libc/string/wcsxfrm.c b/lib/libc/string/wcsxfrm.c
index cea667e..3d6c960 100644
--- a/lib/libc/string/wcsxfrm.c
+++ b/lib/libc/string/wcsxfrm.c
@@ -1,4 +1,5 @@
/*-
+ * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
* at Electronni Visti IA, Kiev, Ukraine.
* All rights reserved.
@@ -31,9 +32,6 @@
*/
#include <sys/cdefs.h>
-#if 0
-__FBSDID("FreeBSD: src/lib/libc/string/strxfrm.c,v 1.15 2002/09/06 11:24:06 tjr Exp ");
-#endif
__FBSDID("$FreeBSD$");
#include <stdlib.h>
@@ -41,18 +39,10 @@ __FBSDID("$FreeBSD$");
#include <wchar.h>
#include "collate.h"
-static char *__mbsdup(const wchar_t *);
-
-/*
- * Placeholder wcsxfrm() implementation. See wcscoll.c for a description of
- * the logic used.
- */
size_t
wcsxfrm_l(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len, locale_t locale)
{
- int prim, sec, l;
size_t slen;
- char *mbsrc, *s, *ss;
FIX_LOCALE(locale);
struct xlocale_collate *table =
(struct xlocale_collate*)locale->components[XLC_COLLATE];
@@ -63,67 +53,33 @@ wcsxfrm_l(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len,
return (0);
}
- if (table->__collate_load_error || MB_CUR_MAX > 1) {
- slen = wcslen(src);
- if (len > 0) {
- if (slen < len)
- wcscpy(dest, src);
- else {
- wcsncpy(dest, src, len - 1);
- dest[len - 1] = L'\0';
- }
- }
- return (slen);
+ if ((table->__collate_load_error) ||
+ ((slen = _collate_wxfrm(table, src, dest, len)) == (size_t)-1)) {
+ goto error;
}
- mbsrc = __mbsdup(src);
- slen = 0;
- prim = sec = 0;
- ss = s = __collate_substitute(table, mbsrc);
- while (*s != '\0') {
- while (*s != '\0' && prim == 0) {
- __collate_lookup(table, s, &l, &prim, &sec);
- s += l;
- }
- if (prim != 0) {
- if (len > 1) {
- *dest++ = (wchar_t)prim;
- len--;
- }
- slen++;
- prim = 0;
- }
+ /* Add null termination at the correct location. */
+ if (len > slen) {
+ dest[slen] = 0;
+ } else if (len) {
+ dest[len-1] = 0;
}
- free(ss);
- free(mbsrc);
- if (len != 0)
- *dest = L'\0';
return (slen);
+
+error:
+ slen = wcslen(src);
+ if (slen < len)
+ (void) wcscpy(dest, src);
+ else {
+ (void) wcsncpy(dest, src, len - 1);
+ dest[len - 1] = L'\0';
+ }
+ return (slen);
}
+
size_t
wcsxfrm(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len)
{
return wcsxfrm_l(dest, src, len, __get_locale());
}
-
-static char *
-__mbsdup(const wchar_t *ws)
-{
- static const mbstate_t initial;
- mbstate_t st;
- const wchar_t *wcp;
- size_t len;
- char *mbs;
-
- wcp = ws;
- st = initial;
- if ((len = wcsrtombs(NULL, &wcp, 0, &st)) == (size_t)-1)
- return (NULL);
- if ((mbs = malloc(len + 1)) == NULL)
- return (NULL);
- st = initial;
- wcsrtombs(mbs, &ws, len + 1, &st);
-
- return (mbs);
-}
diff --git a/lib/libc/sys/cpuset.2 b/lib/libc/sys/cpuset.2
index 8349566..d16b3ff 100644
--- a/lib/libc/sys/cpuset.2
+++ b/lib/libc/sys/cpuset.2
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd January 8, 2015
+.Dd October 20, 2015
.Dt CPUSET 2
.Os
.Sh NAME
@@ -219,7 +219,8 @@ for allocation.
.Xr cpuset_getaffinity 2 ,
.Xr cpuset_setaffinity 2 ,
.Xr pthread_affinity_np 3 ,
-.Xr pthread_attr_affinity_np 3
+.Xr pthread_attr_affinity_np 3 ,
+.Xr cpuset 9
.Sh HISTORY
The
.Nm
diff --git a/lib/libc/sys/cpuset_getaffinity.2 b/lib/libc/sys/cpuset_getaffinity.2
index 810a03c..7032d2e 100644
--- a/lib/libc/sys/cpuset_getaffinity.2
+++ b/lib/libc/sys/cpuset_getaffinity.2
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd September 10, 2010
+.Dd October 20, 2015
.Dt CPUSET_GETAFFINITY 2
.Os
.Sh NAME
@@ -153,7 +153,8 @@ operation.
.Xr cpuset_getid 2 ,
.Xr cpuset_setid 2 ,
.Xr pthread_affinity_np 3 ,
-.Xr pthread_attr_affinity_np 3
+.Xr pthread_attr_affinity_np 3 ,
+.Xr cpuset 9
.Sh HISTORY
The
.Nm
diff --git a/lib/libc/sys/ptrace.2 b/lib/libc/sys/ptrace.2
index 5c93438..a94e314 100644
--- a/lib/libc/sys/ptrace.2
+++ b/lib/libc/sys/ptrace.2
@@ -2,7 +2,7 @@
.\" $NetBSD: ptrace.2,v 1.2 1995/02/27 12:35:37 cgd Exp $
.\"
.\" This file is in the public domain.
-.Dd October 6, 2015
+.Dd October 20, 2015
.Dt PTRACE 2
.Os
.Sh NAME
@@ -306,7 +306,7 @@ struct ptrace_lwpinfo {
sigset_t pl_siglist;
siginfo_t pl_siginfo;
char pl_tdname[MAXCOMLEN + 1];
- int pl_child_pid;
+ pid_t pl_child_pid;
u_int pl_syscall_code;
u_int pl_syscall_narg;
};
diff --git a/lib/libc/tests/Makefile b/lib/libc/tests/Makefile
index 2e97151..e6ddc15 100644
--- a/lib/libc/tests/Makefile
+++ b/lib/libc/tests/Makefile
@@ -11,6 +11,7 @@ TESTS_SUBDIRS+= hash
TESTS_SUBDIRS+= inet
TESTS_SUBDIRS+= net
TESTS_SUBDIRS+= regex
+TESTS_SUBDIRS+= rpc
TESTS_SUBDIRS+= stdio
TESTS_SUBDIRS+= stdlib
TESTS_SUBDIRS+= string
diff --git a/lib/libc/tests/Makefile.netbsd-tests b/lib/libc/tests/Makefile.netbsd-tests
index 3238518..18b0276 100644
--- a/lib/libc/tests/Makefile.netbsd-tests
+++ b/lib/libc/tests/Makefile.netbsd-tests
@@ -4,4 +4,6 @@ TESTSRC:= ${SRCTOP}/contrib/netbsd-tests/${RELDIR:C/libc\/tests/libc/}
TESTSDIR:= ${TESTSBASE}/${RELDIR:C/libc\/tests/libc/}
+WARNS?= 2
+
.include <netbsd-tests.test.mk>
diff --git a/lib/libc/tests/c063/Makefile b/lib/libc/tests/c063/Makefile
index 2e4565c..05da6ea 100644
--- a/lib/libc/tests/c063/Makefile
+++ b/lib/libc/tests/c063/Makefile
@@ -2,21 +2,21 @@
#TODO: t_o_search
-NETBSD_ATF_TESTS_C= faccessat
-NETBSD_ATF_TESTS_C+= fchmodat
-NETBSD_ATF_TESTS_C+= fchownat
-NETBSD_ATF_TESTS_C+= fexecve
-NETBSD_ATF_TESTS_C+= fstatat
-NETBSD_ATF_TESTS_C+= linkat
-NETBSD_ATF_TESTS_C+= mkdirat
-NETBSD_ATF_TESTS_C+= mkfifoat
-NETBSD_ATF_TESTS_C+= mknodat
-NETBSD_ATF_TESTS_C+= openat
-NETBSD_ATF_TESTS_C+= readlinkat
-NETBSD_ATF_TESTS_C+= renameat
-NETBSD_ATF_TESTS_C+= symlinkat
-NETBSD_ATF_TESTS_C+= unlinkat
-NETBSD_ATF_TESTS_C+= utimensat
+NETBSD_ATF_TESTS_C= faccessat_test
+NETBSD_ATF_TESTS_C+= fchmodat_test
+NETBSD_ATF_TESTS_C+= fchownat_test
+NETBSD_ATF_TESTS_C+= fexecve_test
+NETBSD_ATF_TESTS_C+= fstatat_test
+NETBSD_ATF_TESTS_C+= linkat_test
+NETBSD_ATF_TESTS_C+= mkdirat_test
+NETBSD_ATF_TESTS_C+= mkfifoat_test
+NETBSD_ATF_TESTS_C+= mknodat_test
+NETBSD_ATF_TESTS_C+= openat_test
+NETBSD_ATF_TESTS_C+= readlinkat_test
+NETBSD_ATF_TESTS_C+= renameat_test
+NETBSD_ATF_TESTS_C+= symlinkat_test
+NETBSD_ATF_TESTS_C+= unlinkat_test
+NETBSD_ATF_TESTS_C+= utimensat_test
CFLAGS+= -D_INCOMPLETE_XOPEN_C063
diff --git a/lib/libc/tests/gen/Makefile b/lib/libc/tests/gen/Makefile
index 90f6573..476b5b7 100644
--- a/lib/libc/tests/gen/Makefile
+++ b/lib/libc/tests/gen/Makefile
@@ -2,8 +2,15 @@
.include <bsd.own.mk>
-ATF_TESTS_C= arc4random_test
+ATF_TESTS_C+= arc4random_test
+ATF_TESTS_C+= fmtcheck2_test
+ATF_TESTS_C+= fmtmsg_test
+ATF_TESTS_C+= fnmatch2_test
ATF_TESTS_C+= fpclassify2_test
+ATF_TESTS_C+= ftw_test
+ATF_TESTS_C+= popen_test
+ATF_TESTS_C+= posix_spawn_test
+ATF_TESTS_C+= wordexp_test
# TODO: t_closefrom, t_cpuset, t_fmtcheck, t_randomid, t_sleep
# TODO: t_siginfo (fixes require further inspection)
@@ -53,7 +60,25 @@ DPADD.nice_test+= ${LIBPTHREAD}
LDADD.syslog_test+= -lpthread
DPADD.syslog_test+= ${LIBPTHREAD}
+CFLAGS+= -I${.CURDIR}
+
+SRCS.fmtcheck2_test= fmtcheck_test.c
+SRCS.fnmatch2_test= fnmatch_test.c
+
TESTS_SUBDIRS= execve
TESTS_SUBDIRS+= posix_spawn
+# The old testcase name
+TEST_FNMATCH= test-fnmatch
+CLEANFILES+= ${GEN_SH_CASE_TESTCASES}
+sh-tests: .PHONY
+.for target in clean obj depend all
+ @cd ${.CURDIR} && ${MAKE} PROG=${TEST_FNMATCH} \
+ -DNO_SUBDIR ${target}
+.endfor
+ @cd ${.OBJDIR} && ./${TEST_FNMATCH} -s 1 > \
+ ${SRCTOP}/bin/sh/tests/builtins/case2.0
+ @cd ${.OBJDIR} && ./${TEST_FNMATCH} -s 2 > \
+ ${SRCTOP}/bin/sh/tests/builtins/case3.0
+
.include <bsd.test.mk>
diff --git a/lib/libc/tests/gen/arc4random_test.c b/lib/libc/tests/gen/arc4random_test.c
index ec82c32..a28db30 100644
--- a/lib/libc/tests/gen/arc4random_test.c
+++ b/lib/libc/tests/gen/arc4random_test.c
@@ -30,10 +30,12 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/wait.h>
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+
#include <atf-c.h>
/*
@@ -56,14 +58,9 @@ ATF_TC_BODY(test_arc4random, tc)
pid_t pid;
char c;
- printf("1..1\n");
-
page = mmap(NULL, sizeof(struct shared_page), PROT_READ | PROT_WRITE,
MAP_ANON | MAP_SHARED, -1, 0);
- if (page == MAP_FAILED) {
- printf("fail 1 - mmap\n");
- exit(1);
- }
+ ATF_REQUIRE_MSG(page != MAP_FAILED, "mmap failed; errno=%d", errno);
arc4random_buf(&c, 1);
diff --git a/lib/libc/tests/gen/fmtcheck_test.c b/lib/libc/tests/gen/fmtcheck_test.c
new file mode 100644
index 0000000..3e180c9
--- /dev/null
+++ b/lib/libc/tests/gen/fmtcheck_test.c
@@ -0,0 +1,105 @@
+/* $NetBSD: tfmtcheck.c,v 1.3 2008/04/28 20:23:04 martin Exp $ */
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code was contributed to The NetBSD Foundation by Allen Briggs.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <atf-c.h>
+
+struct test_fmt {
+ char *fmt1;
+ char *fmt2;
+ int correct;
+} test_fmts[] = {
+ { "%d", "%d", 1 },
+ { "%2d", "%2.2d", 1 },
+ { "%x", "%d", 1 },
+ { "%u", "%d", 1 },
+ { "%03d", "%d", 1 },
+ { "%-2d", "%d", 1 },
+ { "%d", "%-12.1d", 1 },
+ { "%d", "%-01.3d", 1 },
+ { "%X", "%-01.3d", 1 },
+ { "%D", "%ld", 1 },
+ { "%s", "%s", 1 },
+ { "%s", "This is a %s test", 1 },
+ { "Hi, there. This is a %s test", "%s", 1 },
+ { "%d", "%s", 2 },
+ { "%e", "%s", 2 },
+ { "%r", "%d", 2 },
+ { "%*.2d", "%*d", 1 },
+ { "%2.*d", "%*d", 2 },
+ { "%*d", "%*d", 1 },
+ { "%-3", "%d", 2 },
+ { "%d %s", "%d", 2 },
+ { "%*.*.*d", "%*.*.*d", 2 },
+ { "%d", "%d %s", 1 },
+ { "%40s", "%20s", 1 },
+ { "%x %x %x", "%o %u %d", 1 },
+ { "%o %u %d", "%x %x %X", 1 },
+ { "%#o %u %#-d", "%x %#x %X", 1 },
+ { "%qd", "%llx", 1 },
+ { "%%", "%llx", 1 },
+ { "%p %30s %#llx %-10.*e", "This number %lu%% and string %s has %qd numbers and %.*g floats", 1 },
+};
+
+ATF_TC_WITHOUT_HEAD(fmtcheck_test);
+ATF_TC_BODY(fmtcheck_test, tc)
+{
+ int i;
+ const char *f, *cf, *f1, *f2;
+
+ for (i = 0; i < nitems(test_fmts); i++) {
+ f1 = test_fmts[i].fmt1;
+ f2 = test_fmts[i].fmt2;
+ f = fmtcheck(f1, f2);
+ if (test_fmts[i].correct == 1)
+ cf = f1;
+ else
+ cf = f2;
+ ATF_CHECK_MSG(f == cf,
+ "Test %d: (%s) vs. (%s) failed "
+ "(should have returned %s)", i + 1, f1, f2,
+ (test_fmts[i].correct == 1) ? "1st" : "2nd");
+ }
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, fmtcheck_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/gen/fmtmsg_test.c b/lib/libc/tests/gen/fmtmsg_test.c
new file mode 100644
index 0000000..aa3ca19
--- /dev/null
+++ b/lib/libc/tests/gen/fmtmsg_test.c
@@ -0,0 +1,252 @@
+/*-
+ * Copyright (c) 2012 Jilles Tjoelker
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/wait.h>
+#include <err.h>
+#include <errno.h>
+#include <fmtmsg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <atf-c.h>
+
+static char *run_test(long classification, const char *label, int severity,
+ const char *text, const char *action, const char *tag);
+
+struct testcase {
+ long classification;
+ const char *label;
+ int severity;
+ const char *text;
+ const char *action;
+ const char *tag;
+ const char *msgverb;
+ const char *result;
+} testcases[] = {
+ {
+ MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR,
+ "illegal option -- z", "refer to manual", "BSD:ls:001",
+ NULL,
+ "BSD:ls: ERROR: illegal option -- z\n"
+ "TO FIX: refer to manual BSD:ls:001\n"
+ },
+ {
+ MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR,
+ "illegal option -- z", "refer to manual", "BSD:ls:001",
+ "text:severity:action:tag",
+ "illegal option -- z: ERROR\n"
+ "TO FIX: refer to manual BSD:ls:001\n"
+ },
+ {
+ MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR,
+ "illegal option -- z", "refer to manual", "BSD:ls:001",
+ "text",
+ "illegal option -- z\n"
+ },
+ {
+ MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR,
+ "illegal option -- z", "refer to manual", "BSD:ls:001",
+ "severity:text",
+ "ERROR: illegal option -- z\n"
+ },
+ {
+ MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR,
+ "illegal option -- z", "refer to manual", "BSD:ls:001",
+ "ignore me",
+ "BSD:ls: ERROR: illegal option -- z\n"
+ "TO FIX: refer to manual BSD:ls:001\n"
+ },
+ {
+ MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR,
+ "illegal option -- z", "refer to manual", "BSD:ls:001",
+ "tag:severity:text:nothing:action",
+ "BSD:ls: ERROR: illegal option -- z\n"
+ "TO FIX: refer to manual BSD:ls:001\n"
+ },
+ {
+ MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR,
+ "illegal option -- z", "refer to manual", "BSD:ls:001",
+ "",
+ "BSD:ls: ERROR: illegal option -- z\n"
+ "TO FIX: refer to manual BSD:ls:001\n"
+ },
+ {
+ MM_UTIL | MM_PRINT, MM_NULLLBL, MM_ERROR,
+ "illegal option -- z", "refer to manual", "BSD:ls:001",
+ NULL,
+ "ERROR: illegal option -- z\n"
+ "TO FIX: refer to manual BSD:ls:001\n"
+ },
+ {
+ MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR,
+ "illegal option -- z", MM_NULLACT, MM_NULLTAG,
+ NULL,
+ "BSD:ls: ERROR: illegal option -- z\n"
+ },
+ {
+ MM_UTIL | MM_NULLMC, "BSD:ls", MM_ERROR,
+ "illegal option -- z", "refer to manual", "BSD:ls:001",
+ NULL,
+ ""
+ },
+ {
+ MM_APPL | MM_PRINT, "ABCDEFGHIJ:abcdefghijklmn", MM_INFO,
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+ "refer to manual", "ABCDEFGHIJ:abcdefghijklmn:001",
+ NULL,
+ "ABCDEFGHIJ:abcdefghijklmn: INFO: "
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n"
+ "TO FIX: refer to manual ABCDEFGHIJ:abcdefghijklmn:001\n"
+ },
+ {
+ MM_OPSYS | MM_PRINT, "TEST:test", MM_HALT,
+ "failed", "nothing can help me", "NOTHING",
+ NULL,
+ "TEST:test: HALT: failed\n"
+ "TO FIX: nothing can help me NOTHING\n"
+ },
+ {
+ MM_OPSYS | MM_PRINT, "TEST:test", MM_WARNING,
+ "failed", "nothing can help me", "NOTHING",
+ NULL,
+ "TEST:test: WARNING: failed\n"
+ "TO FIX: nothing can help me NOTHING\n"
+ },
+ {
+ MM_OPSYS | MM_PRINT, "TEST:test", MM_NOSEV,
+ "failed", "nothing can help me", "NOTHING",
+ NULL,
+ "TEST:test: failed\n"
+ "TO FIX: nothing can help me NOTHING\n"
+ }
+};
+
+static char *
+run_test(long classification, const char *label, int severity,
+ const char *text, const char *action, const char *tag)
+{
+ int pip[2];
+ pid_t pid, wpid;
+ char *result, *p;
+ size_t resultsize;
+ ssize_t n;
+ int status;
+
+ if (pipe(pip) == -1)
+ err(2, "pipe");
+ pid = fork();
+ if (pid == -1)
+ err(2, "fork");
+ if (pid == 0) {
+ close(pip[0]);
+ if (pip[1] != STDERR_FILENO &&
+ dup2(pip[1], STDERR_FILENO) == -1)
+ _exit(2);
+ if (fmtmsg(classification, label, severity, text, action, tag)
+ != MM_OK)
+ _exit(1);
+ else
+ _exit(0);
+ }
+ close(pip[1]);
+ resultsize = 1024;
+ result = malloc(resultsize);
+ p = result;
+ while ((n = read(pip[0], p, result + resultsize - p - 1)) != 0) {
+ if (n == -1) {
+ if (errno == EINTR)
+ continue;
+ else
+ err(2, "read");
+ }
+ p += n;
+ if (result + resultsize == p - 1) {
+ resultsize *= 2;
+ result = realloc(result, resultsize);
+ if (result == NULL)
+ err(2, "realloc");
+ }
+ }
+ if (memchr(result, '\0', p - result) != NULL) {
+ free(result);
+ return (NULL);
+ }
+ *p = '\0';
+ close(pip[0]);
+ while ((wpid = waitpid(pid, &status, 0)) == -1 && errno == EINTR)
+ ;
+ if (wpid == -1)
+ err(2, "waitpid");
+ if (status != 0) {
+ free(result);
+ return (NULL);
+ }
+ return (result);
+}
+
+ATF_TC_WITHOUT_HEAD(fmtmsg_test);
+ATF_TC_BODY(fmtmsg_test, tc)
+{
+ char *result;
+ struct testcase *t;
+ int i;
+
+ for (i = 0; i < nitems(testcases); i++) {
+ t = &testcases[i];
+ if (t->msgverb != NULL)
+ setenv("MSGVERB", t->msgverb, 1);
+ else
+ unsetenv("MSGVERB");
+ result = run_test(t->classification, t->label, t->severity,
+ t->text, t->action, t->tag);
+ ATF_CHECK_MSG(result != NULL, "testcase %d failed", i + 1);
+ if (result != NULL)
+ ATF_CHECK_MSG(strcmp(result, t->result) == 0,
+ "results for testcase %d didn't match; "
+ "`%s` != `%s`", i + 1, result, t->result);
+ free(result);
+ }
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, fmtmsg_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/gen/fnmatch_test.c b/lib/libc/tests/gen/fnmatch_test.c
new file mode 100644
index 0000000..8d9ead2
--- /dev/null
+++ b/lib/libc/tests/gen/fnmatch_test.c
@@ -0,0 +1,188 @@
+/*-
+ * Copyright (c) 2010 Jilles Tjoelker
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <atf-c.h>
+
+#include "fnmatch_testcases.h"
+
+static const char *
+flags_to_string(int flags)
+{
+ static const int flagvalues[] = { FNM_NOESCAPE, FNM_PATHNAME,
+ FNM_PERIOD, FNM_LEADING_DIR, FNM_CASEFOLD, 0 };
+ static const char flagnames[] = "FNM_NOESCAPE\0FNM_PATHNAME\0FNM_PERIOD\0FNM_LEADING_DIR\0FNM_CASEFOLD\0";
+ static char result[sizeof(flagnames) + 3 * sizeof(int) + 2];
+ char *p;
+ size_t i, len;
+ const char *fp;
+
+ p = result;
+ fp = flagnames;
+ for (i = 0; flagvalues[i] != 0; i++) {
+ len = strlen(fp);
+ if (flags & flagvalues[i]) {
+ if (p != result)
+ *p++ = '|';
+ memcpy(p, fp, len);
+ p += len;
+ flags &= ~flagvalues[i];
+ }
+ fp += len + 1;
+ }
+ if (p == result)
+ memcpy(p, "0", 2);
+ else if (flags != 0)
+ sprintf(p, "%d", flags);
+ else
+ *p = '\0';
+ return result;
+}
+
+ATF_TC_WITHOUT_HEAD(fnmatch_test);
+ATF_TC_BODY(fnmatch_test, tc)
+{
+ size_t i;
+ int flags, result;
+ struct testcase *t;
+
+ for (i = 0; i < nitems(testcases); i++) {
+ t = &testcases[i];
+ flags = t->flags;
+ do {
+ result = fnmatch(t->pattern, t->string, flags);
+ if (result != t->result)
+ break;
+ if (strchr(t->pattern, '\\') == NULL &&
+ !(flags & FNM_NOESCAPE)) {
+ flags |= FNM_NOESCAPE;
+ result = fnmatch(t->pattern, t->string, flags);
+ if (result != t->result)
+ break;
+ flags = t->flags;
+ }
+ if (strchr(t->pattern, '\\') != NULL &&
+ strchr(t->string, '\\') == NULL &&
+ t->result == FNM_NOMATCH &&
+ !(flags & (FNM_NOESCAPE | FNM_LEADING_DIR))) {
+ flags |= FNM_NOESCAPE;
+ result = fnmatch(t->pattern, t->string, flags);
+ if (result != t->result)
+ break;
+ flags = t->flags;
+ }
+ if ((t->string[0] != '.' || t->pattern[0] == '.' ||
+ t->result == FNM_NOMATCH) &&
+ !(flags & (FNM_PATHNAME | FNM_PERIOD))) {
+ flags |= FNM_PERIOD;
+ result = fnmatch(t->pattern, t->string, flags);
+ if (result != t->result)
+ break;
+ flags = t->flags;
+ }
+ if ((strchr(t->string, '/') == NULL ||
+ t->result == FNM_NOMATCH) &&
+ !(flags & FNM_PATHNAME)) {
+ flags |= FNM_PATHNAME;
+ result = fnmatch(t->pattern, t->string, flags);
+ if (result != t->result)
+ break;
+ flags = t->flags;
+ }
+ if ((((t->string[0] != '.' || t->pattern[0] == '.') &&
+ strstr(t->string, "/.") == NULL) ||
+ t->result == FNM_NOMATCH) &&
+ flags & FNM_PATHNAME && !(flags & FNM_PERIOD)) {
+ flags |= FNM_PERIOD;
+ result = fnmatch(t->pattern, t->string, flags);
+ if (result != t->result)
+ break;
+ flags = t->flags;
+ }
+ if ((((t->string[0] != '.' || t->pattern[0] == '.') &&
+ strchr(t->string, '/') == NULL) ||
+ t->result == FNM_NOMATCH) &&
+ !(flags & (FNM_PATHNAME | FNM_PERIOD))) {
+ flags |= FNM_PATHNAME | FNM_PERIOD;
+ result = fnmatch(t->pattern, t->string, flags);
+ if (result != t->result)
+ break;
+ flags = t->flags;
+ }
+ if ((strchr(t->string, '/') == NULL || t->result == 0)
+ && !(flags & FNM_LEADING_DIR)) {
+ flags |= FNM_LEADING_DIR;
+ result = fnmatch(t->pattern, t->string, flags);
+ if (result != t->result)
+ break;
+ flags = t->flags;
+ }
+ if (t->result == 0 && !(flags & FNM_CASEFOLD)) {
+ flags |= FNM_CASEFOLD;
+ result = fnmatch(t->pattern, t->string, flags);
+ if (result != t->result)
+ break;
+ flags = t->flags;
+ }
+ if (strchr(t->pattern, '\\') == NULL &&
+ t->result == 0 &&
+ !(flags & (FNM_NOESCAPE | FNM_CASEFOLD))) {
+ flags |= FNM_NOESCAPE | FNM_CASEFOLD;
+ result = fnmatch(t->pattern, t->string, flags);
+ if (result != t->result)
+ break;
+ flags = t->flags;
+ }
+ } while (0);
+
+ ATF_CHECK(result == t->result);
+ if (result == t->result)
+ printf("fnmatch(\"%s\", \"%s\", %s) == %d\n",
+ t->pattern, t->string, flags_to_string(flags), result);
+ else
+ printf("fnmatch(\"%s\", \"%s\", %s) != %d (was %d)\n",
+ t->pattern, t->string, flags_to_string(flags),
+ t->result, result);
+ }
+
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, fnmatch_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/gen/fnmatch_testcases.h b/lib/libc/tests/gen/fnmatch_testcases.h
new file mode 100644
index 0000000..537011f
--- /dev/null
+++ b/lib/libc/tests/gen/fnmatch_testcases.h
@@ -0,0 +1,176 @@
+/*-
+ * Copyright (c) 2010 Jilles Tjoelker
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <fnmatch.h>
+
+struct testcase {
+ const char *pattern;
+ const char *string;
+ int flags;
+ int result;
+} testcases[] = {
+ { "", "", 0, 0 },
+ { "a", "a", 0, 0 },
+ { "a", "b", 0, FNM_NOMATCH },
+ { "a", "A", 0, FNM_NOMATCH },
+ { "*", "a", 0, 0 },
+ { "*", "aa", 0, 0 },
+ { "*a", "a", 0, 0 },
+ { "*a", "b", 0, FNM_NOMATCH },
+ { "*a*", "b", 0, FNM_NOMATCH },
+ { "*a*b*", "ab", 0, 0 },
+ { "*a*b*", "qaqbq", 0, 0 },
+ { "*a*bb*", "qaqbqbbq", 0, 0 },
+ { "*a*bc*", "qaqbqbcq", 0, 0 },
+ { "*a*bb*", "qaqbqbb", 0, 0 },
+ { "*a*bc*", "qaqbqbc", 0, 0 },
+ { "*a*bb", "qaqbqbb", 0, 0 },
+ { "*a*bc", "qaqbqbc", 0, 0 },
+ { "*a*bb", "qaqbqbbq", 0, FNM_NOMATCH },
+ { "*a*bc", "qaqbqbcq", 0, FNM_NOMATCH },
+ { "*a*a*a*a*a*a*a*a*a*a*", "aaaaaaaaa", 0, FNM_NOMATCH },
+ { "*a*a*a*a*a*a*a*a*a*a*", "aaaaaaaaaa", 0, 0 },
+ { "*a*a*a*a*a*a*a*a*a*a*", "aaaaaaaaaaa", 0, 0 },
+ { ".*.*.*.*.*.*.*.*.*.*", ".........", 0, FNM_NOMATCH },
+ { ".*.*.*.*.*.*.*.*.*.*", "..........", 0, 0 },
+ { ".*.*.*.*.*.*.*.*.*.*", "...........", 0, 0 },
+ { "*?*?*?*?*?*?*?*?*?*?*", "123456789", 0, FNM_NOMATCH },
+ { "??????????*", "123456789", 0, FNM_NOMATCH },
+ { "*??????????", "123456789", 0, FNM_NOMATCH },
+ { "*?*?*?*?*?*?*?*?*?*?*", "1234567890", 0, 0 },
+ { "??????????*", "1234567890", 0, 0 },
+ { "*??????????", "1234567890", 0, 0 },
+ { "*?*?*?*?*?*?*?*?*?*?*", "12345678901", 0, 0 },
+ { "??????????*", "12345678901", 0, 0 },
+ { "*??????????", "12345678901", 0, 0 },
+ { "[x]", "x", 0, 0 },
+ { "[*]", "*", 0, 0 },
+ { "[?]", "?", 0, 0 },
+ { "[", "[", 0, 0 },
+ { "[[]", "[", 0, 0 },
+ { "[[]", "x", 0, FNM_NOMATCH },
+ { "[*]", "", 0, FNM_NOMATCH },
+ { "[*]", "x", 0, FNM_NOMATCH },
+ { "[?]", "x", 0, FNM_NOMATCH },
+ { "*[*]*", "foo*foo", 0, 0 },
+ { "*[*]*", "foo", 0, FNM_NOMATCH },
+ { "[0-9]", "0", 0, 0 },
+ { "[0-9]", "5", 0, 0 },
+ { "[0-9]", "9", 0, 0 },
+ { "[0-9]", "/", 0, FNM_NOMATCH },
+ { "[0-9]", ":", 0, FNM_NOMATCH },
+ { "[0-9]", "*", 0, FNM_NOMATCH },
+ { "[!0-9]", "0", 0, FNM_NOMATCH },
+ { "[!0-9]", "5", 0, FNM_NOMATCH },
+ { "[!0-9]", "9", 0, FNM_NOMATCH },
+ { "[!0-9]", "/", 0, 0 },
+ { "[!0-9]", ":", 0, 0 },
+ { "[!0-9]", "*", 0, 0 },
+ { "*[0-9]", "a0", 0, 0 },
+ { "*[0-9]", "a5", 0, 0 },
+ { "*[0-9]", "a9", 0, 0 },
+ { "*[0-9]", "a/", 0, FNM_NOMATCH },
+ { "*[0-9]", "a:", 0, FNM_NOMATCH },
+ { "*[0-9]", "a*", 0, FNM_NOMATCH },
+ { "*[!0-9]", "a0", 0, FNM_NOMATCH },
+ { "*[!0-9]", "a5", 0, FNM_NOMATCH },
+ { "*[!0-9]", "a9", 0, FNM_NOMATCH },
+ { "*[!0-9]", "a/", 0, 0 },
+ { "*[!0-9]", "a:", 0, 0 },
+ { "*[!0-9]", "a*", 0, 0 },
+ { "*[0-9]", "a00", 0, 0 },
+ { "*[0-9]", "a55", 0, 0 },
+ { "*[0-9]", "a99", 0, 0 },
+ { "*[0-9]", "a0a0", 0, 0 },
+ { "*[0-9]", "a5a5", 0, 0 },
+ { "*[0-9]", "a9a9", 0, 0 },
+ { "\\*", "*", 0, 0 },
+ { "\\?", "?", 0, 0 },
+ { "\\[x]", "[x]", 0, 0 },
+ { "\\[", "[", 0, 0 },
+ { "\\\\", "\\", 0, 0 },
+ { "*\\**", "foo*foo", 0, 0 },
+ { "*\\**", "foo", 0, FNM_NOMATCH },
+ { "*\\\\*", "foo\\foo", 0, 0 },
+ { "*\\\\*", "foo", 0, FNM_NOMATCH },
+ { "\\(", "(", 0, 0 },
+ { "\\a", "a", 0, 0 },
+ { "\\*", "a", 0, FNM_NOMATCH },
+ { "\\?", "a", 0, FNM_NOMATCH },
+ { "\\*", "\\*", 0, FNM_NOMATCH },
+ { "\\?", "\\?", 0, FNM_NOMATCH },
+ { "\\[x]", "\\[x]", 0, FNM_NOMATCH },
+ { "\\[x]", "\\x", 0, FNM_NOMATCH },
+ { "\\[", "\\[", 0, FNM_NOMATCH },
+ { "\\(", "\\(", 0, FNM_NOMATCH },
+ { "\\a", "\\a", 0, FNM_NOMATCH },
+ { "\\", "\\", 0, FNM_NOMATCH },
+ { "\\", "", 0, 0 },
+ { "\\*", "\\*", FNM_NOESCAPE, 0 },
+ { "\\?", "\\?", FNM_NOESCAPE, 0 },
+ { "\\", "\\", FNM_NOESCAPE, 0 },
+ { "\\\\", "\\", FNM_NOESCAPE, FNM_NOMATCH },
+ { "\\\\", "\\\\", FNM_NOESCAPE, 0 },
+ { "*\\*", "foo\\foo", FNM_NOESCAPE, 0 },
+ { "*\\*", "foo", FNM_NOESCAPE, FNM_NOMATCH },
+ { "*", ".", FNM_PERIOD, FNM_NOMATCH },
+ { "?", ".", FNM_PERIOD, FNM_NOMATCH },
+ { ".*", ".", 0, 0 },
+ { ".*", "..", 0, 0 },
+ { ".*", ".a", 0, 0 },
+ { "[0-9]", ".", FNM_PERIOD, FNM_NOMATCH },
+ { "a*", "a.", 0, 0 },
+ { "a/a", "a/a", FNM_PATHNAME, 0 },
+ { "a/*", "a/a", FNM_PATHNAME, 0 },
+ { "*/a", "a/a", FNM_PATHNAME, 0 },
+ { "*/*", "a/a", FNM_PATHNAME, 0 },
+ { "a*b/*", "abbb/x", FNM_PATHNAME, 0 },
+ { "a*b/*", "abbb/.x", FNM_PATHNAME, 0 },
+ { "*", "a/a", FNM_PATHNAME, FNM_NOMATCH },
+ { "*/*", "a/a/a", FNM_PATHNAME, FNM_NOMATCH },
+ { "b/*", "b/.x", FNM_PATHNAME | FNM_PERIOD, FNM_NOMATCH },
+ { "b*/*", "a/.x", FNM_PATHNAME | FNM_PERIOD, FNM_NOMATCH },
+ { "b/.*", "b/.x", FNM_PATHNAME | FNM_PERIOD, 0 },
+ { "b*/.*", "b/.x", FNM_PATHNAME | FNM_PERIOD, 0 },
+ { "a", "A", FNM_CASEFOLD, 0 },
+ { "A", "a", FNM_CASEFOLD, 0 },
+ { "[a]", "A", FNM_CASEFOLD, 0 },
+ { "[A]", "a", FNM_CASEFOLD, 0 },
+ { "a", "b", FNM_CASEFOLD, FNM_NOMATCH },
+ { "a", "a/b", FNM_PATHNAME, FNM_NOMATCH },
+ { "*", "a/b", FNM_PATHNAME, FNM_NOMATCH },
+ { "*b", "a/b", FNM_PATHNAME, FNM_NOMATCH },
+ { "a", "a/b", FNM_PATHNAME | FNM_LEADING_DIR, 0 },
+ { "*", "a/b", FNM_PATHNAME | FNM_LEADING_DIR, 0 },
+ { "*", ".a/b", FNM_PATHNAME | FNM_LEADING_DIR, 0 },
+ { "*a", ".a/b", FNM_PATHNAME | FNM_LEADING_DIR, 0 },
+ { "*", ".a/b", FNM_PATHNAME | FNM_PERIOD | FNM_LEADING_DIR, FNM_NOMATCH },
+ { "*a", ".a/b", FNM_PATHNAME | FNM_PERIOD | FNM_LEADING_DIR, FNM_NOMATCH },
+ { "a*b/*", "abbb/.x", FNM_PATHNAME | FNM_PERIOD, FNM_NOMATCH },
+};
diff --git a/lib/libc/tests/gen/ftw_test.c b/lib/libc/tests/gen/ftw_test.c
new file mode 100644
index 0000000..b120f01
--- /dev/null
+++ b/lib/libc/tests/gen/ftw_test.c
@@ -0,0 +1,127 @@
+/*-
+ * Copyright (c) 2012 Jilles Tjoelker
+ * 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.
+ */
+
+/*
+ * Limited test program for nftw() as specified by IEEE Std. 1003.1-2008.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/wait.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <ftw.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <spawn.h>
+#include <unistd.h>
+
+#include <atf-c.h>
+
+extern char **environ;
+
+static char template[] = "testftw.XXXXXXXXXX";
+static char dir[PATH_MAX];
+static int ftwflags;
+
+static int
+cb(const char *path, const struct stat *st, int type, struct FTW *f)
+{
+
+ switch (type) {
+ case FTW_D:
+ if ((ftwflags & FTW_DEPTH) == 0)
+ return (0);
+ break;
+ case FTW_DP:
+ if ((ftwflags & FTW_DEPTH) != 0)
+ return (0);
+ break;
+ case FTW_SL:
+ if ((ftwflags & FTW_PHYS) != 0)
+ return (0);
+ break;
+ }
+ ATF_CHECK_MSG(false,
+ "unexpected path=%s type=%d f.level=%d\n",
+ path, type, f->level);
+ return (0);
+}
+
+ATF_TC_WITHOUT_HEAD(ftw_test);
+ATF_TC_BODY(ftw_test, tc)
+{
+ int fd;
+
+ ATF_REQUIRE_MSG(mkdtemp(template) != NULL, "mkdtemp failed");
+
+ /* XXX: the path needs to be absolute for the 0/FTW_DEPTH testcases */
+ ATF_REQUIRE_MSG(realpath(template, dir) != NULL,
+ "realpath failed; errno=%d", errno);
+
+ fd = open(dir, O_DIRECTORY|O_RDONLY);
+ ATF_REQUIRE_MSG(fd != -1, "open failed; errno=%d", errno);
+
+ ATF_REQUIRE_MSG(mkdirat(fd, "d1", 0777) == 0,
+ "mkdirat failed; errno=%d", errno);
+
+ ATF_REQUIRE_MSG(symlinkat(dir, fd, "d1/looper") == 0,
+ "symlinkat failed; errno=%d", errno);
+
+ printf("ftwflags=FTW_PHYS\n");
+ ftwflags = FTW_PHYS;
+ ATF_REQUIRE_MSG(nftw(dir, cb, 10, ftwflags) != -1,
+ "nftw FTW_PHYS failed; errno=%d", errno);
+
+ printf("ftwflags=FTW_PHYS|FTW_DEPTH\n");
+ ftwflags = FTW_PHYS|FTW_DEPTH;
+ ATF_REQUIRE_MSG(nftw(dir, cb, 10, ftwflags) != -1,
+ "nftw FTW_PHYS|FTW_DEPTH failed; errno=%d", errno);
+
+ printf("ftwflags=0\n");
+ ftwflags = 0;
+ ATF_REQUIRE_MSG(nftw(dir, cb, 10, ftwflags) != -1,
+ "nftw 0 failed; errno=%d", errno);
+
+ printf("ftwflags=FTW_DEPTH\n");
+ ftwflags = FTW_DEPTH;
+ ATF_REQUIRE_MSG(nftw(dir, cb, 10, ftwflags) != -1,
+ "nftw FTW_DEPTH failed; errno=%d", errno);
+
+ close(fd);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, ftw_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/gen/popen_test.c b/lib/libc/tests/gen/popen_test.c
new file mode 100644
index 0000000..5c615b7
--- /dev/null
+++ b/lib/libc/tests/gen/popen_test.c
@@ -0,0 +1,251 @@
+/*-
+ * Copyright (c) 2013 Jilles Tjoelker
+ * 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.
+ */
+
+/*
+ * Limited test program for popen() as specified by IEEE Std. 1003.1-2008,
+ * with BSD extensions.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <atf-c.h>
+
+static volatile sig_atomic_t got_sigpipe;
+
+static void
+sigpipe_handler(int sig __unused)
+{
+ got_sigpipe = 1;
+}
+
+static void
+check_cloexec(FILE *fp, const char *mode)
+{
+ int exp_flags, flags;
+
+ flags = fcntl(fileno(fp), F_GETFD);
+ ATF_CHECK_MSG(flags != -1, "fcntl(F_GETFD) failed; errno=%d", errno);
+ if (flags == -1)
+ return;
+ if (strchr(mode, 'e') != NULL)
+ exp_flags = FD_CLOEXEC;
+ else
+ exp_flags = 0;
+ ATF_CHECK_MSG((flags & FD_CLOEXEC) == exp_flags,
+ "bad cloexec flag; %d != %d", flags, exp_flags);
+}
+
+ATF_TC_WITHOUT_HEAD(popen_all_modes_test);
+ATF_TC_BODY(popen_all_modes_test, tc)
+{
+ FILE *fp;
+ int i, status;
+ const char *mode;
+ const char *allmodes[] = { "r", "w", "r+", "re", "we", "r+e", "re+" };
+
+ for (i = 0; i < nitems(allmodes); i++) {
+ mode = allmodes[i];
+ fp = popen("exit 7", mode);
+ ATF_CHECK_MSG(fp != NULL, "popen(, \"%s\") failed", mode);
+ if (fp == NULL)
+ continue;
+ check_cloexec(fp, mode);
+ status = pclose(fp);
+ ATF_CHECK_MSG(WIFEXITED(status) && WEXITSTATUS(status) == 7,
+ "bad exit status (no I/O)");
+ }
+}
+
+ATF_TC_WITHOUT_HEAD(popen_rmodes_test);
+ATF_TC_BODY(popen_rmodes_test, tc)
+{
+ FILE *fp;
+ const char *rmodes[] = { "r", "r+", "re", "r+e", "re+" };
+ const char *mode;
+ char buf[80];
+ int i, status;
+
+ for (i = 0; i < nitems(rmodes); i++) {
+ mode = rmodes[i];
+ fp = popen("exit 9", mode);
+ ATF_CHECK_MSG(fp != NULL, "popen(, \"%s\") failed", mode);
+ if (fp == NULL)
+ continue;
+ check_cloexec(fp, mode);
+ bool input_error_1 = !(fgetc(fp) != EOF || !feof(fp) || !ferror(fp));
+ ATF_CHECK_MSG(!input_error_1, "input error 1");
+ if (input_error_1)
+ continue;
+ status = pclose(fp);
+ ATF_CHECK_MSG(WIFEXITED(status) && WEXITSTATUS(status) == 9,
+ "bad exit status (input)");
+ }
+
+ for (i = 0; i < nitems(rmodes); i++) {
+ char *sres;
+ mode = rmodes[i];
+ fp = popen("echo hi there", mode);
+ ATF_CHECK_MSG(fp != NULL, "popen(, \"%s\") failed", mode);
+ if (fp == NULL)
+ continue;
+ check_cloexec(fp, mode);
+ ATF_CHECK_MSG((sres = fgets(buf, sizeof(buf), fp)) != NULL,
+ "Input error 2");
+ if (sres != NULL)
+ ATF_CHECK_MSG(strcmp(buf, "hi there\n") == 0,
+ "Bad input 1");
+ status = pclose(fp);
+ ATF_CHECK_MSG(WIFEXITED(status) && WEXITSTATUS(status) == 0,
+ "Bad exit status (input)");
+ }
+}
+
+ATF_TC_WITHOUT_HEAD(popen_wmodes_test);
+ATF_TC_BODY(popen_wmodes_test, tc)
+{
+ FILE *fp, *fp2;
+ const char *wmodes[] = { "w", "r+", "we", "r+e", "re+" };
+ const char *mode;
+ struct sigaction act, oact;
+ int i, j, status;
+
+ for (i = 0; i < nitems(wmodes); i++) {
+ mode = wmodes[i];
+ fp = popen("read x && [ \"$x\" = abcd ]", mode);
+ ATF_CHECK_MSG(fp != NULL, "popen(, \"%s\") failed", mode);
+ if (fp == NULL)
+ continue;
+ check_cloexec(fp, mode);
+ ATF_CHECK_MSG(fputs("abcd\n", fp) != EOF,
+ "Output error 1");
+ status = pclose(fp);
+ ATF_CHECK_MSG(WIFEXITED(status) && WEXITSTATUS(status) == 0,
+ "Bad exit status (output)");
+ }
+
+ act.sa_handler = sigpipe_handler;
+ act.sa_flags = SA_RESTART;
+ sigemptyset(&act.sa_mask);
+ ATF_CHECK_MSG(sigaction(SIGPIPE, &act, &oact) != -1,
+ "sigaction() failed");
+ for (i = 0; i < nitems(wmodes); i++) {
+ mode = wmodes[i];
+ fp = popen("exit 88", mode);
+ ATF_CHECK_MSG(fp != NULL, "popen(, \"%s\") failed", mode);
+ if (fp == NULL)
+ continue;
+ check_cloexec(fp, mode);
+ got_sigpipe = 0;
+ while (fputs("abcd\n", fp) != EOF)
+ ;
+ ATF_CHECK_MSG(ferror(fp) && errno == EPIPE, "Expected EPIPE");
+ ATF_CHECK_MSG(got_sigpipe, "Expected SIGPIPE");
+ status = pclose(fp);
+ ATF_CHECK_MSG(WIFEXITED(status) && WEXITSTATUS(status) == 88,
+ "Bad exit status (EPIPE)");
+ }
+ ATF_CHECK_MSG(sigaction(SIGPIPE, &oact, NULL) != -1,
+ "sigaction() failed");
+
+ for (i = 0; i < nitems(wmodes); i++) {
+ for (j = 0; j < nitems(wmodes); j++) {
+ mode = wmodes[i];
+ fp = popen("read x", mode);
+ ATF_CHECK_MSG(fp != NULL,
+ "popen(, \"%s\") failed", mode);
+ if (fp == NULL)
+ continue;
+ mode = wmodes[j];
+ fp2 = popen("read x", mode);
+ ATF_CHECK_MSG(fp2 != NULL,
+ "popen(, \"%s\") failed", mode);
+ if (fp2 == NULL) {
+ pclose(fp);
+ continue;
+ }
+ /* If fp2 inherits fp's pipe, we will deadlock here. */
+ status = pclose(fp);
+ ATF_CHECK_MSG(WIFEXITED(status) && WEXITSTATUS(status) == 1,
+ "bad exit status (2 pipes)");
+ status = pclose(fp2);
+ ATF_CHECK_MSG(WIFEXITED(status) && WEXITSTATUS(status) == 1,
+ "bad exit status (2 pipes)");
+ }
+ }
+}
+
+ATF_TC_WITHOUT_HEAD(popen_rwmodes_test);
+ATF_TC_BODY(popen_rwmodes_test, tc)
+{
+ const char *rwmodes[] = { "r+", "r+e", "re+" };
+ FILE *fp;
+ const char *mode;
+ char *sres;
+ char buf[80];
+ int i, ires, status;
+
+ for (i = 0; i < nitems(rwmodes); i++) {
+ mode = rwmodes[i];
+ fp = popen("read x && printf '%s\\n' \"Q${x#a}\"", mode);
+ ATF_CHECK_MSG(fp != NULL, "popen(, \"%s\") failed", mode);
+ if (fp == NULL)
+ continue;
+ check_cloexec(fp, mode);
+ ATF_CHECK_MSG((ires = fputs("abcd\n", fp)) != EOF,
+ "Output error 2");
+ if (ires != EOF) {
+ sres = fgets(buf, sizeof(buf), fp);
+ ATF_CHECK_MSG(sres != NULL, "Input error 3");
+ if (sres != NULL)
+ ATF_CHECK_MSG(strcmp(buf, "Qbcd\n") == 0,
+ "Bad input 2");
+ }
+ status = pclose(fp);
+ ATF_CHECK_MSG(WIFEXITED(status) && WEXITSTATUS(status) == 0,
+ "bad exit status (I/O)");
+ }
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, popen_all_modes_test);
+ ATF_TP_ADD_TC(tp, popen_rmodes_test);
+ ATF_TP_ADD_TC(tp, popen_wmodes_test);
+ ATF_TP_ADD_TC(tp, popen_rwmodes_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/gen/posix_spawn_test.c b/lib/libc/tests/gen/posix_spawn_test.c
new file mode 100644
index 0000000..e04d103
--- /dev/null
+++ b/lib/libc/tests/gen/posix_spawn_test.c
@@ -0,0 +1,103 @@
+/*-
+ * Copyright (c) 2011 Jilles Tjoelker
+ * 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.
+ */
+
+/*
+ * Test program for posix_spawn() and posix_spawnp() as specified by
+ * IEEE Std. 1003.1-2008.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/wait.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <spawn.h>
+
+#include <atf-c.h>
+
+char *myenv[2] = { "answer=42", NULL };
+
+ATF_TC_WITHOUT_HEAD(posix_spawn_simple_test);
+ATF_TC_BODY(posix_spawn_simple_test, tc)
+{
+ char *myargs[4];
+ int error, status;
+ pid_t pid, waitres;
+
+ /* Make sure we have no child processes. */
+ while (waitpid(-1, NULL, 0) != -1)
+ ;
+ ATF_REQUIRE_MSG(errno == ECHILD, "errno was not ECHILD: %d", errno);
+
+ /* Simple test. */
+ myargs[0] = "sh";
+ myargs[1] = "-c";
+ myargs[2] = "exit $answer";
+ myargs[3] = NULL;
+ error = posix_spawnp(&pid, myargs[0], NULL, NULL, myargs, myenv);
+ ATF_REQUIRE(error == 0);
+ waitres = waitpid(pid, &status, 0);
+ ATF_REQUIRE(waitres == pid);
+ ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 42);
+}
+
+ATF_TC_WITHOUT_HEAD(posix_spawn_no_such_command_negative_test);
+ATF_TC_BODY(posix_spawn_no_such_command_negative_test, tc)
+{
+ char *myargs[4];
+ int error, status;
+ pid_t pid, waitres;
+
+ /*
+ * If the executable does not exist, the function shall either fail
+ * and not create a child process or succeed and create a child
+ * process that exits with status 127.
+ */
+ myargs[0] = "/var/empty/nonexistent";
+ myargs[1] = NULL;
+ error = posix_spawn(&pid, myargs[0], NULL, NULL, myargs, myenv);
+ if (error == 0) {
+ waitres = waitpid(pid, &status, 0);
+ ATF_REQUIRE(waitres == pid);
+ ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 127);
+ } else {
+ ATF_REQUIRE(error == ENOENT);
+ waitres = waitpid(-1, NULL, 0);
+ ATF_REQUIRE(waitres == -1 && errno == ECHILD);
+ }
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, posix_spawn_simple_test);
+ ATF_TP_ADD_TC(tp, posix_spawn_no_such_command_negative_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/gen/test-fnmatch.c b/lib/libc/tests/gen/test-fnmatch.c
new file mode 100644
index 0000000..7771ab3
--- /dev/null
+++ b/lib/libc/tests/gen/test-fnmatch.c
@@ -0,0 +1,102 @@
+/*-
+ * Copyright (c) 2010 Jilles Tjoelker
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "fnmatch_testcases.h"
+
+static int
+write_sh_tests(const char *progname, int num)
+{
+ size_t i;
+ struct testcase *t;
+
+ printf("# Generated by %s -s %d, do not edit.\n", progname, num);
+ printf("# $" "FreeBSD$\n");
+ printf("failures=\n");
+ printf("failed() { printf '%%s\\n' \"Failed: $1 '$2' '$3'\"; failures=x$failures; }\n");
+ if (num == 1) {
+ printf("testmatch() { eval \"case \\$2 in ''$1) ;; *) failed testmatch \\\"\\$@\\\";; esac\"; }\n");
+ printf("testnomatch() { eval \"case \\$2 in ''$1) failed testnomatch \\\"\\$@\\\";; esac\"; }\n");
+ } else if (num == 2) {
+ printf("# We do not treat a backslash specially in this case,\n");
+ printf("# but this is not the case in all shells.\n");
+ printf("netestmatch() { case $2 in $1) ;; *) failed netestmatch \"$@\";; esac; }\n");
+ printf("netestnomatch() { case $2 in $1) failed netestnomatch \"$@\";; esac; }\n");
+ }
+
+ for (i = 0; i < nitems(testcases); i++) {
+ t = &testcases[i];
+ if (strchr(t->pattern, '\'') != NULL ||
+ strchr(t->string, '\'') != NULL)
+ continue;
+ if (t->flags == 0 && strcmp(t->pattern, "\\") == 0)
+ continue;
+ if (num == 1 && t->flags == 0)
+ printf("test%smatch '%s' '%s'\n",
+ t->result == FNM_NOMATCH ? "no" : "",
+ t->pattern, t->string);
+ if (num == 2 && (t->flags == FNM_NOESCAPE ||
+ (t->flags == 0 && strchr(t->pattern, '\\') == NULL)))
+ printf("netest%smatch '%s' '%s'\n",
+ t->result == FNM_NOMATCH ? "no" : "",
+ t->pattern, t->string);
+ }
+ printf("[ -z \"$failures\" ]\n");
+ return 0;
+}
+
+static void
+usage(char *progname)
+{
+ fprintf(stderr, "usage: %s [-s num]\n", progname);
+ fprintf(stderr, "-s option writes tests for sh(1), num is 1 or 2\n");
+}
+
+int
+main(int argc, char *argv[])
+{
+ int opt;
+
+ while ((opt = getopt(argc, argv, "s:")) != -1) {
+ switch (opt) {
+ case 's':
+ return (write_sh_tests(argv[0], atoi(optarg)));
+ default:
+ usage(argv[0]);
+ exit(1);
+ }
+ }
+ usage(argv[0]);
+ exit(1);
+}
diff --git a/lib/libc/tests/gen/wordexp_test.c b/lib/libc/tests/gen/wordexp_test.c
new file mode 100644
index 0000000..3ccc677
--- /dev/null
+++ b/lib/libc/tests/gen/wordexp_test.c
@@ -0,0 +1,360 @@
+/*-
+ * Copyright (c) 2003 Tim J. Robbins
+ * 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.
+ */
+
+/*
+ * Test program for wordexp() and wordfree() as specified by
+ * IEEE Std. 1003.1-2001.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/wait.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wordexp.h>
+
+#include <atf-c.h>
+
+static void
+chld_handler(int x)
+{
+ int status, serrno;
+
+ (void)x;
+ serrno = errno;
+ while (waitpid(-1, &status, WNOHANG) > 0)
+ ;
+ errno = serrno;
+}
+
+ATF_TC_WITHOUT_HEAD(simple_test);
+ATF_TC_BODY(simple_test, tc)
+{
+ wordexp_t we;
+ int r;
+
+ /* Test that the macros are there. */
+ (void)(WRDE_APPEND + WRDE_DOOFFS + WRDE_NOCMD + WRDE_REUSE +
+ WRDE_SHOWERR + WRDE_UNDEF);
+ (void)(WRDE_BADCHAR + WRDE_BADVAL + WRDE_CMDSUB + WRDE_NOSPACE +
+ WRDE_SYNTAX);
+
+ /* Simple test. */
+ r = wordexp("hello world", &we, 0);
+ ATF_REQUIRE(r == 0);
+ ATF_REQUIRE(we.we_wordc == 2);
+ ATF_REQUIRE(strcmp(we.we_wordv[0], "hello") == 0);
+ ATF_REQUIRE(strcmp(we.we_wordv[1], "world") == 0);
+ ATF_REQUIRE(we.we_wordv[2] == NULL);
+ wordfree(&we);
+}
+
+ATF_TC_WITHOUT_HEAD(long_output_test);
+ATF_TC_BODY(long_output_test, tc)
+{
+ char longdata[6 * 10000 + 1];
+ wordexp_t we;
+ int i, r;
+
+ /* Long output. */
+ for (i = 0; i < 10000; i++)
+ snprintf(longdata + 6 * i, 7, "%05d ", i);
+ r = wordexp(longdata, &we, 0);
+ ATF_REQUIRE(r == 0);
+ ATF_REQUIRE(we.we_wordc == 10000);
+ ATF_REQUIRE(we.we_wordv[10000] == NULL);
+ wordfree(&we);
+}
+
+ATF_TC_WITHOUT_HEAD(WRDE_DOOFFS_test);
+ATF_TC_BODY(WRDE_DOOFFS_test, tc)
+{
+ wordexp_t we;
+ int r;
+
+ we.we_offs = 3;
+ r = wordexp("hello world", &we, WRDE_DOOFFS);
+ ATF_REQUIRE(r == 0);
+ ATF_REQUIRE(we.we_wordc == 2);
+ ATF_REQUIRE(we.we_wordv[0] == NULL);
+ ATF_REQUIRE(we.we_wordv[1] == NULL);
+ ATF_REQUIRE(we.we_wordv[2] == NULL);
+ ATF_REQUIRE(strcmp(we.we_wordv[3], "hello") == 0);
+ ATF_REQUIRE(strcmp(we.we_wordv[4], "world") == 0);
+ ATF_REQUIRE(we.we_wordv[5] == NULL);
+ wordfree(&we);
+}
+
+ATF_TC_WITHOUT_HEAD(WRDE_REUSE_test);
+ATF_TC_BODY(WRDE_REUSE_test, tc)
+{
+ wordexp_t we;
+ int r;
+
+ r = wordexp("hello world", &we, 0);
+ r = wordexp("hello world", &we, WRDE_REUSE);
+ ATF_REQUIRE(r == 0);
+ ATF_REQUIRE(we.we_wordc == 2);
+ ATF_REQUIRE(strcmp(we.we_wordv[0], "hello") == 0);
+ ATF_REQUIRE(strcmp(we.we_wordv[1], "world") == 0);
+ ATF_REQUIRE(we.we_wordv[2] == NULL);
+ wordfree(&we);
+}
+
+ATF_TC_WITHOUT_HEAD(WRDE_APPEND_test);
+ATF_TC_BODY(WRDE_APPEND_test, tc)
+{
+ wordexp_t we;
+ int r;
+
+ r = wordexp("this is", &we, 0);
+ ATF_REQUIRE(r == 0);
+ r = wordexp("a test", &we, WRDE_APPEND);
+ ATF_REQUIRE(r == 0);
+ ATF_REQUIRE(we.we_wordc == 4);
+ ATF_REQUIRE(strcmp(we.we_wordv[0], "this") == 0);
+ ATF_REQUIRE(strcmp(we.we_wordv[1], "is") == 0);
+ ATF_REQUIRE(strcmp(we.we_wordv[2], "a") == 0);
+ ATF_REQUIRE(strcmp(we.we_wordv[3], "test") == 0);
+ ATF_REQUIRE(we.we_wordv[4] == NULL);
+ wordfree(&we);
+}
+
+ATF_TC_WITHOUT_HEAD(WRDE_DOOFFS__WRDE_APPEND_test);
+ATF_TC_BODY(WRDE_DOOFFS__WRDE_APPEND_test, tc)
+{
+ wordexp_t we;
+ int r;
+
+ we.we_offs = 2;
+ r = wordexp("this is", &we, WRDE_DOOFFS);
+ ATF_REQUIRE(r == 0);
+ r = wordexp("a test", &we, WRDE_APPEND|WRDE_DOOFFS);
+ ATF_REQUIRE(r == 0);
+ r = wordexp("of wordexp", &we, WRDE_APPEND|WRDE_DOOFFS);
+ ATF_REQUIRE(r == 0);
+ ATF_REQUIRE(we.we_wordc == 6);
+ ATF_REQUIRE(we.we_wordv[0] == NULL);
+ ATF_REQUIRE(we.we_wordv[1] == NULL);
+ ATF_REQUIRE(strcmp(we.we_wordv[2], "this") == 0);
+ ATF_REQUIRE(strcmp(we.we_wordv[3], "is") == 0);
+ ATF_REQUIRE(strcmp(we.we_wordv[4], "a") == 0);
+ ATF_REQUIRE(strcmp(we.we_wordv[5], "test") == 0);
+ ATF_REQUIRE(strcmp(we.we_wordv[6], "of") == 0);
+ ATF_REQUIRE(strcmp(we.we_wordv[7], "wordexp") == 0);
+ ATF_REQUIRE(we.we_wordv[8] == NULL);
+ wordfree(&we);
+}
+
+ATF_TC_WITHOUT_HEAD(WRDE_UNDEF_test);
+ATF_TC_BODY(WRDE_UNDEF_test, tc)
+{
+ wordexp_t we;
+ int r;
+
+ r = wordexp("${dont_set_me}", &we, WRDE_UNDEF);
+ ATF_REQUIRE(r == WRDE_BADVAL);
+}
+
+ATF_TC_WITHOUT_HEAD(WRDE_NOCMD_test);
+ATF_TC_BODY(WRDE_NOCMD_test, tc)
+{
+ wordexp_t we;
+ int r;
+
+ r = wordexp("`date`", &we, WRDE_NOCMD);
+ ATF_REQUIRE(r == WRDE_CMDSUB);
+ r = wordexp("\"`date`\"", &we, WRDE_NOCMD);
+ ATF_REQUIRE(r == WRDE_CMDSUB);
+ r = wordexp("$(date)", &we, WRDE_NOCMD);
+ ATF_REQUIRE(r == WRDE_CMDSUB);
+ r = wordexp("\"$(date)\"", &we, WRDE_NOCMD);
+ ATF_REQUIRE(r == WRDE_CMDSUB);
+ r = wordexp("$((3+5))", &we, WRDE_NOCMD);
+ ATF_REQUIRE(r == 0);
+ r = wordexp("\\$\\(date\\)", &we, WRDE_NOCMD|WRDE_REUSE);
+ ATF_REQUIRE(r == 0);
+ r = wordexp("'`date`'", &we, WRDE_NOCMD|WRDE_REUSE);
+ ATF_REQUIRE(r == 0);
+ r = wordexp("'$(date)'", &we, WRDE_NOCMD|WRDE_REUSE);
+ ATF_REQUIRE(r == 0);
+ wordfree(&we);
+}
+
+ATF_TC_WITHOUT_HEAD(WRDE_BADCHAR_test);
+ATF_TC_BODY(WRDE_BADCHAR_test, tc)
+{
+ wordexp_t we;
+ int r;
+
+ r = wordexp("'\n|&;<>(){}'", &we, 0);
+ ATF_REQUIRE(r == 0);
+ r = wordexp("\"\n|&;<>(){}\"", &we, WRDE_REUSE);
+ ATF_REQUIRE(r == 0);
+ r = wordexp("\\\n\\|\\&\\;\\<\\>\\(\\)\\{\\}", &we, WRDE_REUSE);
+ ATF_REQUIRE(r == 0);
+ wordfree(&we);
+ r = wordexp("test \n test", &we, 0);
+ ATF_REQUIRE(r == WRDE_BADCHAR);
+ r = wordexp("test | test", &we, 0);
+ ATF_REQUIRE(r == WRDE_BADCHAR);
+ r = wordexp("test & test", &we, 0);
+ ATF_REQUIRE(r == WRDE_BADCHAR);
+ r = wordexp("test ; test", &we, 0);
+ ATF_REQUIRE(r == WRDE_BADCHAR);
+ r = wordexp("test > test", &we, 0);
+ ATF_REQUIRE(r == WRDE_BADCHAR);
+ r = wordexp("test < test", &we, 0);
+ ATF_REQUIRE(r == WRDE_BADCHAR);
+ r = wordexp("test ( test", &we, 0);
+ ATF_REQUIRE(r == WRDE_BADCHAR);
+ r = wordexp("test ) test", &we, 0);
+ ATF_REQUIRE(r == WRDE_BADCHAR);
+ r = wordexp("test { test", &we, 0);
+ ATF_REQUIRE(r == WRDE_BADCHAR);
+ r = wordexp("test } test", &we, 0);
+ ATF_REQUIRE(r == WRDE_BADCHAR);
+}
+
+ATF_TC_WITHOUT_HEAD(WRDE_SYNTAX_test);
+ATF_TC_BODY(WRDE_SYNTAX_test, tc)
+{
+ wordexp_t we;
+ int r;
+
+ r = wordexp("'", &we, 0);
+ ATF_REQUIRE(r == WRDE_SYNTAX);
+ r = wordexp("'", &we, WRDE_UNDEF);
+ ATF_REQUIRE(r == WRDE_SYNTAX);
+ r = wordexp("'\\'", &we, 0);
+ ATF_REQUIRE(r == 0);
+ ATF_REQUIRE(we.we_wordc == 1);
+ ATF_REQUIRE(strcmp(we.we_wordv[0], "\\") == 0);
+ ATF_REQUIRE(we.we_wordv[1] == NULL);
+ wordfree(&we);
+ /* Two syntax errors that are not detected by the current we_check(). */
+ r = wordexp("${IFS:+'}", &we, 0);
+ ATF_REQUIRE(r == WRDE_SYNTAX);
+ r = wordexp("${IFS:+'}", &we, WRDE_UNDEF);
+ ATF_REQUIRE(r == WRDE_SYNTAX);
+ r = wordexp("$(case)", &we, 0);
+ ATF_REQUIRE(r == WRDE_SYNTAX);
+ r = wordexp("$(case)", &we, WRDE_UNDEF);
+ ATF_REQUIRE(r == WRDE_SYNTAX);
+}
+
+ATF_TC_WITHOUT_HEAD(with_SIGCHILD_handler_test);
+ATF_TC_BODY(with_SIGCHILD_handler_test, tc)
+{
+ struct sigaction sa;
+ wordexp_t we;
+ int r;
+
+ /* With a SIGCHLD handler that reaps all zombies. */
+ sa.sa_flags = 0;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_handler = chld_handler;
+ r = sigaction(SIGCHLD, &sa, NULL);
+ ATF_REQUIRE(r == 0);
+ r = wordexp("hello world", &we, 0);
+ ATF_REQUIRE(r == 0);
+ ATF_REQUIRE(we.we_wordc == 2);
+ ATF_REQUIRE(strcmp(we.we_wordv[0], "hello") == 0);
+ ATF_REQUIRE(strcmp(we.we_wordv[1], "world") == 0);
+ ATF_REQUIRE(we.we_wordv[2] == NULL);
+ wordfree(&we);
+ sa.sa_handler = SIG_DFL;
+ r = sigaction(SIGCHLD, &sa, NULL);
+ ATF_REQUIRE(r == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(with_unused_non_default_IFS_test);
+ATF_TC_BODY(with_unused_non_default_IFS_test, tc)
+{
+ wordexp_t we;
+ int r;
+
+ /*
+ * With IFS set to a non-default value (without depending on whether
+ * IFS is inherited or not).
+ */
+ r = setenv("IFS", ":", 1);
+ ATF_REQUIRE(r == 0);
+ r = wordexp("hello world", &we, 0);
+ ATF_REQUIRE(r == 0);
+ ATF_REQUIRE(we.we_wordc == 2);
+ ATF_REQUIRE(strcmp(we.we_wordv[0], "hello") == 0);
+ ATF_REQUIRE(strcmp(we.we_wordv[1], "world") == 0);
+ ATF_REQUIRE(we.we_wordv[2] == NULL);
+ wordfree(&we);
+ r = unsetenv("IFS");
+ ATF_REQUIRE(r == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(with_used_non_default_IFS_test);
+ATF_TC_BODY(with_used_non_default_IFS_test, tc)
+{
+ wordexp_t we;
+ int r;
+
+ /*
+ * With IFS set to a non-default value, and using it.
+ */
+ r = setenv("IFS", ":", 1);
+ ATF_REQUIRE(r == 0);
+ r = wordexp("${IFS+hello:world}", &we, 0);
+ ATF_REQUIRE(r == 0);
+ ATF_REQUIRE(we.we_wordc == 2);
+ ATF_REQUIRE(strcmp(we.we_wordv[0], "hello") == 0);
+ ATF_REQUIRE(strcmp(we.we_wordv[1], "world") == 0);
+ ATF_REQUIRE(we.we_wordv[2] == NULL);
+ wordfree(&we);
+ r = unsetenv("IFS");
+ ATF_REQUIRE(r == 0);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, simple_test);
+ ATF_TP_ADD_TC(tp, long_output_test);
+ ATF_TP_ADD_TC(tp, WRDE_DOOFFS_test);
+ ATF_TP_ADD_TC(tp, WRDE_REUSE_test);
+ ATF_TP_ADD_TC(tp, WRDE_APPEND_test);
+ ATF_TP_ADD_TC(tp, WRDE_DOOFFS__WRDE_APPEND_test);
+ ATF_TP_ADD_TC(tp, WRDE_UNDEF_test);
+ ATF_TP_ADD_TC(tp, WRDE_NOCMD_test);
+ ATF_TP_ADD_TC(tp, WRDE_BADCHAR_test);
+ ATF_TP_ADD_TC(tp, WRDE_SYNTAX_test);
+ ATF_TP_ADD_TC(tp, with_SIGCHILD_handler_test);
+ ATF_TP_ADD_TC(tp, with_unused_non_default_IFS_test);
+ ATF_TP_ADD_TC(tp, with_used_non_default_IFS_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/locale/Makefile b/lib/libc/tests/locale/Makefile
index c0e0378..e05cbae 100644
--- a/lib/libc/tests/locale/Makefile
+++ b/lib/libc/tests/locale/Makefile
@@ -2,6 +2,24 @@
.include <bsd.own.mk>
+ATF_TESTS_C+= btowc_test
+ATF_TESTS_C+= c16rtomb_test
+ATF_TESTS_C+= iswctype_test
+ATF_TESTS_C+= mblen_test
+ATF_TESTS_C+= mbrlen_test
+ATF_TESTS_C+= mbrtoc16_test
+ATF_TESTS_C+= mbrtowc_2_test
+ATF_TESTS_C+= mbsnrtowcs_2_test
+ATF_TESTS_C+= mbsrtowcs_test
+ATF_TESTS_C+= mbstowcs_2_test
+ATF_TESTS_C+= mbtowc_2_test
+ATF_TESTS_C+= towctrans_test
+ATF_TESTS_C+= wcrtomb_test
+ATF_TESTS_C+= wcsnrtombs_test
+ATF_TESTS_C+= wcsrtombs_test
+ATF_TESTS_C+= wcstombs_test
+ATF_TESTS_C+= wctomb_2_test
+
NETBSD_ATF_TESTS_C= io_test
NETBSD_ATF_TESTS_C+= mbrtowc_test
NETBSD_ATF_TESTS_C+= mbstowcs_test
@@ -13,7 +31,13 @@ NETBSD_ATF_TESTS_C+= wcsspn_test
NETBSD_ATF_TESTS_C+= wcstod_test
NETBSD_ATF_TESTS_C+= wctomb_test
-CFLAGS.t_wctomb.c+= -Wno-stack-protector
+SRCS.mbrtowc_2_test= mbrtowc_test.c
+SRCS.mbsnrtowcs_2_test= mbsnrtowcs_test.c
+SRCS.mbstowcs_2_test= mbstowcs_test.c
+SRCS.mbtowc_2_test= mbtowc_test.c
+SRCS.wctomb_2_test= wctomb_test.c
+
+CFLAGS.t_wctomb.c+= -Wno-stack-protector
.include "../Makefile.netbsd-tests"
diff --git a/lib/libc/tests/locale/btowc_test.c b/lib/libc/tests/locale/btowc_test.c
new file mode 100644
index 0000000..01a1133
--- /dev/null
+++ b/lib/libc/tests/locale/btowc_test.c
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * 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.
+ */
+
+/*
+ * Test program for btowc() and wctob() as specified by IEEE Std. 1003.1-2001
+ * and ISO/IEC 9899:1999.
+ *
+ * The function is tested in the "C" and "ja_JP.eucJP" locales.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include <atf-c.h>
+
+ATF_TC_WITHOUT_HEAD(btowc_test);
+ATF_TC_BODY(btowc_test, tc)
+{
+ int i;
+
+ /* C/POSIX locale. */
+ ATF_REQUIRE(btowc(EOF) == WEOF);
+ ATF_REQUIRE(wctob(WEOF) == EOF);
+ for (i = 0; i < UCHAR_MAX; i++)
+ ATF_REQUIRE(btowc(i) == (wchar_t)i && i == (int)wctob(i));
+
+ /* Japanese (EUC) locale. */
+ ATF_REQUIRE(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0);
+ ATF_REQUIRE(MB_CUR_MAX > 1);
+ ATF_REQUIRE(btowc('A') == L'A' && wctob(L'A') == 'A');
+ ATF_REQUIRE(btowc(0xa3) == WEOF && wctob(0xa3c1) == EOF);
+
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, btowc_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/locale/c16rtomb_test.c b/lib/libc/tests/locale/c16rtomb_test.c
new file mode 100644
index 0000000..ea1f64f
--- /dev/null
+++ b/lib/libc/tests/locale/c16rtomb_test.c
@@ -0,0 +1,166 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Copyright (c) 2013 Ed Schouten <ed@FreeBSD.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.
+ */
+/*
+ * Test program for c16rtomb() as specified by ISO/IEC 9899:2011.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <string.h>
+#include <uchar.h>
+
+#include <atf-c.h>
+
+static void
+require_lc_ctype(const char *locale_name)
+{
+ char *lc_ctype_set;
+
+ lc_ctype_set = setlocale(LC_CTYPE, locale_name);
+ if (lc_ctype_set == NULL)
+ atf_tc_fail("setlocale(LC_CTYPE, \"%s\") failed; errno=%d",
+ locale_name, errno);
+
+ ATF_REQUIRE(strcmp(lc_ctype_set, locale_name) == 0);
+}
+
+static mbstate_t s;
+static char buf[MB_LEN_MAX + 1];
+
+ATF_TC_WITHOUT_HEAD(c16rtomb_c_locale_test);
+ATF_TC_BODY(c16rtomb_c_locale_test, tc)
+{
+
+ require_lc_ctype("C");
+
+ /*
+ * If the buffer argument is NULL, c16 is implicitly 0,
+ * c16rtomb() resets its internal state.
+ */
+ ATF_REQUIRE(c16rtomb(NULL, L'\0', NULL) == 1);
+ ATF_REQUIRE(c16rtomb(NULL, 0xdc00, NULL) == 1);
+
+ /* Null wide character. */
+ memset(&s, 0, sizeof(s));
+ memset(buf, 0xcc, sizeof(buf));
+ ATF_REQUIRE(c16rtomb(buf, 0, &s) == 1);
+ ATF_REQUIRE((unsigned char)buf[0] == 0 && (unsigned char)buf[1] == 0xcc);
+
+ /* Latin letter A, internal state. */
+ ATF_REQUIRE(c16rtomb(NULL, L'\0', NULL) == 1);
+ ATF_REQUIRE(c16rtomb(NULL, L'A', NULL) == 1);
+
+ /* Latin letter A. */
+ memset(&s, 0, sizeof(s));
+ memset(buf, 0xcc, sizeof(buf));
+ ATF_REQUIRE(c16rtomb(buf, L'A', &s) == 1);
+ ATF_REQUIRE((unsigned char)buf[0] == 'A' && (unsigned char)buf[1] == 0xcc);
+
+ /* Unicode character 'Pile of poo'. */
+ memset(&s, 0, sizeof(s));
+ memset(buf, 0xcc, sizeof(buf));
+ ATF_REQUIRE(c16rtomb(buf, 0xd83d, &s) == 0);
+ ATF_REQUIRE(c16rtomb(buf, 0xdca9, &s) == (size_t)-1);
+ ATF_REQUIRE(errno == EILSEQ);
+ ATF_REQUIRE((unsigned char)buf[0] == 0xcc);
+}
+
+ATF_TC_WITHOUT_HEAD(c16rtomb_iso_8859_1_test);
+ATF_TC_BODY(c16rtomb_iso_8859_1_test, tc)
+{
+
+ require_lc_ctype("en_US.ISO8859-1");
+
+ /* Unicode character 'Euro sign'. */
+ memset(&s, 0, sizeof(s));
+ memset(buf, 0xcc, sizeof(buf));
+ ATF_REQUIRE(c16rtomb(buf, 0x20ac, &s) == (size_t)-1);
+ ATF_REQUIRE(errno == EILSEQ);
+ ATF_REQUIRE((unsigned char)buf[0] == 0xcc);
+}
+
+ATF_TC_WITHOUT_HEAD(c16rtomb_iso_8859_15_test);
+ATF_TC_BODY(c16rtomb_iso_8859_15_test, tc)
+{
+
+ require_lc_ctype("en_US.ISO8859-15");
+
+ /* Unicode character 'Euro sign'. */
+ memset(&s, 0, sizeof(s));
+ memset(buf, 0xcc, sizeof(buf));
+ ATF_REQUIRE(c16rtomb(buf, 0x20ac, &s) == 1);
+ ATF_REQUIRE((unsigned char)buf[0] == 0xa4 && (unsigned char)buf[1] == 0xcc);
+}
+
+ATF_TC_WITHOUT_HEAD(c16rtomb_utf_8_test);
+ATF_TC_BODY(c16rtomb_utf_8_test, tc)
+{
+
+ require_lc_ctype("en_US.UTF-8");
+
+ /* Unicode character 'Pile of poo'. */
+ memset(&s, 0, sizeof(s));
+ memset(buf, 0xcc, sizeof(buf));
+ ATF_REQUIRE(c16rtomb(buf, 0xd83d, &s) == 0);
+ ATF_REQUIRE(c16rtomb(buf, 0xdca9, &s) == 4);
+ ATF_REQUIRE((unsigned char)buf[0] == 0xf0 && (unsigned char)buf[1] == 0x9f &&
+ (unsigned char)buf[2] == 0x92 && (unsigned char)buf[3] == 0xa9 &&
+ (unsigned char)buf[4] == 0xcc);
+
+ /* Invalid code; 'Pile of poo' without the trail surrogate. */
+ memset(&s, 0, sizeof(s));
+ memset(buf, 0xcc, sizeof(buf));
+ ATF_REQUIRE(c16rtomb(buf, 0xd83d, &s) == 0);
+ ATF_REQUIRE(c16rtomb(buf, L'A', &s) == (size_t)-1);
+ ATF_REQUIRE(errno == EILSEQ);
+ ATF_REQUIRE((unsigned char)buf[0] == 0xcc);
+
+ /* Invalid code; 'Pile of poo' without the lead surrogate. */
+ memset(&s, 0, sizeof(s));
+ memset(buf, 0xcc, sizeof(buf));
+ ATF_REQUIRE(c16rtomb(buf, 0xdca9, &s) == (size_t)-1);
+ ATF_REQUIRE(errno == EILSEQ);
+ ATF_REQUIRE((unsigned char)buf[0] == 0xcc);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, c16rtomb_c_locale_test);
+ ATF_TP_ADD_TC(tp, c16rtomb_iso_8859_1_test);
+ ATF_TP_ADD_TC(tp, c16rtomb_iso_8859_15_test);
+ ATF_TP_ADD_TC(tp, c16rtomb_utf_8_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/locale/iswctype_test.c b/lib/libc/tests/locale/iswctype_test.c
new file mode 100644
index 0000000..14e57b4
--- /dev/null
+++ b/lib/libc/tests/locale/iswctype_test.c
@@ -0,0 +1,122 @@
+/*-
+ * Copyright (c) 2003 Tim J. Robbins
+ * 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.
+ */
+
+/*
+ * Test program for wctype() and iswctype() as specified by
+ * IEEE Std. 1003.1-2001 and ISO/IEC 9899:1999.
+ *
+ * The functions are tested in the "C" and "ja_JP.eucJP" locales.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <errno.h>
+#include <locale.h>
+#include <stdio.h>
+#include <string.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include <atf-c.h>
+
+static void
+require_lc_ctype(const char *locale_name)
+{
+ char *lc_ctype_set;
+
+ lc_ctype_set = setlocale(LC_CTYPE, locale_name);
+ if (lc_ctype_set == NULL)
+ atf_tc_fail("setlocale(LC_CTYPE, \"%s\") failed; errno=%d",
+ locale_name, errno);
+
+ ATF_REQUIRE(strcmp(lc_ctype_set, locale_name) == 0);
+}
+
+static wctype_t t;
+static int i, j;
+static struct {
+ const char *name;
+ int (*func)(wint_t);
+} cls[] = {
+ { "alnum", iswalnum },
+ { "alpha", iswalpha },
+ { "blank", iswblank },
+ { "cntrl", iswcntrl },
+ { "digit", iswdigit },
+ { "graph", iswgraph },
+ { "lower", iswlower },
+ { "print", iswprint },
+ { "punct", iswpunct },
+ { "space", iswspace },
+ { "upper", iswupper },
+ { "xdigit", iswxdigit }
+};
+
+ATF_TC_WITHOUT_HEAD(iswctype_c_locale_test);
+ATF_TC_BODY(iswctype_c_locale_test, tc)
+{
+
+ require_lc_ctype("C");
+ for (i = 0; i < nitems(cls); i++) {
+ t = wctype(cls[i].name);
+ ATF_REQUIRE(t != 0);
+ for (j = 0; j < 256; j++)
+ ATF_REQUIRE(cls[i].func(j) == iswctype(j, t));
+ }
+ t = wctype("elephant");
+ ATF_REQUIRE(t == 0);
+ for (i = 0; i < 256; i++)
+ ATF_REQUIRE(iswctype(i, t) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(iswctype_euc_jp_test);
+ATF_TC_BODY(iswctype_euc_jp_test, tc)
+{
+
+ require_lc_ctype("ja_JP.eucJP");
+
+ for (i = 0; i < nitems(cls); i++) {
+ t = wctype(cls[i].name);
+ ATF_REQUIRE(t != 0);
+ for (j = 0; j < 65536; j++)
+ ATF_REQUIRE(cls[i].func(j) == iswctype(j, t));
+ }
+ t = wctype("elephant");
+ ATF_REQUIRE(t == 0);
+ for (i = 0; i < 65536; i++)
+ ATF_REQUIRE(iswctype(i, t) == 0);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, iswctype_c_locale_test);
+ ATF_TP_ADD_TC(tp, iswctype_euc_jp_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/locale/mblen_test.c b/lib/libc/tests/locale/mblen_test.c
new file mode 100644
index 0000000..fbb938d
--- /dev/null
+++ b/lib/libc/tests/locale/mblen_test.c
@@ -0,0 +1,116 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins
+ * 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.
+ */
+
+/*
+ * Test program for mblen(), as specified by IEEE Std. 1003.1-2001 and
+ * ISO/IEC 9899:1990.
+ *
+ * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and
+ * "ja_JP.eucJP". Other encodings are not tested.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <atf-c.h>
+
+ATF_TC_WITHOUT_HEAD(mblen_test);
+ATF_TC_BODY(mblen_test, tc)
+{
+ char buf[MB_LEN_MAX + 1];
+
+ /*
+ * C/POSIX locale.
+ */
+
+ ATF_REQUIRE(MB_CUR_MAX == 1);
+
+ /* No shift states in C locale. */
+ ATF_REQUIRE(mblen(NULL, 0) == 0);
+
+ /* Null wide character. */
+ memset(buf, 0xcc, sizeof(buf));
+ buf[0] = '\0';
+ ATF_REQUIRE(mblen(buf, 1) == 0);
+
+ /* Latin letter A. */
+ buf[0] = 'A';
+ ATF_REQUIRE(mblen(buf, 1) == 1);
+
+ /* Incomplete character sequence. */
+ buf[0] = '\0';
+ ATF_REQUIRE(mblen(buf, 0) == -1);
+ ATF_REQUIRE(mblen(NULL, 0) == 0);
+
+ /*
+ * Japanese (EUC) locale.
+ */
+
+ ATF_REQUIRE(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0);
+ ATF_REQUIRE(MB_CUR_MAX > 1);
+
+ /* No shift states in EUC. */
+ ATF_REQUIRE(mblen(NULL, 0) == 0);
+
+ /* Null wide character. */
+ memset(buf, 0xcc, sizeof(buf));
+ buf[0] = '\0';
+ ATF_REQUIRE(mblen(buf, 1) == 0);
+
+ /* Latin letter A. */
+ buf[0] = 'A';
+ ATF_REQUIRE(mblen(buf, 1) == 1);
+
+ /* Incomplete character sequence. */
+ buf[0] = '\0';
+ ATF_REQUIRE(mblen(buf, 0) == -1);
+ ATF_REQUIRE(mblen(NULL, 0) == 0);
+
+ /* Incomplete character sequence (truncated double-byte). */
+ memset(buf, 0xcc, sizeof(buf));
+ buf[0] = 0xa3;
+ buf[1] = 0x00;
+ ATF_REQUIRE(mblen(buf, 1) == -1);
+ ATF_REQUIRE(mblen(NULL, 0) == 0);
+
+ /* Same as above, but complete. */
+ buf[1] = 0xc1;
+ ATF_REQUIRE(mblen(buf, 2) == 2);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, mblen_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/locale/mbrlen_test.c b/lib/libc/tests/locale/mbrlen_test.c
new file mode 100644
index 0000000..c2bc548
--- /dev/null
+++ b/lib/libc/tests/locale/mbrlen_test.c
@@ -0,0 +1,126 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * 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.
+ */
+
+/*
+ * Test program for mbrlen(), as specified by IEEE Std. 1003.1-2001 and
+ * ISO/IEC 9899:1999.
+ *
+ * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and
+ * "ja_JP.eucJP". Other encodings are not tested.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include <atf-c.h>
+
+ATF_TC_WITHOUT_HEAD(mbrlen_test);
+ATF_TC_BODY(mbrlen_test, tc)
+{
+ mbstate_t s;
+ char buf[MB_LEN_MAX + 1];
+
+ /* C/POSIX locale. */
+ ATF_REQUIRE(MB_CUR_MAX == 1);
+
+ /* Null wide character, internal state. */
+ memset(buf, 0xcc, sizeof(buf));
+ buf[0] = 0;
+ ATF_REQUIRE(mbrlen(buf, 1, NULL) == 0);
+
+ /* Null wide character. */
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbrlen(buf, 1, &s) == 0);
+
+ /* Latin letter A, internal state. */
+ ATF_REQUIRE(mbrlen(NULL, 0, NULL) == 0);
+ buf[0] = 'A';
+ ATF_REQUIRE(mbrlen(buf, 1, NULL) == 1);
+
+ /* Latin letter A. */
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbrlen(buf, 1, &s) == 1);
+
+ /* Incomplete character sequence. */
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbrlen(buf, 0, &s) == (size_t)-2);
+
+ /* Japanese (EUC) locale. */
+
+ ATF_REQUIRE(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0);
+ ATF_REQUIRE(MB_CUR_MAX > 1);
+
+ /* Null wide character, internal state. */
+ ATF_REQUIRE(mbrlen(NULL, 0, NULL) == 0);
+ memset(buf, 0xcc, sizeof(buf));
+ buf[0] = 0;
+ ATF_REQUIRE(mbrlen(buf, 1, NULL) == 0);
+
+ /* Null wide character. */
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbrlen(buf, 1, &s) == 0);
+
+ /* Latin letter A, internal state. */
+ ATF_REQUIRE(mbrlen(NULL, 0, NULL) == 0);
+ buf[0] = 'A';
+ ATF_REQUIRE(mbrlen(buf, 1, NULL) == 1);
+
+ /* Latin letter A. */
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbrlen(buf, 1, &s) == 1);
+
+ /* Incomplete character sequence (zero length). */
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbrlen(buf, 0, &s) == (size_t)-2);
+
+ /* Incomplete character sequence (truncated double-byte). */
+ memset(buf, 0xcc, sizeof(buf));
+ buf[0] = 0xa3;
+ buf[1] = 0x00;
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbrlen(buf, 1, &s) == (size_t)-2);
+
+ /* Same as above, but complete. */
+ buf[1] = 0xc1;
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbrlen(buf, 2, &s) == 2);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, mbrlen_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/locale/mbrtoc16_test.c b/lib/libc/tests/locale/mbrtoc16_test.c
new file mode 100644
index 0000000..a6289e1
--- /dev/null
+++ b/lib/libc/tests/locale/mbrtoc16_test.c
@@ -0,0 +1,214 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Copyright (c) 2013 Ed Schouten <ed@FreeBSD.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.
+ */
+/*
+ * Test program for mbrtoc16() as specified by ISO/IEC 9899:2011.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <string.h>
+#include <uchar.h>
+
+#include <atf-c.h>
+
+static void
+require_lc_ctype(const char *locale_name)
+{
+ char *lc_ctype_set;
+
+ lc_ctype_set = setlocale(LC_CTYPE, locale_name);
+ if (lc_ctype_set == NULL)
+ atf_tc_fail("setlocale(LC_CTYPE, \"%s\") failed; errno=%d",
+ locale_name, errno);
+
+ ATF_REQUIRE(strcmp(lc_ctype_set, locale_name) == 0);
+}
+
+static mbstate_t s;
+static char16_t c16;
+
+ATF_TC_WITHOUT_HEAD(mbrtoc16_c_locale_test);
+ATF_TC_BODY(mbrtoc16_c_locale_test, tc)
+{
+
+ require_lc_ctype("C");
+
+ /* Null wide character, internal state. */
+ ATF_REQUIRE(mbrtoc16(&c16, "", 1, NULL) == 0);
+ ATF_REQUIRE(c16 == 0);
+
+ /* Null wide character. */
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbrtoc16(&c16, "", 1, &s) == 0);
+ ATF_REQUIRE(c16 == 0);
+
+ /* Latin letter A, internal state. */
+ ATF_REQUIRE(mbrtoc16(NULL, 0, 0, NULL) == 0);
+ ATF_REQUIRE(mbrtoc16(&c16, "A", 1, NULL) == 1);
+ ATF_REQUIRE(c16 == L'A');
+
+ /* Latin letter A. */
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbrtoc16(&c16, "A", 1, &s) == 1);
+ ATF_REQUIRE(c16 == L'A');
+
+ /* Incomplete character sequence. */
+ c16 = L'z';
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbrtoc16(&c16, "", 0, &s) == (size_t)-2);
+ ATF_REQUIRE(c16 == L'z');
+
+ /* Check that mbrtoc16() doesn't access the buffer when n == 0. */
+ c16 = L'z';
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbrtoc16(&c16, "", 0, &s) == (size_t)-2);
+ ATF_REQUIRE(c16 == L'z');
+
+ /* Check that mbrtoc16() doesn't read ahead too aggressively. */
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbrtoc16(&c16, "AB", 2, &s) == 1);
+ ATF_REQUIRE(c16 == L'A');
+ ATF_REQUIRE(mbrtoc16(&c16, "C", 1, &s) == 1);
+ ATF_REQUIRE(c16 == L'C');
+
+}
+
+ATF_TC_WITHOUT_HEAD(mbrtoc16_iso_8859_1_test);
+ATF_TC_BODY(mbrtoc16_iso_8859_1_test, tc)
+{
+
+ require_lc_ctype("en_US.ISO8859-1");
+
+ /* Currency sign. */
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbrtoc16(&c16, "\xa4", 1, &s) == 1);
+ ATF_REQUIRE(c16 == 0xa4);
+}
+
+ATF_TC_WITHOUT_HEAD(mbrtoc16_iso_8859_15_test);
+ATF_TC_BODY(mbrtoc16_iso_8859_15_test, tc)
+{
+
+ require_lc_ctype("en_US.ISO8859-15");
+
+ /* Euro sign. */
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbrtoc16(&c16, "\xa4", 1, &s) == 1);
+ ATF_REQUIRE(c16 == 0x20ac);
+}
+
+ATF_TC_WITHOUT_HEAD(mbrtoc16_utf_8_test);
+ATF_TC_BODY(mbrtoc16_utf_8_test, tc)
+{
+
+ require_lc_ctype("en_US.UTF-8");
+
+ /* Null wide character, internal state. */
+ ATF_REQUIRE(mbrtoc16(NULL, 0, 0, NULL) == 0);
+ ATF_REQUIRE(mbrtoc16(&c16, "", 1, NULL) == 0);
+ ATF_REQUIRE(c16 == 0);
+
+ /* Null wide character. */
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbrtoc16(&c16, "", 1, &s) == 0);
+ ATF_REQUIRE(c16 == 0);
+
+ /* Latin letter A, internal state. */
+ ATF_REQUIRE(mbrtoc16(NULL, 0, 0, NULL) == 0);
+ ATF_REQUIRE(mbrtoc16(&c16, "A", 1, NULL) == 1);
+ ATF_REQUIRE(c16 == L'A');
+
+ /* Latin letter A. */
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbrtoc16(&c16, "A", 1, &s) == 1);
+ ATF_REQUIRE(c16 == L'A');
+
+ /* Incomplete character sequence (zero length). */
+ c16 = L'z';
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbrtoc16(&c16, "", 0, &s) == (size_t)-2);
+ ATF_REQUIRE(c16 == L'z');
+
+ /* Incomplete character sequence (truncated double-byte). */
+ memset(&s, 0, sizeof(s));
+ c16 = 0;
+ ATF_REQUIRE(mbrtoc16(&c16, "\xc3", 1, &s) == (size_t)-2);
+
+ /* Same as above, but complete. */
+ memset(&s, 0, sizeof(s));
+ c16 = 0;
+ ATF_REQUIRE(mbrtoc16(&c16, "\xc3\x84", 2, &s) == 2);
+ ATF_REQUIRE(c16 == 0xc4);
+
+ /* Test restarting behaviour. */
+ memset(&s, 0, sizeof(s));
+ c16 = 0;
+ ATF_REQUIRE(mbrtoc16(&c16, "\xc3", 1, &s) == (size_t)-2);
+ ATF_REQUIRE(c16 == 0);
+ ATF_REQUIRE(mbrtoc16(&c16, "\xb7", 1, &s) == 1);
+ ATF_REQUIRE(c16 == 0xf7);
+
+ /* Surrogate pair. */
+ memset(&s, 0, sizeof(s));
+ c16 = 0;
+ ATF_REQUIRE(mbrtoc16(&c16, "\xf0\x9f\x92\xa9", 4, &s) == 4);
+ ATF_REQUIRE(c16 == 0xd83d);
+ ATF_REQUIRE(mbrtoc16(&c16, "", 0, &s) == (size_t)-3);
+ ATF_REQUIRE(c16 == 0xdca9);
+
+ /* Letter e with acute, precomposed. */
+ memset(&s, 0, sizeof(s));
+ c16 = 0;
+ ATF_REQUIRE(mbrtoc16(&c16, "\xc3\xa9", 2, &s) == 2);
+ ATF_REQUIRE(c16 == 0xe9);
+
+ /* Letter e with acute, combined. */
+ memset(&s, 0, sizeof(s));
+ c16 = 0;
+ ATF_REQUIRE(mbrtoc16(&c16, "\x65\xcc\x81", 3, &s) == 1);
+ ATF_REQUIRE(c16 == 0x65);
+ ATF_REQUIRE(mbrtoc16(&c16, "\xcc\x81", 2, &s) == 2);
+ ATF_REQUIRE(c16 == 0x301);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, mbrtoc16_c_locale_test);
+ ATF_TP_ADD_TC(tp, mbrtoc16_iso_8859_1_test);
+ ATF_TP_ADD_TC(tp, mbrtoc16_iso_8859_15_test);
+ ATF_TP_ADD_TC(tp, mbrtoc16_utf_8_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/locale/mbrtowc_test.c b/lib/libc/tests/locale/mbrtowc_test.c
new file mode 100644
index 0000000..37e0bfd
--- /dev/null
+++ b/lib/libc/tests/locale/mbrtowc_test.c
@@ -0,0 +1,165 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * 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.
+ */
+
+/*
+ * Test program for mbrtowc(), as specified by IEEE Std. 1003.1-2001 and
+ * ISO/IEC 9899:1999.
+ *
+ * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and
+ * "ja_JP.eucJP". Other encodings are not tested.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include <atf-c.h>
+
+ATF_TC_WITHOUT_HEAD(mbrtowc_test);
+ATF_TC_BODY(mbrtowc_test, tc)
+{
+ mbstate_t s;
+ wchar_t wc;
+ char buf[MB_LEN_MAX + 1];
+
+ /*
+ * C/POSIX locale.
+ */
+
+ ATF_REQUIRE(MB_CUR_MAX == 1);
+
+ /* Null wide character, internal state. */
+ memset(buf, 0xcc, sizeof(buf));
+ buf[0] = 0;
+ ATF_REQUIRE(mbrtowc(&wc, buf, 1, NULL) == 0);
+ ATF_REQUIRE(wc == 0);
+
+ /* Null wide character. */
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbrtowc(&wc, buf, 1, &s) == 0);
+ ATF_REQUIRE(wc == 0);
+
+ /* Latin letter A, internal state. */
+ ATF_REQUIRE(mbrtowc(NULL, 0, 0, NULL) == 0);
+ buf[0] = 'A';
+ ATF_REQUIRE(mbrtowc(&wc, buf, 1, NULL) == 1);
+ ATF_REQUIRE(wc == L'A');
+
+ /* Latin letter A. */
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbrtowc(&wc, buf, 1, &s) == 1);
+ ATF_REQUIRE(wc == L'A');
+
+ /* Incomplete character sequence. */
+ wc = L'z';
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbrtowc(&wc, buf, 0, &s) == (size_t)-2);
+ ATF_REQUIRE(wc == L'z');
+
+ /* Check that mbrtowc() doesn't access the buffer when n == 0. */
+ wc = L'z';
+ memset(&s, 0, sizeof(s));
+ buf[0] = '\0';
+ ATF_REQUIRE(mbrtowc(&wc, buf, 0, &s) == (size_t)-2);
+ ATF_REQUIRE(wc == L'z');
+
+ /*
+ * Japanese (EUC) locale.
+ */
+
+ ATF_REQUIRE(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0);
+ ATF_REQUIRE(MB_CUR_MAX > 1);
+
+ /* Null wide character, internal state. */
+ ATF_REQUIRE(mbrtowc(NULL, 0, 0, NULL) == 0);
+ memset(buf, 0xcc, sizeof(buf));
+ buf[0] = 0;
+ ATF_REQUIRE(mbrtowc(&wc, buf, 1, NULL) == 0);
+ ATF_REQUIRE(wc == 0);
+
+ /* Null wide character. */
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbrtowc(&wc, buf, 1, &s) == 0);
+ ATF_REQUIRE(wc == 0);
+
+ /* Latin letter A, internal state. */
+ ATF_REQUIRE(mbrtowc(NULL, 0, 0, NULL) == 0);
+ buf[0] = 'A';
+ ATF_REQUIRE(mbrtowc(&wc, buf, 1, NULL) == 1);
+ ATF_REQUIRE(wc == L'A');
+
+ /* Latin letter A. */
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbrtowc(&wc, buf, 1, &s) == 1);
+ ATF_REQUIRE(wc == L'A');
+
+ /* Incomplete character sequence (zero length). */
+ wc = L'z';
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbrtowc(&wc, buf, 0, &s) == (size_t)-2);
+ ATF_REQUIRE(wc == L'z');
+
+ /* Incomplete character sequence (truncated double-byte). */
+ memset(buf, 0xcc, sizeof(buf));
+ buf[0] = 0xa3;
+ buf[1] = 0x00;
+ memset(&s, 0, sizeof(s));
+ wc = 0;
+ ATF_REQUIRE(mbrtowc(&wc, buf, 1, &s) == (size_t)-2);
+
+ /* Same as above, but complete. */
+ buf[1] = 0xc1;
+ memset(&s, 0, sizeof(s));
+ wc = 0;
+ ATF_REQUIRE(mbrtowc(&wc, buf, 2, &s) == 2);
+ ATF_REQUIRE(wc == 0xa3c1);
+
+ /* Test restarting behaviour. */
+ memset(buf, 0xcc, sizeof(buf));
+ buf[0] = 0xa3;
+ memset(&s, 0, sizeof(s));
+ wc = 0;
+ ATF_REQUIRE(mbrtowc(&wc, buf, 1, &s) == (size_t)-2);
+ ATF_REQUIRE(wc == 0);
+ buf[0] = 0xc1;
+ ATF_REQUIRE(mbrtowc(&wc, buf, 1, &s) == 1);
+ ATF_REQUIRE(wc == 0xa3c1);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, mbrtowc_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/locale/mbsnrtowcs_test.c b/lib/libc/tests/locale/mbsnrtowcs_test.c
new file mode 100644
index 0000000..4012b7e
--- /dev/null
+++ b/lib/libc/tests/locale/mbsnrtowcs_test.c
@@ -0,0 +1,195 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins
+ * 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.
+ */
+
+/*
+ * Test program for mbsnrtowcs().
+ *
+ * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and
+ * "ja_JP.eucJP". Other encodings are not tested.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include <atf-c.h>
+
+ATF_TC_WITHOUT_HEAD(mbsnrtowcs_test);
+ATF_TC_BODY(mbsnrtowcs_test, tc)
+{
+ char srcbuf[128];
+ wchar_t dstbuf[128];
+ char *src;
+ mbstate_t s;
+
+ /* C/POSIX locale. */
+
+ /* Simple null terminated string. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 6, sizeof(dstbuf) /
+ sizeof(*dstbuf), &s) == 5);
+ ATF_REQUIRE(wcscmp(dstbuf, L"hello") == 0);
+ ATF_REQUIRE(dstbuf[6] == 0xcccc);
+ ATF_REQUIRE(src == NULL);
+
+ /* Simple null terminated string, stopping early. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 4, sizeof(dstbuf) /
+ sizeof(*dstbuf), &s) == 4);
+ ATF_REQUIRE(wmemcmp(dstbuf, L"hell", 4) == 0);
+ ATF_REQUIRE(dstbuf[5] == 0xcccc);
+ ATF_REQUIRE(src == srcbuf + 4);
+
+ /* Not enough space in destination buffer. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 6, 4, &s) == 4);
+ ATF_REQUIRE(wmemcmp(dstbuf, L"hell", 4) == 0);
+ ATF_REQUIRE(dstbuf[5] == 0xcccc);
+ ATF_REQUIRE(src == srcbuf + 4);
+
+ /* Null terminated string, internal dest. buffer */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbsnrtowcs(NULL, (const char **)&src, 6, 0, &s) == 5);
+
+ /* Null terminated string, internal dest. buffer, stopping early */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbsnrtowcs(NULL, (const char **)&src, 4, 0, &s) == 4);
+
+ /* Null terminated string, internal state. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ src = srcbuf;
+ ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 6, sizeof(dstbuf) /
+ sizeof(*dstbuf), NULL) == 5);
+ ATF_REQUIRE(wcscmp(dstbuf, L"hello") == 0);
+ ATF_REQUIRE(dstbuf[6] == 0xcccc);
+ ATF_REQUIRE(src == NULL);
+
+ /* Null terminated string, internal state, internal dest. buffer. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ src = srcbuf;
+ ATF_REQUIRE(mbsnrtowcs(NULL, (const char **)&src, 6, 0, NULL) == 5);
+
+ /* Empty source buffer. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ srcbuf[0] = '\0';
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 1, 1, &s) == 0);
+ ATF_REQUIRE(dstbuf[0] == 0);
+ ATF_REQUIRE(dstbuf[1] == 0xcccc);
+ ATF_REQUIRE(src == NULL);
+
+ /* Zero length destination buffer. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 1, 0, &s) == 0);
+ ATF_REQUIRE(dstbuf[0] == 0xcccc);
+ ATF_REQUIRE(src == srcbuf);
+
+ /* Zero length source buffer. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 0, 1, &s) == 0);
+ ATF_REQUIRE(dstbuf[0] == 0xcccc);
+ ATF_REQUIRE(src == srcbuf);
+
+ /*
+ * Japanese (EUC) locale.
+ */
+
+ ATF_REQUIRE(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0);
+ ATF_REQUIRE(MB_CUR_MAX > 1);
+
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "\xA3\xC1 B \xA3\xC3");
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 8, sizeof(dstbuf) /
+ sizeof(*dstbuf), &s) == 5);
+ ATF_REQUIRE(dstbuf[0] == 0xA3C1 && dstbuf[1] == 0x20 && dstbuf[2] == 0x42 &&
+ dstbuf[3] == 0x20 && dstbuf[4] == 0xA3C3 && dstbuf[5] == 0);
+ ATF_REQUIRE(src == NULL);
+
+ /* Partial character. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "\xA3\xC1 B \xA3\xC3");
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 6, sizeof(dstbuf) /
+ sizeof(*dstbuf), &s) == 4);
+ ATF_REQUIRE(src == srcbuf + 6);
+ ATF_REQUIRE(!mbsinit(&s));
+ ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 1, sizeof(dstbuf) /
+ sizeof(*dstbuf), &s) == 1);
+ ATF_REQUIRE(src == srcbuf + 7);
+ ATF_REQUIRE(mbsnrtowcs(dstbuf, (const char **)&src, 1, sizeof(dstbuf) /
+ sizeof(*dstbuf), &s) == 0);
+ ATF_REQUIRE(src == NULL);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, mbsnrtowcs_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/locale/mbsrtowcs_test.c b/lib/libc/tests/locale/mbsrtowcs_test.c
new file mode 100644
index 0000000..1b9d5c9
--- /dev/null
+++ b/lib/libc/tests/locale/mbsrtowcs_test.c
@@ -0,0 +1,153 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * 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.
+ */
+
+/*
+ * Test program for mbsrtowcs(), as specified by IEEE Std. 1003.1-2001 and
+ * ISO/IEC 9899:1999.
+ *
+ * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and
+ * "ja_JP.eucJP". Other encodings are not tested.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include <atf-c.h>
+
+ATF_TC_WITHOUT_HEAD(mbsrtowcs_test);
+ATF_TC_BODY(mbsrtowcs_test, tc)
+{
+ char srcbuf[128];
+ wchar_t dstbuf[128];
+ char *src;
+ mbstate_t s;
+
+ /*
+ * C/POSIX locale.
+ */
+
+ /* Simple null terminated string. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbsrtowcs(dstbuf, (const char **)&src, sizeof(dstbuf) /
+ sizeof(*dstbuf), &s) == 5);
+ ATF_REQUIRE(wcscmp(dstbuf, L"hello") == 0);
+ ATF_REQUIRE(dstbuf[6] == 0xcccc);
+ ATF_REQUIRE(src == NULL);
+
+ /* Not enough space in destination buffer. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbsrtowcs(dstbuf, (const char **)&src, 4, &s) == 4);
+ ATF_REQUIRE(wmemcmp(dstbuf, L"hell", 4) == 0);
+ ATF_REQUIRE(dstbuf[5] == 0xcccc);
+ ATF_REQUIRE(src == srcbuf + 4);
+
+ /* Null terminated string, internal dest. buffer */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(mbsrtowcs(NULL, (const char **)&src, 0, &s) == 5);
+
+ /* Null terminated string, internal state. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ src = srcbuf;
+ ATF_REQUIRE(mbsrtowcs(dstbuf, (const char **)&src, sizeof(dstbuf) /
+ sizeof(*dstbuf), NULL) == 5);
+ ATF_REQUIRE(wcscmp(dstbuf, L"hello") == 0);
+ ATF_REQUIRE(dstbuf[6] == 0xcccc);
+ ATF_REQUIRE(src == NULL);
+
+ /* Null terminated string, internal state, internal dest. buffer. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ src = srcbuf;
+ ATF_REQUIRE(mbsrtowcs(NULL, (const char **)&src, 0, NULL) == 5);
+
+ /* Empty source buffer. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ srcbuf[0] = '\0';
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ ATF_REQUIRE(mbsrtowcs(dstbuf, (const char **)&src, 1, &s) == 0);
+ ATF_REQUIRE(dstbuf[0] == 0);
+ ATF_REQUIRE(dstbuf[1] == 0xcccc);
+ ATF_REQUIRE(src == NULL);
+
+ /* Zero length destination buffer. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ ATF_REQUIRE(mbsrtowcs(dstbuf, (const char **)&src, 0, &s) == 0);
+ ATF_REQUIRE(dstbuf[0] == 0xcccc);
+ ATF_REQUIRE(src == srcbuf);
+
+ /*
+ * Japanese (EUC) locale.
+ */
+
+ ATF_REQUIRE(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0);
+ ATF_REQUIRE(MB_CUR_MAX > 1);
+
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "\xA3\xC1 B \xA3\xC3");
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ ATF_REQUIRE(mbsrtowcs(dstbuf, (const char **)&src, sizeof(dstbuf) /
+ sizeof(*dstbuf), &s) == 5);
+ ATF_REQUIRE(dstbuf[0] == 0xA3C1 && dstbuf[1] == 0x20 && dstbuf[2] == 0x42 &&
+ dstbuf[3] == 0x20 && dstbuf[4] == 0xA3C3 && dstbuf[5] == 0);
+ ATF_REQUIRE(src == NULL);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, mbsrtowcs_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/locale/mbstowcs_test.c b/lib/libc/tests/locale/mbstowcs_test.c
new file mode 100644
index 0000000..77b0e9e
--- /dev/null
+++ b/lib/libc/tests/locale/mbstowcs_test.c
@@ -0,0 +1,111 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * 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.
+ */
+
+/*
+ * Test program for mbstowcs(), as specified by IEEE Std. 1003.1-2001 and
+ * ISO/IEC 9899:1999.
+ *
+ * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and
+ * "ja_JP.eucJP". Other encodings are not tested.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include <atf-c.h>
+
+ATF_TC_WITHOUT_HEAD(mbstowcs_test);
+ATF_TC_BODY(mbstowcs_test, tc)
+{
+ char srcbuf[128];
+ wchar_t dstbuf[128];
+
+ /* C/POSIX locale. */
+
+ /* Simple null terminated string. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ ATF_REQUIRE(mbstowcs(dstbuf, srcbuf, sizeof(dstbuf) / sizeof(*dstbuf)) == 5);
+ ATF_REQUIRE(wcscmp(dstbuf, L"hello") == 0);
+ ATF_REQUIRE(dstbuf[6] == 0xcccc);
+
+ /* Not enough space in destination buffer. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ ATF_REQUIRE(mbstowcs(dstbuf, srcbuf, 4) == 4);
+ ATF_REQUIRE(wmemcmp(dstbuf, L"hell", 4) == 0);
+ ATF_REQUIRE(dstbuf[5] == 0xcccc);
+
+ /* Null terminated string, internal dest. buffer (XSI extension) */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ ATF_REQUIRE(mbstowcs(NULL, srcbuf, 0) == 5);
+
+ /* Empty source buffer. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ srcbuf[0] = '\0';
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ ATF_REQUIRE(mbstowcs(dstbuf, srcbuf, 1) == 0);
+ ATF_REQUIRE(dstbuf[0] == 0);
+ ATF_REQUIRE(dstbuf[1] == 0xcccc);
+
+ /* Zero length destination buffer. */
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "hello");
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ ATF_REQUIRE(mbstowcs(dstbuf, srcbuf, 0) == 0);
+ ATF_REQUIRE(dstbuf[0] == 0xcccc);
+
+ /* Japanese (EUC) locale. */
+
+ ATF_REQUIRE(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0);
+ ATF_REQUIRE(MB_CUR_MAX > 1);
+
+ memset(srcbuf, 0xcc, sizeof(srcbuf));
+ strcpy(srcbuf, "\xA3\xC1 B \xA3\xC3");
+ wmemset(dstbuf, 0xcccc, sizeof(dstbuf) / sizeof(*dstbuf));
+ ATF_REQUIRE(mbstowcs(dstbuf, srcbuf, sizeof(dstbuf) / sizeof(*dstbuf)) == 5);
+ ATF_REQUIRE(dstbuf[0] == 0xA3C1 && dstbuf[1] == 0x20 && dstbuf[2] == 0x42 &&
+ dstbuf[3] == 0x20 && dstbuf[4] == 0xA3C3 && dstbuf[5] == 0);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, mbstowcs_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/locale/mbtowc_test.c b/lib/libc/tests/locale/mbtowc_test.c
new file mode 100644
index 0000000..7c7f80e
--- /dev/null
+++ b/lib/libc/tests/locale/mbtowc_test.c
@@ -0,0 +1,122 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins
+ * 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.
+ */
+
+/*
+ * Test program for mbtowc(), as specified by IEEE Std. 1003.1-2001 and
+ * ISO/IEC 9899:1990.
+ *
+ * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and
+ * "ja_JP.eucJP". Other encodings are not tested.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <atf-c.h>
+
+ATF_TC_WITHOUT_HEAD(mbtowc_test);
+ATF_TC_BODY(mbtowc_test, tc)
+{
+ char buf[MB_LEN_MAX + 1];
+ wchar_t wc;
+
+ /* C/POSIX locale. */
+
+ ATF_REQUIRE(MB_CUR_MAX == 1);
+
+ /* No shift states in C locale. */
+ ATF_REQUIRE(mbtowc(NULL, NULL, 0) == 0);
+
+ /* Null wide character. */
+ wc = 0xcccc;
+ memset(buf, 0, sizeof(buf));
+ ATF_REQUIRE(mbtowc(&wc, buf, 1) == 0);
+ ATF_REQUIRE(wc == 0);
+
+ /* Latin letter A. */
+ buf[0] = 'A';
+ ATF_REQUIRE(mbtowc(&wc, buf, 1) == 1);
+ ATF_REQUIRE(wc == L'A');
+
+ /* Incomplete character sequence. */
+ wc = L'z';
+ buf[0] = '\0';
+ ATF_REQUIRE(mbtowc(&wc, buf, 0) == -1);
+ ATF_REQUIRE(wc == L'z');
+ ATF_REQUIRE(mbtowc(NULL, NULL, 0) == 0);
+
+ /* Japanese (EUC) locale. */
+
+ ATF_REQUIRE(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0);
+ ATF_REQUIRE(MB_CUR_MAX > 1);
+
+ /* Null wide character */
+ memset(buf, 0xcc, sizeof(buf));
+ buf[0] = 0;
+ wc = 0xcccc;
+ ATF_REQUIRE(mbtowc(&wc, buf, 1) == 0);
+ ATF_REQUIRE(wc == 0);
+
+ /* Latin letter A. */
+ buf[0] = 'A';
+ ATF_REQUIRE(mbtowc(&wc, buf, 1) == 1);
+ ATF_REQUIRE(wc == L'A');
+
+ /* Incomplete character sequence (zero length). */
+ wc = L'z';
+ buf[0] = '\0';
+ ATF_REQUIRE(mbtowc(&wc, buf, 0) == -1);
+ ATF_REQUIRE(wc == L'z');
+ ATF_REQUIRE(mbtowc(NULL, NULL, 0) == 0);
+
+ /* Incomplete character sequence (truncated double-byte). */
+ memset(buf, 0xcc, sizeof(buf));
+ buf[0] = 0xa3;
+ buf[1] = 0x00;
+ wc = L'z';
+ ATF_REQUIRE(mbtowc(&wc, buf, 1) == -1);
+ ATF_REQUIRE(wc == L'z');
+ ATF_REQUIRE(mbtowc(NULL, NULL, 0) == 0);
+
+ /* Same as above, but complete. */
+ buf[1] = 0xc1;
+ ATF_REQUIRE(mbtowc(&wc, buf, 2) == 2);
+ ATF_REQUIRE(wc == 0xa3c1);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, mbtowc_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/locale/towctrans_test.c b/lib/libc/tests/locale/towctrans_test.c
new file mode 100644
index 0000000..bb9d97c
--- /dev/null
+++ b/lib/libc/tests/locale/towctrans_test.c
@@ -0,0 +1,90 @@
+/*-
+ * Copyright (c) 2003 Tim J. Robbins
+ * 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.
+ */
+
+/*
+ * Test program for wctrans() and towctrans() as specified by
+ * IEEE Std. 1003.1-2001 and ISO/IEC 9899:1999.
+ *
+ * The functions are tested in the "C" and "ja_JP.eucJP" locales.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <locale.h>
+#include <stdio.h>
+#include <string.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include <atf-c.h>
+
+ATF_TC_WITHOUT_HEAD(towctrans_test);
+ATF_TC_BODY(towctrans_test, tc)
+{
+ wctype_t t;
+ int i, j;
+ struct {
+ const char *name;
+ wint_t (*func)(wint_t);
+ } tran[] = {
+ { "tolower", towlower },
+ { "toupper", towupper },
+ };
+
+ /* C/POSIX locale. */
+ for (i = 0; i < sizeof(tran) / sizeof(*tran); i++) {
+ t = wctrans(tran[i].name);
+ ATF_REQUIRE(t != 0);
+ for (j = 0; j < 256; j++)
+ ATF_REQUIRE(tran[i].func(j) == towctrans(j, t));
+ }
+ t = wctrans("elephant");
+ ATF_REQUIRE(t == 0);
+ for (i = 0; i < 256; i++)
+ ATF_REQUIRE(towctrans(i, t) == i);
+
+ /* Japanese (EUC) locale. */
+ ATF_REQUIRE(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0);
+ for (i = 0; i < sizeof(tran) / sizeof(*tran); i++) {
+ t = wctrans(tran[i].name);
+ ATF_REQUIRE(t != 0);
+ for (j = 0; j < 65536; j++)
+ ATF_REQUIRE(tran[i].func(j) == towctrans(j, t));
+ }
+ t = wctrans("elephant");
+ ATF_REQUIRE(t == 0);
+ for (i = 0; i < 65536; i++)
+ ATF_REQUIRE(towctrans(i, t) == i);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, towctrans_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/locale/wcrtomb_test.c b/lib/libc/tests/locale/wcrtomb_test.c
new file mode 100644
index 0000000..09199ba
--- /dev/null
+++ b/lib/libc/tests/locale/wcrtomb_test.c
@@ -0,0 +1,135 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * 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.
+ */
+
+/*
+ * Test program for wcrtomb(), as specified by IEEE Std. 1003.1-2001 and
+ * ISO/IEC 9899:1999.
+ *
+ * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and
+ * "ja_JP.eucJP". Other encodings are not tested.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include <atf-c.h>
+
+ATF_TC_WITHOUT_HEAD(wcrtomb_test);
+ATF_TC_BODY(wcrtomb_test, tc)
+{
+ mbstate_t s;
+ size_t len;
+ char buf[MB_LEN_MAX + 1];
+
+ /* C/POSIX locale. */
+
+ ATF_REQUIRE(MB_CUR_MAX == 1);
+
+ /*
+ * If the buffer argument is NULL, wc is implicitly L'\0',
+ * wcrtomb() resets its internal state.
+ */
+ ATF_REQUIRE(wcrtomb(NULL, L'\0', NULL) == 1);
+ ATF_REQUIRE(wcrtomb(NULL, UCHAR_MAX + 1, NULL) == 1);
+
+ /* Null wide character. */
+ memset(&s, 0, sizeof(s));
+ memset(buf, 0xcc, sizeof(buf));
+ len = wcrtomb(buf, L'\0', &s);
+ ATF_REQUIRE(len == 1);
+ ATF_REQUIRE((unsigned char)buf[0] == 0 && (unsigned char)buf[1] == 0xcc);
+
+ /* Latin letter A, internal state. */
+ ATF_REQUIRE(wcrtomb(NULL, L'\0', NULL) == 1);
+ ATF_REQUIRE(wcrtomb(NULL, L'A', NULL) == 1);
+
+ /* Latin letter A. */
+ memset(&s, 0, sizeof(s));
+ memset(buf, 0xcc, sizeof(buf));
+ len = wcrtomb(buf, L'A', &s);
+ ATF_REQUIRE(len == 1);
+ ATF_REQUIRE((unsigned char)buf[0] == 'A' && (unsigned char)buf[1] == 0xcc);
+
+ /* Invalid code. */
+ ATF_REQUIRE(wcrtomb(buf, UCHAR_MAX + 1, NULL) == (size_t)-1);
+ ATF_REQUIRE(errno == EILSEQ);
+
+ /*
+ * Japanese (EUC) locale.
+ */
+
+ ATF_REQUIRE(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0);
+ ATF_REQUIRE(MB_CUR_MAX == 3);
+
+ /*
+ * If the buffer argument is NULL, wc is implicitly L'\0',
+ * wcrtomb() resets its internal state.
+ */
+ ATF_REQUIRE(wcrtomb(NULL, L'\0', NULL) == 1);
+
+ /* Null wide character. */
+ memset(&s, 0, sizeof(s));
+ memset(buf, 0xcc, sizeof(buf));
+ len = wcrtomb(buf, L'\0', &s);
+ ATF_REQUIRE(len == 1);
+ ATF_REQUIRE((unsigned char)buf[0] == 0 && (unsigned char)buf[1] == 0xcc);
+
+ /* Latin letter A, internal state. */
+ ATF_REQUIRE(wcrtomb(NULL, L'\0', NULL) == 1);
+ ATF_REQUIRE(wcrtomb(NULL, L'A', NULL) == 1);
+
+ /* Latin letter A. */
+ memset(&s, 0, sizeof(s));
+ memset(buf, 0xcc, sizeof(buf));
+ len = wcrtomb(buf, L'A', &s);
+ ATF_REQUIRE(len == 1);
+ ATF_REQUIRE((unsigned char)buf[0] == 'A' && (unsigned char)buf[1] == 0xcc);
+
+ /* Full width letter A. */
+ memset(&s, 0, sizeof(s));
+ memset(buf, 0xcc, sizeof(buf));
+ len = wcrtomb(buf, 0xa3c1, &s);
+ ATF_REQUIRE(len == 2);
+ ATF_REQUIRE((unsigned char)buf[0] == 0xa3 &&
+ (unsigned char)buf[1] == 0xc1 &&
+ (unsigned char)buf[2] == 0xcc);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, wcrtomb_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/locale/wcsnrtombs_test.c b/lib/libc/tests/locale/wcsnrtombs_test.c
new file mode 100644
index 0000000..2e330a1
--- /dev/null
+++ b/lib/libc/tests/locale/wcsnrtombs_test.c
@@ -0,0 +1,195 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins
+ * 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.
+ */
+
+/*
+ * Test program for wcsnrtombs().
+ *
+ * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and
+ * "ja_JP.eucJP". Other encodings are not tested.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include <atf-c.h>
+
+ATF_TC_WITHOUT_HEAD(wcsnrtombs_test);
+ATF_TC_BODY(wcsnrtombs_test, tc)
+{
+ wchar_t srcbuf[128];
+ char dstbuf[128];
+ wchar_t *src;
+ mbstate_t s;
+
+ /* C/POSIX locale. */
+
+ /* Simple null terminated string. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(wcsnrtombs(dstbuf, (const wchar_t **)&src, 6, sizeof(dstbuf),
+ &s) == 5);
+ ATF_REQUIRE(strcmp(dstbuf, "hello") == 0);
+ ATF_REQUIRE((unsigned char)dstbuf[6] == 0xcc);
+ ATF_REQUIRE(src == NULL);
+
+ /* Simple null terminated string, stopping early. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(wcsnrtombs(dstbuf, (const wchar_t **)&src, 4, sizeof(dstbuf),
+ &s) == 4);
+ ATF_REQUIRE(memcmp(dstbuf, "hell", 4) == 0);
+ ATF_REQUIRE((unsigned char)dstbuf[5] == 0xcc);
+ ATF_REQUIRE(src == srcbuf + 4);
+
+ /* Not enough space in destination buffer. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(wcsnrtombs(dstbuf, (const wchar_t **)&src, 6, 4,
+ &s) == 4);
+ ATF_REQUIRE(memcmp(dstbuf, "hell", 4) == 0);
+ ATF_REQUIRE((unsigned char)dstbuf[5] == 0xcc);
+ ATF_REQUIRE(src == srcbuf + 4);
+
+ /* Null terminated string, internal dest. buffer */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(wcsnrtombs(NULL, (const wchar_t **)&src, 6, sizeof(dstbuf),
+ &s) == 5);
+
+ /* Null terminated string, internal dest. buffer, stopping early. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(wcsnrtombs(NULL, (const wchar_t **)&src, 4, sizeof(dstbuf),
+ &s) == 4);
+
+ /* Null terminated string, internal state. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ src = srcbuf;
+ ATF_REQUIRE(wcsnrtombs(dstbuf, (const wchar_t **)&src, 6, sizeof(dstbuf),
+ NULL) == 5);
+ ATF_REQUIRE(strcmp(dstbuf, "hello") == 0);
+ ATF_REQUIRE((unsigned char)dstbuf[6] == 0xcc);
+ ATF_REQUIRE(src == NULL);
+
+ /* Null terminated string, internal state, internal dest. buffer. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ src = srcbuf;
+ ATF_REQUIRE(wcsnrtombs(NULL, (const wchar_t **)&src, 6, 0, NULL) == 5);
+
+ /* Empty source buffer. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ srcbuf[0] = L'\0';
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(wcsnrtombs(dstbuf, (const wchar_t **)&src, 1, sizeof(dstbuf),
+ &s) == 0);
+ ATF_REQUIRE(dstbuf[0] == L'\0');
+
+ /* Zero length destination buffer. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(wcsnrtombs(dstbuf, (const wchar_t **)&src, 6, 0, &s) == 0);
+ ATF_REQUIRE((unsigned char)dstbuf[0] == 0xcc);
+
+ /* Zero length source buffer. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(wcsnrtombs(dstbuf, (const wchar_t **)&src, 0, sizeof(dstbuf),
+ &s) == 0);
+ ATF_REQUIRE((unsigned char)dstbuf[0] == 0xcc);
+ ATF_REQUIRE(src == srcbuf);
+
+ /*
+ * Japanese (EUC) locale.
+ */
+
+ ATF_REQUIRE(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0);
+ ATF_REQUIRE(MB_CUR_MAX > 1);
+
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ srcbuf[0] = 0xA3C1;
+ srcbuf[1] = 0x0020;
+ srcbuf[2] = 0x0042;
+ srcbuf[3] = 0x0020;
+ srcbuf[4] = 0xA3C3;
+ srcbuf[5] = 0x0000;
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(wcsnrtombs(dstbuf, (const wchar_t **)&src, 6, sizeof(dstbuf),
+ &s) == 7);
+ ATF_REQUIRE(strcmp(dstbuf, "\xA3\xC1 B \xA3\xC3") == 0);
+ ATF_REQUIRE((unsigned char)dstbuf[8] == 0xcc);
+ ATF_REQUIRE(src == NULL);
+
+ /* Stopping early. */
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(wcsnrtombs(dstbuf, (const wchar_t **)&src, 6, 6,
+ &s) == 5);
+ ATF_REQUIRE(memcmp(dstbuf, "\xA3\xC1 B ", 5) == 0);
+ ATF_REQUIRE((unsigned char)dstbuf[5] == 0xcc);
+ ATF_REQUIRE(src == srcbuf + 4);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, wcsnrtombs_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/locale/wcsrtombs_test.c b/lib/libc/tests/locale/wcsrtombs_test.c
new file mode 100644
index 0000000..4c3455a8
--- /dev/null
+++ b/lib/libc/tests/locale/wcsrtombs_test.c
@@ -0,0 +1,156 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * 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.
+ */
+
+/*
+ * Test program for wcsrtombs(), as specified by IEEE Std. 1003.1-2001 and
+ * ISO/IEC 9899:1999.
+ *
+ * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and
+ * "ja_JP.eucJP". Other encodings are not tested.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include <atf-c.h>
+
+ATF_TC_WITHOUT_HEAD(wcsrtombs_test);
+ATF_TC_BODY(wcsrtombs_test, tc)
+{
+ wchar_t srcbuf[128];
+ char dstbuf[128];
+ wchar_t *src;
+ mbstate_t s;
+
+ /* C/POSIX locale. */
+
+ /* Simple null terminated string. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(wcsrtombs(dstbuf, (const wchar_t **)&src, sizeof(dstbuf),
+ &s) == 5);
+ ATF_REQUIRE(strcmp(dstbuf, "hello") == 0);
+ ATF_REQUIRE((unsigned char)dstbuf[6] == 0xcc);
+ ATF_REQUIRE(src == NULL);
+
+ /* Not enough space in destination buffer. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(wcsrtombs(dstbuf, (const wchar_t **)&src, 4,
+ &s) == 4);
+ ATF_REQUIRE(memcmp(dstbuf, "hell", 4) == 0);
+ ATF_REQUIRE((unsigned char)dstbuf[5] == 0xcc);
+ ATF_REQUIRE(src == srcbuf + 4);
+
+ /* Null terminated string, internal dest. buffer */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(wcsrtombs(NULL, (const wchar_t **)&src, sizeof(dstbuf),
+ &s) == 5);
+
+ /* Null terminated string, internal state. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ src = srcbuf;
+ ATF_REQUIRE(wcsrtombs(dstbuf, (const wchar_t **)&src, sizeof(dstbuf),
+ NULL) == 5);
+ ATF_REQUIRE(strcmp(dstbuf, "hello") == 0);
+ ATF_REQUIRE((unsigned char)dstbuf[6] == 0xcc);
+ ATF_REQUIRE(src == NULL);
+
+ /* Null terminated string, internal state, internal dest. buffer. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ src = srcbuf;
+ ATF_REQUIRE(wcsrtombs(NULL, (const wchar_t **)&src, 0, NULL) == 5);
+
+ /* Empty source buffer. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ srcbuf[0] = L'\0';
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(wcsrtombs(dstbuf, (const wchar_t **)&src, sizeof(dstbuf),
+ &s) == 0);
+ ATF_REQUIRE(dstbuf[0] == L'\0');
+
+ /* Zero length destination buffer. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(wcsrtombs(dstbuf, (const wchar_t **)&src, 0, &s) == 0);
+ ATF_REQUIRE((unsigned char)dstbuf[0] == 0xcc);
+
+ /*
+ * Japanese (EUC) locale.
+ */
+
+ ATF_REQUIRE(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0);
+ ATF_REQUIRE(MB_CUR_MAX > 1);
+
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ srcbuf[0] = 0xA3C1;
+ srcbuf[1] = 0x0020;
+ srcbuf[2] = 0x0042;
+ srcbuf[3] = 0x0020;
+ srcbuf[4] = 0xA3C3;
+ srcbuf[5] = 0x0000;
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ src = srcbuf;
+ memset(&s, 0, sizeof(s));
+ ATF_REQUIRE(wcsrtombs(dstbuf, (const wchar_t **)&src, sizeof(dstbuf),
+ &s) == 7);
+ ATF_REQUIRE(strcmp(dstbuf, "\xA3\xC1 B \xA3\xC3") == 0);
+ ATF_REQUIRE((unsigned char)dstbuf[8] == 0xcc);
+ ATF_REQUIRE(src == NULL);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, wcsrtombs_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/locale/wcstombs_test.c b/lib/libc/tests/locale/wcstombs_test.c
new file mode 100644
index 0000000..f3fcd81
--- /dev/null
+++ b/lib/libc/tests/locale/wcstombs_test.c
@@ -0,0 +1,130 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * 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.
+ */
+
+/*
+ * Test program for wcstombs(), as specified by IEEE Std. 1003.1-2001 and
+ * ISO/IEC 9899:1999.
+ *
+ * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and
+ * "ja_JP.eucJP". Other encodings are not tested.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include <atf-c.h>
+
+ATF_TC_WITHOUT_HEAD(wcstombs_test);
+ATF_TC_BODY(wcstombs_test, tc)
+{
+ wchar_t srcbuf[128];
+ char dstbuf[128];
+
+ /* C/POSIX locale. */
+
+ /* Simple null terminated string. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ ATF_REQUIRE(wcstombs(dstbuf, srcbuf, sizeof(dstbuf)) == 5);
+ ATF_REQUIRE(strcmp(dstbuf, "hello") == 0);
+ ATF_REQUIRE((unsigned char)dstbuf[6] == 0xcc);
+
+ /* Not enough space in destination buffer. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ ATF_REQUIRE(wcstombs(dstbuf, srcbuf, 4) == 4);
+ ATF_REQUIRE(memcmp(dstbuf, "hell", 4) == 0);
+ ATF_REQUIRE((unsigned char)dstbuf[5] == 0xcc);
+
+ /* Null terminated string, internal dest. buffer */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ ATF_REQUIRE(wcstombs(NULL, srcbuf, sizeof(dstbuf)) == 5);
+
+ /* Null terminated string, internal state. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ ATF_REQUIRE(wcstombs(dstbuf, srcbuf, sizeof(dstbuf)) == 5);
+ ATF_REQUIRE(strcmp(dstbuf, "hello") == 0);
+ ATF_REQUIRE((unsigned char)dstbuf[6] == 0xcc);
+
+ /* Null terminated string, internal state, internal dest. buffer. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ ATF_REQUIRE(wcstombs(NULL, srcbuf, 0) == 5);
+
+ /* Empty source buffer. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ srcbuf[0] = L'\0';
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ ATF_REQUIRE(wcstombs(dstbuf, srcbuf, sizeof(dstbuf)) == 0);
+ ATF_REQUIRE(dstbuf[0] == L'\0');
+
+ /* Zero length destination buffer. */
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ wcscpy(srcbuf, L"hello");
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ ATF_REQUIRE(wcstombs(dstbuf, srcbuf, 0) == 0);
+ ATF_REQUIRE((unsigned char)dstbuf[0] == 0xcc);
+
+ /*
+ * Japanese (EUC) locale.
+ */
+
+ ATF_REQUIRE(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0);
+ ATF_REQUIRE(MB_CUR_MAX > 1);
+
+ wmemset(srcbuf, 0xcc, sizeof(srcbuf) / sizeof(*srcbuf));
+ srcbuf[0] = 0xA3C1;
+ srcbuf[1] = 0x0020;
+ srcbuf[2] = 0x0042;
+ srcbuf[3] = 0x0020;
+ srcbuf[4] = 0xA3C3;
+ srcbuf[5] = 0x0000;
+ memset(dstbuf, 0xcc, sizeof(dstbuf));
+ ATF_REQUIRE(wcstombs(dstbuf, srcbuf, sizeof(dstbuf)) == 7);
+ ATF_REQUIRE(strcmp(dstbuf, "\xA3\xC1 B \xA3\xC3") == 0);
+ ATF_REQUIRE((unsigned char)dstbuf[8] == 0xcc);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, wcstombs_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/locale/wctomb_test.c b/lib/libc/tests/locale/wctomb_test.c
new file mode 100644
index 0000000..255cda4
--- /dev/null
+++ b/lib/libc/tests/locale/wctomb_test.c
@@ -0,0 +1,113 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins
+ * 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.
+ */
+
+/*
+ * Test program for wctomb(), as specified by IEEE Std. 1003.1-2001 and
+ * ISO/IEC 9899:1999.
+ *
+ * The function is tested with both the "C" ("POSIX") LC_CTYPE setting and
+ * "ja_JP.eucJP". Other encodings are not tested.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <atf-c.h>
+
+ATF_TC_WITHOUT_HEAD(wctomb_test);
+ATF_TC_BODY(wctomb_test, tc)
+{
+ size_t len;
+ char buf[MB_LEN_MAX + 1];
+
+ /* C/POSIX locale. */
+
+ ATF_REQUIRE(MB_CUR_MAX == 1);
+
+ /* No shift states in C locale. */
+ ATF_REQUIRE(wctomb(NULL, L'\0') == 0);
+
+ /* Null wide character. */
+ memset(buf, 0xcc, sizeof(buf));
+ len = wctomb(buf, L'\0');
+ ATF_REQUIRE(len == 1);
+ ATF_REQUIRE((unsigned char)buf[0] == 0 && (unsigned char)buf[1] == 0xcc);
+
+ /* Latin letter A. */
+ memset(buf, 0xcc, sizeof(buf));
+ len = wctomb(buf, L'A');
+ ATF_REQUIRE(len == 1);
+ ATF_REQUIRE((unsigned char)buf[0] == 'A' && (unsigned char)buf[1] == 0xcc);
+
+ /* Invalid code. */
+ ATF_REQUIRE(wctomb(buf, UCHAR_MAX + 1) == -1);
+ ATF_REQUIRE(wctomb(NULL, 0) == 0);
+
+ /*
+ * Japanese (EUC) locale.
+ */
+
+ ATF_REQUIRE(strcmp(setlocale(LC_CTYPE, "ja_JP.eucJP"), "ja_JP.eucJP") == 0);
+ ATF_REQUIRE(MB_CUR_MAX == 3);
+
+ /* No shift states in EUC encoding. */
+ ATF_REQUIRE(wctomb(NULL, L'\0') == 0);
+
+ /* Null wide character. */
+ memset(buf, 0xcc, sizeof(buf));
+ len = wctomb(buf, L'\0');
+ ATF_REQUIRE(len == 1);
+ ATF_REQUIRE((unsigned char)buf[0] == 0 && (unsigned char)buf[1] == 0xcc);
+
+ /* Latin letter A. */
+ memset(buf, 0xcc, sizeof(buf));
+ len = wctomb(buf, L'A');
+ ATF_REQUIRE(len == 1);
+ ATF_REQUIRE((unsigned char)buf[0] == 'A' && (unsigned char)buf[1] == 0xcc);
+
+ /* Full width letter A. */
+ memset(buf, 0xcc, sizeof(buf));
+ len = wctomb(buf, 0xa3c1);
+ ATF_REQUIRE(len == 2);
+ ATF_REQUIRE((unsigned char)buf[0] == 0xa3 &&
+ (unsigned char)buf[1] == 0xc1 &&
+ (unsigned char)buf[2] == 0xcc);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, wctomb_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/net/Makefile b/lib/libc/tests/net/Makefile
index 5a0d775..8a4e932 100644
--- a/lib/libc/tests/net/Makefile
+++ b/lib/libc/tests/net/Makefile
@@ -1,22 +1,23 @@
# $FreeBSD$
-.include <bsd.own.mk>
+ATF_TESTS_C+= ether_test
+ATF_TESTS_C+= eui64_aton_test
+ATF_TESTS_C+= eui64_ntoa_test
-BINDIR= ${TESTSDIR}
+CFLAGS+= -I${.CURDIR}
-NETBSD_ATF_TESTS_C= getprotoent_test
+NETBSD_ATF_TESTS_C+= getprotoent_test
NETBSD_ATF_TESTS_C+= ether_aton_test
-SRCS.t_ether_aton= aton_ether_subr.c t_ether_aton.c
-
-aton_ether_subr.c: gen_ether_subr ${.CURDIR:H:H:H:H}/sys/net/if_ethersubr.c
- ${HOST_SH} ${.ALLSRC} ${.TARGET}
+SRCS.ether_aton_test= aton_ether_subr.c t_ether_aton.c
# TODO: hostent_test
NETBSD_ATF_TESTS_SH= nsdispatch_test
NETBSD_ATF_TESTS_SH+= protoent_test
NETBSD_ATF_TESTS_SH+= servent_test
+BINDIR= ${TESTSDIR}
+
PROGS= h_nsd_recurse
PROGS+= h_protoent
PROGS+= h_servent
@@ -26,12 +27,14 @@ DPADD.h_nsd_recurse+= ${LIBPTHREAD}
LDADD.h_nsd_recurse+= -lpthread
CLEANFILES+= aton_ether_subr.c
+aton_ether_subr.c: gen_ether_subr ${SRCTOP}/sys/net/if_ethersubr.c
+ ${HOST_SH} ${.ALLSRC} ${.TARGET}
.include "../Makefile.netbsd-tests"
# TODO: the testcases needs to be ported to FreeBSD
#TESTS_SUBDIRS= getaddrinfo
-FILES= hosts
+FILES+= hosts
FILES+= resolv.conf
.include <bsd.test.mk>
diff --git a/lib/libc/tests/net/ether_test.c b/lib/libc/tests/net/ether_test.c
new file mode 100644
index 0000000..fa8e484
--- /dev/null
+++ b/lib/libc/tests/net/ether_test.c
@@ -0,0 +1,192 @@
+/*-
+ * Copyright (c) 2007 Robert N. M. Watson
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+
+#include <net/ethernet.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <atf-c.h>
+
+static const char *ether_line_string = "01:23:45:67:89:ab ether_line_hostname";
+static const char *ether_line_hostname = "ether_line_hostname";
+static const struct ether_addr ether_line_addr = {
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab }
+};
+
+ATF_TC_WITHOUT_HEAD(ether_line);
+ATF_TC_BODY(ether_line, tc)
+{
+ struct ether_addr e;
+ char hostname[256];
+
+ ATF_REQUIRE_MSG(ether_line(ether_line_string, &e, hostname) == 0,
+ "ether_line failed; errno=%d", errno);
+ ATF_REQUIRE_MSG(bcmp(&e, &ether_line_addr, ETHER_ADDR_LEN) == 0,
+ "bad address");
+ ATF_REQUIRE_MSG(strcmp(hostname, ether_line_hostname) == 0,
+ "bad hostname");
+}
+
+static const char *ether_line_bad_1_string = "x";
+
+ATF_TC_WITHOUT_HEAD(ether_line_bad_1);
+ATF_TC_BODY(ether_line_bad_1, tc)
+{
+ struct ether_addr e;
+ char hostname[256];
+
+ ATF_REQUIRE_MSG(ether_line(ether_line_bad_1_string, &e, hostname) != 0,
+ "ether_line succeeded unexpectedly; errno=%d", errno);
+}
+
+static const char *ether_line_bad_2_string = "x x";
+
+ATF_TC_WITHOUT_HEAD(ether_line_bad_2);
+ATF_TC_BODY(ether_line_bad_2, tc)
+{
+ struct ether_addr e;
+ char hostname[256];
+
+ ATF_REQUIRE_MSG(ether_line(ether_line_bad_2_string, &e, hostname) != 0,
+ "ether_line succeeded unexpectedly; errno=%d", errno);
+}
+
+static const char *ether_aton_string = "01:23:45:67:89:ab";
+static const struct ether_addr ether_aton_addr = {
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab }
+};
+
+ATF_TC_WITHOUT_HEAD(ether_aton_r);
+ATF_TC_BODY(ether_aton_r, tc)
+{
+ struct ether_addr e, *ep;
+
+ ep = ether_aton_r(ether_aton_string, &e);
+
+ ATF_REQUIRE_MSG(ep != NULL, "ether_aton_r failed; errno=%d", errno);
+ ATF_REQUIRE_MSG(ep == &e,
+ "ether_aton_r returned different pointers; %p != %p", ep, &e);
+}
+
+static const char *ether_aton_bad_string = "x";
+
+ATF_TC_WITHOUT_HEAD(ether_aton_r_bad);
+ATF_TC_BODY(ether_aton_r_bad, tc)
+{
+ struct ether_addr e, *ep;
+
+ ep = ether_aton_r(ether_aton_bad_string, &e);
+ ATF_REQUIRE_MSG(ep == NULL, "ether_aton_r succeeded unexpectedly");
+}
+
+ATF_TC_WITHOUT_HEAD(ether_aton);
+ATF_TC_BODY(ether_aton, tc)
+{
+ struct ether_addr *ep;
+
+ ep = ether_aton(ether_aton_string);
+ ATF_REQUIRE_MSG(ep != NULL, "ether_aton failed");
+ ATF_REQUIRE_MSG(bcmp(ep, &ether_aton_addr, ETHER_ADDR_LEN) == 0,
+ "bad address");
+}
+
+ATF_TC_WITHOUT_HEAD(ether_aton_bad);
+ATF_TC_BODY(ether_aton_bad, tc)
+{
+ struct ether_addr *ep;
+
+ ep = ether_aton(ether_aton_bad_string);
+ ATF_REQUIRE_MSG(ep == NULL, "ether_aton succeeded unexpectedly");
+}
+
+static const char *ether_ntoa_string = "01:23:45:67:89:ab";
+static const struct ether_addr ether_ntoa_addr = {
+ { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab }
+};
+
+ATF_TC_WITHOUT_HEAD(ether_ntoa_r);
+ATF_TC_BODY(ether_ntoa_r, tc)
+{
+ char buf[256], *cp;
+
+ cp = ether_ntoa_r(&ether_ntoa_addr, buf);
+ ATF_REQUIRE_MSG(cp != NULL, "ether_ntoa_r failed");
+ ATF_REQUIRE_MSG(cp == buf,
+ "ether_ntoa_r returned a different pointer; %p != %p", cp, buf);
+ ATF_REQUIRE_MSG(strcmp(cp, ether_ntoa_string) == 0,
+ "strings did not match (`%s` != `%s`)", cp, ether_ntoa_string);
+}
+
+ATF_TC_WITHOUT_HEAD(ether_ntoa);
+ATF_TC_BODY(ether_ntoa, tc)
+{
+ char *cp;
+
+ cp = ether_ntoa(&ether_ntoa_addr);
+ ATF_REQUIRE_MSG(cp != NULL, "ether_ntoa failed");
+ ATF_REQUIRE_MSG(strcmp(cp, ether_ntoa_string) == 0,
+ "strings did not match (`%s` != `%s`)", cp, ether_ntoa_string);
+}
+
+#if 0
+ATF_TC_WITHOUT_HEAD(ether_ntohost);
+ATF_TC_BODY(ether_ntohost, tc)
+{
+
+}
+
+ATF_TC_WITHOUT_HEAD(ether_hostton);
+ATF_TC_BODY(ether_hostton, tc)
+{
+
+}
+#endif
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, ether_line);
+ ATF_TP_ADD_TC(tp, ether_line_bad_1);
+ ATF_TP_ADD_TC(tp, ether_line_bad_2);
+ ATF_TP_ADD_TC(tp, ether_aton_r);
+ ATF_TP_ADD_TC(tp, ether_aton_r_bad);
+ ATF_TP_ADD_TC(tp, ether_aton);
+ ATF_TP_ADD_TC(tp, ether_aton_bad);
+ ATF_TP_ADD_TC(tp, ether_ntoa_r);
+ ATF_TP_ADD_TC(tp, ether_ntoa);
+#if 0
+ ATF_TP_ADD_TC(tp, ether_ntohost);
+ ATF_TP_ADD_TC(tp, ether_hostton);
+#endif
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/net/eui64_aton_test.c b/lib/libc/tests/net/eui64_aton_test.c
new file mode 100644
index 0000000..7b97d7f
--- /dev/null
+++ b/lib/libc/tests/net/eui64_aton_test.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2004 The Aerospace Corporation. 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 Aerospace Corporation may not be used to endorse or
+ * promote products derived from this software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION "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 AEROSPACE CORPORATION 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$
+ */
+
+#include <sys/types.h>
+#include <sys/eui64.h>
+#include <locale.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <atf-c.h>
+
+#include "test-eui64.h"
+
+static void
+test_str(const char *str, const struct eui64 *eui)
+{
+ struct eui64 e;
+ char buf[EUI64_SIZ];
+ int rc;
+
+ ATF_REQUIRE_MSG(eui64_aton(str, &e) == 0, "eui64_aton failed");
+ rc = memcmp(&e, eui, sizeof(e));
+ if (rc != 0) {
+ eui64_ntoa(&e, buf, sizeof(buf));
+ atf_tc_fail(
+ "eui64_aton(\"%s\", ..) failed; memcmp returned %d. "
+ "String obtained form eui64_ntoa was: `%s`",
+ str, rc, buf);
+ }
+}
+
+ATF_TC_WITHOUT_HEAD(id_ascii);
+ATF_TC_BODY(id_ascii, tc)
+{
+
+ test_str(test_eui64_id_ascii, &test_eui64_id);
+}
+
+ATF_TC_WITHOUT_HEAD(id_colon_ascii);
+ATF_TC_BODY(id_colon_ascii, tc)
+{
+
+ test_str(test_eui64_id_colon_ascii, &test_eui64_id);
+}
+
+ATF_TC_WITHOUT_HEAD(mac_ascii);
+ATF_TC_BODY(mac_ascii, tc)
+{
+
+ test_str(test_eui64_mac_ascii, &test_eui64_eui48);
+}
+
+ATF_TC_WITHOUT_HEAD(mac_colon_ascii);
+ATF_TC_BODY(mac_colon_ascii, tc)
+{
+
+ test_str(test_eui64_mac_colon_ascii, &test_eui64_eui48);
+}
+
+ATF_TC_WITHOUT_HEAD(hex_ascii);
+ATF_TC_BODY(hex_ascii, tc)
+{
+
+ test_str(test_eui64_hex_ascii, &test_eui64_id);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, id_ascii);
+ ATF_TP_ADD_TC(tp, id_colon_ascii);
+ ATF_TP_ADD_TC(tp, mac_ascii);
+ ATF_TP_ADD_TC(tp, mac_colon_ascii);
+ ATF_TP_ADD_TC(tp, hex_ascii);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/net/eui64_ntoa_test.c b/lib/libc/tests/net/eui64_ntoa_test.c
new file mode 100644
index 0000000..4158e7a
--- /dev/null
+++ b/lib/libc/tests/net/eui64_ntoa_test.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2004 The Aerospace Corporation. 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 Aerospace Corporation may not be used to endorse or
+ * promote products derived from this software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION "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 AEROSPACE CORPORATION 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$
+ */
+
+#include <sys/types.h>
+#include <sys/eui64.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <atf-c.h>
+
+#include "test-eui64.h"
+
+static void
+test_str(const char *str, const struct eui64 *eui)
+{
+ char a[EUI64_SIZ];
+
+ ATF_REQUIRE_MSG(eui64_ntoa(&test_eui64_id, a, sizeof(a)) == 0,
+ "eui64_ntoa failed");
+ ATF_REQUIRE_MSG(strcmp(a, test_eui64_id_ascii) == 0,
+ "the strings mismatched: `%s` != `%s`", a, test_eui64_id_ascii);
+}
+
+ATF_TC_WITHOUT_HEAD(id_ascii);
+ATF_TC_BODY(id_ascii, tc)
+{
+
+ test_str(test_eui64_id_ascii, &test_eui64_id);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, id_ascii);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/net/test-eui64.h b/lib/libc/tests/net/test-eui64.h
new file mode 100644
index 0000000..ea82a10
--- /dev/null
+++ b/lib/libc/tests/net/test-eui64.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2004 The Aerospace Corporation. 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 Aerospace Corporation may not be used to endorse or
+ * promote products derived from this software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION "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 AEROSPACE CORPORATION 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$
+ */
+#ifndef _TEST_EUI64_H
+#define _TEST_EUI64_H
+
+struct eui64 test_eui64_id = {{0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77}};
+struct eui64 test_eui64_eui48 = {{0x00,0x11,0x22,0xFF,0xFE,0x33,0x44,0x55}};
+struct eui64 test_eui64_mac48 = {{0x00,0x11,0x22,0xFF,0xFF,0x33,0x44,0x55}};
+
+#define test_eui64_id_ascii "00-11-22-33-44-55-66-77"
+#define test_eui64_id_colon_ascii "00:11:22:33:44:55:66:77"
+#define test_eui64_hex_ascii "0x0011223344556677"
+#define test_eui64_eui48_ascii "00-11-22-ff-fe-33-44-55"
+#define test_eui64_mac48_ascii "00-11-22-ff-fe-33-44-55"
+#define test_eui64_mac_ascii "00-11-22-33-44-55"
+#define test_eui64_mac_colon_ascii "00:11:22:33:44:55"
+#define test_eui64_id_host "id"
+#define test_eui64_eui48_host "eui-48"
+#define test_eui64_mac48_host "mac-48"
+
+#define test_eui64_line_id "00-11-22-33-44-55-66-77 id"
+#define test_eui64_line_id_colon "00:11:22:33:44:55:66:77 id"
+#define test_eui64_line_eui48 "00-11-22-FF-fe-33-44-55 eui-48"
+#define test_eui64_line_mac48 "00-11-22-FF-ff-33-44-55 mac-48"
+#define test_eui64_line_eui48_6byte "00-11-22-33-44-55 eui-48"
+#define test_eui64_line_eui48_6byte_c "00:11:22:33:44:55 eui-48"
+
+#endif /* !_TEST_EUI64_H */
diff --git a/lib/libc/tests/setjmp/Makefile b/lib/libc/tests/setjmp/Makefile
index 0ca2577..ac962c2 100644
--- a/lib/libc/tests/setjmp/Makefile
+++ b/lib/libc/tests/setjmp/Makefile
@@ -1,10 +1,10 @@
# $FreeBSD$
-NETBSD_ATF_TESTS_C= t_setjmp
-NETBSD_ATF_TESTS_C+= t_threadjmp
+NETBSD_ATF_TESTS_C= setjmp_test
+NETBSD_ATF_TESTS_C+= threadjmp_test
-DPADD.t_threadjmp+= ${LIBPTHREAD}
-LDADD.t_threadjmp+= -lpthread
+DPADD.threadjmp_test+= ${LIBPTHREAD}
+LDADD.threadjmp_test+= -lpthread
WARNS?= 4
diff --git a/lib/libc/tests/ssp/Makefile b/lib/libc/tests/ssp/Makefile
index ec7a82a..dff1578 100644
--- a/lib/libc/tests/ssp/Makefile
+++ b/lib/libc/tests/ssp/Makefile
@@ -26,9 +26,19 @@ PROGS+= h_memmove
PROGS+= h_memset
# This testcase doesn't run properly when not compiled with -fsantize=bounds
# with clang, which is currently contingent on a compiler_rt update
-.if ${COMPILER_TYPE} == "clang" && ${COMPILER_VERSION} < 30500
+#
+# XXX: the h_raw/h_read testcases don't cause a SIGABRT with in-tree gcc right
+# now on amd64 when it trips the stack bounds specified in t_ssp.sh . This
+# probably needs to be fixed as it's currently hardcoded.
+#
+# sanitizer is not tested or supported for ARM right now. sbruno
+.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
+.if ${COMPILER_TYPE} == "clang"
+.if ${COMPILER_VERSION} < 30500 || 30700 <= ${COMPILER_VERSION}
PROGS+= h_raw
.endif
+.endif
+.endif
PROGS+= h_read
PROGS+= h_readlink
PROGS+= h_snprintf
diff --git a/lib/libc/tests/stdio/Makefile b/lib/libc/tests/stdio/Makefile
index f2d686b..7896422 100644
--- a/lib/libc/tests/stdio/Makefile
+++ b/lib/libc/tests/stdio/Makefile
@@ -1,6 +1,22 @@
# $FreeBSD$
-ATF_TESTS_C= fmemopen2_test
+.include <bsd.own.mk>
+
+ATF_TESTS_C+= fdopen_test
+ATF_TESTS_C+= fmemopen2_test
+ATF_TESTS_C+= fopen2_test
+ATF_TESTS_C+= freopen_test
+ATF_TESTS_C+= getdelim_test
+ATF_TESTS_C+= mkostemp_test
+ATF_TESTS_C+= open_memstream_test
+ATF_TESTS_C+= open_wmemstream_test
+ATF_TESTS_C+= perror_test
+ATF_TESTS_C+= print_positional_test
+ATF_TESTS_C+= printbasic_test
+ATF_TESTS_C+= printfloat_test
+ATF_TESTS_C+= scanfloat_test
+
+SRCS.fopen2_test= fopen_test.c
NETBSD_ATF_TESTS_C= clearerr_test
NETBSD_ATF_TESTS_C+= fflush_test
@@ -12,6 +28,18 @@ NETBSD_ATF_TESTS_C+= popen_test
NETBSD_ATF_TESTS_C+= printf_test
NETBSD_ATF_TESTS_C+= scanf_test
+DPADD.printfloat_test+= ${LIBM}
+LDADD.printfloat_test+= -lm
+
+DPADD.scanfloat_test+= ${LIBM}
+LDADD.scanfloat_test+= -lm
+
+.if ${COMPILER_TYPE} == "gcc"
+# 90: use of assignment suppression and length modifier together in scanf format
+PROG_OVERRIDE_VARS+= NO_WFORMAT
+NO_WFORMAT.scanfloat_test=
+.endif
+
.include "../Makefile.netbsd-tests"
.include <bsd.test.mk>
diff --git a/lib/libc/tests/stdio/fdopen_test.c b/lib/libc/tests/stdio/fdopen_test.c
new file mode 100644
index 0000000..060635a
--- /dev/null
+++ b/lib/libc/tests/stdio/fdopen_test.c
@@ -0,0 +1,225 @@
+/*-
+ * Copyright (c) 2014 Jilles Tjoelker
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <atf-c.h>
+
+static void
+runtest(const char *fname, int intmode, const char *strmode, bool success)
+{
+ FILE *fp;
+ int fd;
+
+ fd = open(fname, intmode);
+ ATF_REQUIRE_MSG(fd != -1,
+ "open(\"%s\", %#x) failed; errno=%d", fname, intmode, errno);
+
+ fp = fdopen(fd, strmode);
+ if (fp == NULL) {
+ close(fd);
+ ATF_REQUIRE_MSG(success == false,
+ "fdopen(open(\"%s\", %#x), \"%s\") succeeded unexpectedly",
+ fname, intmode, strmode);
+ return;
+ }
+ ATF_REQUIRE_MSG(success == true,
+ "fdopen(open(\"%s\", %#x), \"%s\") failed; errno=%d",
+ fname, intmode, strmode, errno);
+ fclose(fp);
+}
+
+ATF_TC_WITHOUT_HEAD(null__O_RDONLY__r_test);
+ATF_TC_BODY(null__O_RDONLY__r_test, tc)
+{
+
+ runtest(_PATH_DEVNULL, O_RDONLY, "r", true);
+}
+
+ATF_TC_WITHOUT_HEAD(null__O_WRONLY__r_test);
+ATF_TC_BODY(null__O_WRONLY__r_test, tc)
+{
+
+ runtest(_PATH_DEVNULL, O_WRONLY, "r", false);
+}
+
+ATF_TC_WITHOUT_HEAD(null__O_RDWR__r_test);
+ATF_TC_BODY(null__O_RDWR__r_test, tc)
+{
+
+ runtest(_PATH_DEVNULL, O_RDWR, "r", true);
+}
+
+ATF_TC_WITHOUT_HEAD(null__O_RDONLY__w_test);
+ATF_TC_BODY(null__O_RDONLY__w_test, tc)
+{
+
+ runtest(_PATH_DEVNULL, O_RDONLY, "w", false);
+}
+
+ATF_TC_WITHOUT_HEAD(null__O_WRONLY__w_test);
+ATF_TC_BODY(null__O_WRONLY__w_test, tc)
+{
+
+ runtest(_PATH_DEVNULL, O_WRONLY, "w", true);
+}
+
+ATF_TC_WITHOUT_HEAD(null__O_RDWR__w_test);
+ATF_TC_BODY(null__O_RDWR__w_test, tc)
+{
+
+ runtest(_PATH_DEVNULL, O_RDWR, "w", true);
+}
+
+ATF_TC_WITHOUT_HEAD(null__O_RDONLY__a_test);
+ATF_TC_BODY(null__O_RDONLY__a_test, tc)
+{
+
+ runtest(_PATH_DEVNULL, O_RDONLY, "a", false);
+}
+
+ATF_TC_WITHOUT_HEAD(null__O_WRONLY__a_test);
+ATF_TC_BODY(null__O_WRONLY__a_test, tc)
+{
+
+ runtest(_PATH_DEVNULL, O_WRONLY, "a", true);
+}
+
+ATF_TC_WITHOUT_HEAD(null__O_RDWR__test);
+ATF_TC_BODY(null__O_RDWR__test, tc)
+{
+
+ runtest(_PATH_DEVNULL, O_RDWR, "a", true);
+}
+
+ATF_TC_WITHOUT_HEAD(null__O_RDONLY__r_append);
+ATF_TC_BODY(null__O_RDONLY__r_append, tc)
+{
+
+ runtest(_PATH_DEVNULL, O_RDONLY, "r+", false);
+}
+
+ATF_TC_WITHOUT_HEAD(null__O_WRONLY__r_append);
+ATF_TC_BODY(null__O_WRONLY__r_append, tc)
+{
+
+ runtest(_PATH_DEVNULL, O_WRONLY, "r+", false);
+}
+
+ATF_TC_WITHOUT_HEAD(null__O_RDWR__r_append);
+ATF_TC_BODY(null__O_RDWR__r_append, tc)
+{
+
+ runtest(_PATH_DEVNULL, O_RDWR, "r+", true);
+}
+
+ATF_TC_WITHOUT_HEAD(null__O_RDONLY__w_append);
+ATF_TC_BODY(null__O_RDONLY__w_append, tc)
+{
+
+ runtest(_PATH_DEVNULL, O_RDONLY, "w+", false);
+}
+
+ATF_TC_WITHOUT_HEAD(null__O_WRONLY__w_append);
+ATF_TC_BODY(null__O_WRONLY__w_append, tc)
+{
+
+ runtest(_PATH_DEVNULL, O_WRONLY, "w+", false);
+}
+
+ATF_TC_WITHOUT_HEAD(null__O_RDWR__w_append);
+ATF_TC_BODY(null__O_RDWR__w_append, tc)
+{
+
+ runtest(_PATH_DEVNULL, O_RDWR, "w+", true);
+}
+
+ATF_TC_WITHOUT_HEAD(sh__O_EXEC__r);
+ATF_TC_BODY(sh__O_EXEC__r, tc)
+{
+
+ runtest("/bin/sh", O_EXEC, "r", false);
+}
+
+ATF_TC_WITHOUT_HEAD(sh__O_EXEC__w);
+ATF_TC_BODY(sh__O_EXEC__w, tc)
+{
+
+ runtest("/bin/sh", O_EXEC, "w", false);
+}
+
+ATF_TC_WITHOUT_HEAD(sh__O_EXEC__r_append);
+ATF_TC_BODY(sh__O_EXEC__r_append, tc)
+{
+
+ runtest("/bin/sh", O_EXEC, "r+", false);
+}
+
+ATF_TC_WITHOUT_HEAD(sh__O_EXEC__w_append);
+ATF_TC_BODY(sh__O_EXEC__w_append, tc)
+{
+
+ runtest("/bin/sh", O_EXEC, "w+", false);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, null__O_RDONLY__r_test);
+ ATF_TP_ADD_TC(tp, null__O_WRONLY__r_test);
+ ATF_TP_ADD_TC(tp, null__O_RDWR__r_test);
+ ATF_TP_ADD_TC(tp, null__O_RDONLY__w_test);
+ ATF_TP_ADD_TC(tp, null__O_WRONLY__w_test);
+ ATF_TP_ADD_TC(tp, null__O_RDWR__w_test);
+ ATF_TP_ADD_TC(tp, null__O_RDONLY__a_test);
+ ATF_TP_ADD_TC(tp, null__O_WRONLY__a_test);
+ ATF_TP_ADD_TC(tp, null__O_RDWR__test);
+ ATF_TP_ADD_TC(tp, null__O_RDONLY__r_append);
+ ATF_TP_ADD_TC(tp, null__O_WRONLY__r_append);
+ ATF_TP_ADD_TC(tp, null__O_RDWR__r_append);
+ ATF_TP_ADD_TC(tp, null__O_RDONLY__w_append);
+ ATF_TP_ADD_TC(tp, null__O_WRONLY__w_append);
+ ATF_TP_ADD_TC(tp, null__O_RDWR__w_append);
+ ATF_TP_ADD_TC(tp, sh__O_EXEC__r);
+ ATF_TP_ADD_TC(tp, sh__O_EXEC__w);
+ ATF_TP_ADD_TC(tp, sh__O_EXEC__r_append);
+ ATF_TP_ADD_TC(tp, sh__O_EXEC__w_append);
+
+ return (atf_no_error());
+}
+
+/*
+ vim:ts=8:cin:sw=8
+ */
diff --git a/lib/libc/tests/stdio/fmemopen2_test.c b/lib/libc/tests/stdio/fmemopen2_test.c
index 9555173..c3aa6c5 100644
--- a/lib/libc/tests/stdio/fmemopen2_test.c
+++ b/lib/libc/tests/stdio/fmemopen2_test.c
@@ -35,15 +35,13 @@ __FBSDID("$FreeBSD$");
#include <stdio.h>
#include <string.h>
#include <strings.h>
+
#include <atf-c.h>
ATF_TC_WITHOUT_HEAD(test_preexisting);
ATF_TC_BODY(test_preexisting, tc)
{
- /*
- * Use a pre-existing buffer.
- */
-
+ /* Use a pre-existing buffer. */
char buf[512];
char buf2[512];
char str[] = "Test writing some stuff";
@@ -74,7 +72,7 @@ ATF_TC_BODY(test_preexisting, tc)
nofr = fread(buf2, 1, sizeof(buf2), fp);
ATF_REQUIRE(nofr == sizeof(buf2));
- /*
+ /*
* Since a write on a FILE * retrieved by fmemopen
* will add a '\0' (if there's space), we can check
* the strings for equality.
@@ -106,14 +104,10 @@ ATF_TC_BODY(test_preexisting, tc)
ATF_TC_WITHOUT_HEAD(test_autoalloc);
ATF_TC_BODY(test_autoalloc, tc)
{
- /*
- * Let fmemopen allocate the buffer.
- */
-
- char str[] = "A quick test";
+ /* Let fmemopen allocate the buffer. */
FILE *fp;
long pos;
- size_t nofw, nofr, i;
+ size_t nofw, i;
int rc;
/* Open a FILE * using fmemopen. */
@@ -130,9 +124,7 @@ ATF_TC_BODY(test_autoalloc, tc)
pos = ftell(fp);
ATF_REQUIRE(pos == 512);
- /*
- * Try to write past the end, we should get a short object count (0)
- */
+ /* Try to write past the end, we should get a short object count (0) */
nofw = fwrite("a", 1, 1, fp);
ATF_REQUIRE(nofw == 0);
@@ -173,10 +165,7 @@ ATF_TC_BODY(test_data_length, tc)
nofw = fwrite(str, 1, sizeof(str), fp);
ATF_REQUIRE(nofw == sizeof(str));
- /*
- * Now seek to the end and check that ftell
- * gives us sizeof(str).
- */
+ /* Now seek to the end and check that ftell gives us sizeof(str). */
rc = fseek(fp, 0, SEEK_END);
ATF_REQUIRE(rc == 0);
pos = ftell(fp);
@@ -264,9 +253,7 @@ ATF_TC_BODY(test_append_binary_pos, tc)
ATF_REQUIRE(ftell(fp) == 0L);
fclose(fp);
- /*
- * Make sure that a pre-allocated buffer behaves correctly.
- */
+ /* Make sure that a pre-allocated buffer behaves correctly. */
char buf[] = "Hello";
fp = fmemopen(buf, sizeof(buf), "ab+");
ATF_REQUIRE(ftell(fp) == strlen(buf));
@@ -276,9 +263,7 @@ ATF_TC_BODY(test_append_binary_pos, tc)
ATF_TC_WITHOUT_HEAD(test_size_0);
ATF_TC_BODY(test_size_0, tc)
{
- /*
- * POSIX mandates that we return EINVAL if size is 0.
- */
+ /* POSIX mandates that we return EINVAL if size is 0. */
FILE *fp;
diff --git a/lib/libc/tests/stdio/fopen_test.c b/lib/libc/tests/stdio/fopen_test.c
new file mode 100644
index 0000000..962e7fd
--- /dev/null
+++ b/lib/libc/tests/stdio/fopen_test.c
@@ -0,0 +1,205 @@
+/*-
+ * Copyright (c) 2013 Jilles Tjoelker
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <fcntl.h>
+#include <paths.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <atf-c.h>
+
+/*
+ * O_ACCMODE is currently defined incorrectly. This is what it should be.
+ * Various code depends on the incorrect value.
+ */
+#define CORRECT_O_ACCMODE (O_ACCMODE | O_EXEC)
+
+static void
+runtest(const char *fname, const char *mode)
+{
+ FILE *fp;
+ int exp_fget_ret, fget_ret, fd, flags, wantedflags;
+
+ fp = fopen(fname, mode);
+ ATF_REQUIRE_MSG(fp != NULL,
+ "fopen(\"%s\", \"%s\") failed", fname, mode);
+ fd = fileno(fp);
+ ATF_REQUIRE_MSG(fd >= 0, "fileno() failed for fopen");
+ exp_fget_ret = strchr(mode, 'e') != NULL ? FD_CLOEXEC : 0;
+ ATF_REQUIRE_MSG((fget_ret = fcntl(fd, F_GETFD)) == exp_fget_ret,
+ "fcntl(.., F_GETFD) didn't FD_CLOEXEC as expected %d != %d",
+ exp_fget_ret, fget_ret);
+ flags = fcntl(fd, F_GETFL);
+ if (strchr(mode, '+'))
+ wantedflags = O_RDWR | (*mode == 'a' ? O_APPEND : 0);
+ else if (*mode == 'r')
+ wantedflags = O_RDONLY;
+ else if (*mode == 'w')
+ wantedflags = O_WRONLY;
+ else if (*mode == 'a')
+ wantedflags = O_WRONLY | O_APPEND;
+ else
+ wantedflags = -1;
+ fclose(fp);
+ if (wantedflags == -1)
+ atf_tc_fail("unrecognized mode: %s", mode);
+ else if ((flags & (CORRECT_O_ACCMODE | O_APPEND)) != wantedflags)
+ atf_tc_fail("incorrect access mode: %s", mode);
+}
+
+ATF_TC_WITHOUT_HEAD(fopen_r_test);
+ATF_TC_BODY(fopen_r_test, tc)
+{
+
+ runtest(_PATH_DEVNULL, "r");
+}
+
+ATF_TC_WITHOUT_HEAD(fopen_r_append_test);
+ATF_TC_BODY(fopen_r_append_test, tc)
+{
+
+ runtest(_PATH_DEVNULL, "r+");
+}
+
+ATF_TC_WITHOUT_HEAD(fopen_w_test);
+ATF_TC_BODY(fopen_w_test, tc)
+{
+
+ runtest(_PATH_DEVNULL, "w");
+}
+
+ATF_TC_WITHOUT_HEAD(fopen_w_append_test);
+ATF_TC_BODY(fopen_w_append_test, tc)
+{
+
+ runtest(_PATH_DEVNULL, "w+");
+}
+
+ATF_TC_WITHOUT_HEAD(fopen_a_test);
+ATF_TC_BODY(fopen_a_test, tc)
+{
+
+ runtest(_PATH_DEVNULL, "a");
+}
+
+ATF_TC_WITHOUT_HEAD(fopen_a_append_test);
+ATF_TC_BODY(fopen_a_append_test, tc)
+{
+
+ runtest(_PATH_DEVNULL, "a+");
+}
+
+ATF_TC_WITHOUT_HEAD(fopen_re_test);
+ATF_TC_BODY(fopen_re_test, tc)
+{
+
+ runtest(_PATH_DEVNULL, "re");
+}
+
+ATF_TC_WITHOUT_HEAD(fopen_r_append_e_test);
+ATF_TC_BODY(fopen_r_append_e_test, tc)
+{
+
+ runtest(_PATH_DEVNULL, "r+e");
+}
+
+ATF_TC_WITHOUT_HEAD(fopen_we_test);
+ATF_TC_BODY(fopen_we_test, tc)
+{
+
+ runtest(_PATH_DEVNULL, "we");
+}
+
+ATF_TC_WITHOUT_HEAD(fopen_w_append_e_test);
+ATF_TC_BODY(fopen_w_append_e_test, tc)
+{
+
+ runtest(_PATH_DEVNULL, "w+e");
+}
+
+ATF_TC_WITHOUT_HEAD(fopen_ae_test);
+ATF_TC_BODY(fopen_ae_test, tc)
+{
+
+ runtest(_PATH_DEVNULL, "ae");
+}
+
+ATF_TC_WITHOUT_HEAD(fopen_a_append_e_test);
+ATF_TC_BODY(fopen_a_append_e_test, tc)
+{
+
+ runtest(_PATH_DEVNULL, "a+e");
+}
+
+ATF_TC_WITHOUT_HEAD(fopen_re_append_test);
+ATF_TC_BODY(fopen_re_append_test, tc)
+{
+
+ runtest(_PATH_DEVNULL, "re+");
+}
+
+ATF_TC_WITHOUT_HEAD(fopen_we_append_test);
+ATF_TC_BODY(fopen_we_append_test, tc)
+{
+
+ runtest(_PATH_DEVNULL, "we+");
+}
+
+ATF_TC_WITHOUT_HEAD(fopen_ae_append_test);
+ATF_TC_BODY(fopen_ae_append_test, tc)
+{
+
+ runtest(_PATH_DEVNULL, "ae+");
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, fopen_r_test);
+ ATF_TP_ADD_TC(tp, fopen_r_append_test);
+ ATF_TP_ADD_TC(tp, fopen_w_test);
+ ATF_TP_ADD_TC(tp, fopen_w_append_test);
+ ATF_TP_ADD_TC(tp, fopen_a_test);
+ ATF_TP_ADD_TC(tp, fopen_a_append_test);
+ ATF_TP_ADD_TC(tp, fopen_re_test);
+ ATF_TP_ADD_TC(tp, fopen_r_append_e_test);
+ ATF_TP_ADD_TC(tp, fopen_we_test);
+ ATF_TP_ADD_TC(tp, fopen_w_append_e_test);
+ ATF_TP_ADD_TC(tp, fopen_ae_test);
+ ATF_TP_ADD_TC(tp, fopen_a_append_e_test);
+ ATF_TP_ADD_TC(tp, fopen_re_append_test);
+ ATF_TP_ADD_TC(tp, fopen_we_append_test);
+ ATF_TP_ADD_TC(tp, fopen_ae_append_test);
+
+ return (atf_no_error());
+}
+
+/*
+ vim:ts=8:cin:sw=8
+ */
diff --git a/lib/libc/tests/stdio/freopen_test.c b/lib/libc/tests/stdio/freopen_test.c
new file mode 100644
index 0000000..1719927
--- /dev/null
+++ b/lib/libc/tests/stdio/freopen_test.c
@@ -0,0 +1,224 @@
+/*-
+ * Copyright (c) 2014 Jilles Tjoelker
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <paths.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <atf-c.h>
+
+static void
+runtest(const char *fname1, const char *mode1, const char *fname2,
+ const char *mode2, bool success)
+{
+ FILE *fp1, *fp2;
+ const char *fname2_print;
+
+ fname2_print = fname2 != NULL ? fname2 : "<NULL>";
+ fp1 = fopen(fname1, mode1);
+ ATF_REQUIRE_MSG(fp1 != NULL,
+ "fopen(\"%s\", \"%s\") failed; errno=%d", fname1, mode1, errno);
+ fp2 = freopen(fname2, mode2, fp1);
+ if (fp2 == NULL) {
+ fclose(fp1);
+ ATF_REQUIRE_MSG(success == false,
+ "freopen(\"%s\", \"%s\", fopen(\"%s\", \"%s\")) succeeded "
+ "unexpectedly", fname2_print, mode2, fname1, mode1);
+ return;
+ }
+ ATF_REQUIRE_MSG(success == true,
+ "freopen(\"%s\", \"%s\", fopen(\"%s\", \"%s\")) failed: %d",
+ fname2_print, mode2, fname1, mode1, errno);
+ fclose(fp2);
+}
+
+ATF_TC_WITHOUT_HEAD(null__r__r__test);
+ATF_TC_BODY(null__r__r__test, tc)
+{
+
+ runtest(_PATH_DEVNULL, "r", NULL, "r", true);
+}
+
+ATF_TC_WITHOUT_HEAD(null__w__r__test);
+ATF_TC_BODY(null__w__r__test, tc)
+{
+
+ runtest(_PATH_DEVNULL, "w", NULL, "r", false);
+}
+
+ATF_TC_WITHOUT_HEAD(null__r_append__r__test);
+ATF_TC_BODY(null__r_append__r__test, tc)
+{
+
+ runtest(_PATH_DEVNULL, "r+", NULL, "r", true);
+}
+
+ATF_TC_WITHOUT_HEAD(null__r__w__test);
+ATF_TC_BODY(null__r__w__test, tc)
+{
+
+ runtest(_PATH_DEVNULL, "r", NULL, "w", false);
+}
+
+ATF_TC_WITHOUT_HEAD(null__w__w__test);
+ATF_TC_BODY(null__w__w__test, tc)
+{
+
+ runtest(_PATH_DEVNULL, "w", NULL, "w", true);
+}
+
+ATF_TC_WITHOUT_HEAD(null__r_append__w__test);
+ATF_TC_BODY(null__r_append__w__test, tc)
+{
+
+ runtest(_PATH_DEVNULL, "r+", NULL, "w", true);
+}
+
+ATF_TC_WITHOUT_HEAD(null__r__a__test);
+ATF_TC_BODY(null__r__a__test, tc)
+{
+
+ runtest(_PATH_DEVNULL, "r", NULL, "a", false);
+}
+
+ATF_TC_WITHOUT_HEAD(null__w__a__test);
+ATF_TC_BODY(null__w__a__test, tc)
+{
+
+ runtest(_PATH_DEVNULL, "w", NULL, "a", true);
+}
+
+ATF_TC_WITHOUT_HEAD(null__r_append__a__test);
+ATF_TC_BODY(null__r_append__a__test, tc)
+{
+
+ runtest(_PATH_DEVNULL, "r+", NULL, "a", true);
+}
+
+ATF_TC_WITHOUT_HEAD(null__r__r_append__test);
+ATF_TC_BODY(null__r__r_append__test, tc)
+{
+
+ runtest(_PATH_DEVNULL, "r", NULL, "r+", false);
+}
+
+ATF_TC_WITHOUT_HEAD(null__w__r_append__test);
+ATF_TC_BODY(null__w__r_append__test, tc)
+{
+
+ runtest(_PATH_DEVNULL, "w", NULL, "r+", false);
+}
+
+ATF_TC_WITHOUT_HEAD(null__r_append__r_append__test);
+ATF_TC_BODY(null__r_append__r_append__test, tc)
+{
+
+ runtest(_PATH_DEVNULL, "r+", NULL, "r+", true);
+}
+
+ATF_TC_WITHOUT_HEAD(null__r__w_append__test);
+ATF_TC_BODY(null__r__w_append__test, tc)
+{
+
+ runtest(_PATH_DEVNULL, "r", NULL, "w+", false);
+}
+
+ATF_TC_WITHOUT_HEAD(null__w__w_append__test);
+ATF_TC_BODY(null__w__w_append__test, tc)
+{
+
+ runtest(_PATH_DEVNULL, "w", NULL, "w+", false);
+}
+
+ATF_TC_WITHOUT_HEAD(null__r_append__w_append__test);
+ATF_TC_BODY(null__r_append__w_append__test, tc)
+{
+
+ runtest(_PATH_DEVNULL, "r+", NULL, "w+", true);
+}
+
+ATF_TC_WITHOUT_HEAD(sh__r__r__test);
+ATF_TC_BODY(sh__r__r__test, tc)
+{
+
+ runtest("/bin/sh", "r", NULL, "r", true);
+}
+
+ATF_TC_WITHOUT_HEAD(sh__sh__r__r__test);
+ATF_TC_BODY(sh__sh__r__r__test, tc)
+{
+
+ runtest("/bin/sh", "r", "/bin/sh", "r", true);
+}
+
+ATF_TC_WITHOUT_HEAD(sh__null__r__r__test);
+ATF_TC_BODY(sh__null__r__r__test, tc)
+{
+
+ runtest("/bin/sh", "r", _PATH_DEVNULL, "r", true);
+}
+
+ATF_TC_WITHOUT_HEAD(sh__null__r__w__test);
+ATF_TC_BODY(sh__null__r__w__test, tc)
+{
+
+ runtest("/bin/sh", "r", _PATH_DEVNULL, "w", true);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, null__r__r__test);
+ ATF_TP_ADD_TC(tp, null__w__r__test);
+ ATF_TP_ADD_TC(tp, null__r_append__r__test);
+ ATF_TP_ADD_TC(tp, null__r__w__test);
+ ATF_TP_ADD_TC(tp, null__w__w__test);
+ ATF_TP_ADD_TC(tp, null__r_append__w__test);
+ ATF_TP_ADD_TC(tp, null__r__a__test);
+ ATF_TP_ADD_TC(tp, null__w__a__test);
+ ATF_TP_ADD_TC(tp, null__r_append__a__test);
+ ATF_TP_ADD_TC(tp, null__r__r_append__test);
+ ATF_TP_ADD_TC(tp, null__w__r_append__test);
+ ATF_TP_ADD_TC(tp, null__r_append__r_append__test);
+ ATF_TP_ADD_TC(tp, null__r__w_append__test);
+ ATF_TP_ADD_TC(tp, null__w__w_append__test);
+ ATF_TP_ADD_TC(tp, null__r_append__w_append__test);
+ ATF_TP_ADD_TC(tp, sh__r__r__test);
+ ATF_TP_ADD_TC(tp, sh__sh__r__r__test);
+ ATF_TP_ADD_TC(tp, sh__null__r__r__test);
+ ATF_TP_ADD_TC(tp, sh__null__r__w__test);
+
+ return (atf_no_error());
+}
+
+/*
+ vim:ts=8:cin:sw=8
+ */
diff --git a/lib/libc/tests/stdio/getdelim_test.c b/lib/libc/tests/stdio/getdelim_test.c
new file mode 100644
index 0000000..ffc6810
--- /dev/null
+++ b/lib/libc/tests/stdio/getdelim_test.c
@@ -0,0 +1,236 @@
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define _WITH_GETLINE
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <atf-c.h>
+
+#define CHUNK_MAX 10
+
+/* The assertions depend on this string. */
+char apothegm[] = "All work and no play\0 makes Jack a dull boy.\n";
+
+/*
+ * This is a neurotic reader function designed to give getdelim() a
+ * hard time. It reads through the string `apothegm' and returns a
+ * random number of bytes up to the requested length.
+ */
+static int
+_reader(void *cookie, char *buf, int len)
+{
+ size_t *offp = cookie;
+ size_t r;
+
+ r = random() % CHUNK_MAX + 1;
+ if (len > r)
+ len = r;
+ if (len > sizeof(apothegm) - *offp)
+ len = sizeof(apothegm) - *offp;
+ memcpy(buf, apothegm + *offp, len);
+ *offp += len;
+ return (len);
+}
+
+static FILE *
+mkfilebuf(void)
+{
+ size_t *offp;
+
+ offp = malloc(sizeof(*offp)); /* XXX leak */
+ *offp = 0;
+ return (fropen(offp, _reader));
+}
+
+ATF_TC_WITHOUT_HEAD(getline_basic);
+ATF_TC_BODY(getline_basic, tc)
+{
+ FILE *fp;
+ char *line;
+ size_t linecap;
+ int i;
+
+ srandom(0);
+
+ /*
+ * Test multiple times with different buffer sizes
+ * and different _reader() return values.
+ */
+ errno = 0;
+ for (i = 0; i < 8; i++) {
+ fp = mkfilebuf();
+ linecap = i;
+ line = malloc(i);
+ /* First line: the full apothegm */
+ ATF_REQUIRE(getline(&line, &linecap, fp) == sizeof(apothegm) - 1);
+ ATF_REQUIRE(memcmp(line, apothegm, sizeof(apothegm)) == 0);
+ ATF_REQUIRE(linecap >= sizeof(apothegm));
+ /* Second line: the NUL terminator following the newline */
+ ATF_REQUIRE(getline(&line, &linecap, fp) == 1);
+ ATF_REQUIRE(line[0] == '\0' && line[1] == '\0');
+ /* Third line: EOF */
+ line[0] = 'X';
+ ATF_REQUIRE(getline(&line, &linecap, fp) == -1);
+ ATF_REQUIRE(line[0] == '\0');
+ free(line);
+ line = NULL;
+ ATF_REQUIRE(feof(fp));
+ ATF_REQUIRE(!ferror(fp));
+ fclose(fp);
+ }
+ ATF_REQUIRE(errno == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(stream_error);
+ATF_TC_BODY(stream_error, tc)
+{
+ char *line;
+ size_t linecap;
+
+ /* Make sure read errors are handled properly. */
+ line = NULL;
+ linecap = 0;
+ errno = 0;
+ ATF_REQUIRE(getline(&line, &linecap, stdout) == -1);
+ ATF_REQUIRE(errno == EBADF);
+ errno = 0;
+ ATF_REQUIRE(getdelim(&line, &linecap, 'X', stdout) == -1);
+ ATF_REQUIRE(errno == EBADF);
+ ATF_REQUIRE(ferror(stdout));
+}
+
+ATF_TC_WITHOUT_HEAD(invalid_params);
+ATF_TC_BODY(invalid_params, tc)
+{
+ FILE *fp;
+ char *line;
+ size_t linecap;
+
+ /* Make sure NULL linep or linecapp pointers are handled. */
+ fp = mkfilebuf();
+ ATF_REQUIRE(getline(NULL, &linecap, fp) == -1);
+ ATF_REQUIRE(errno == EINVAL);
+ ATF_REQUIRE(getline(&line, NULL, fp) == -1);
+ ATF_REQUIRE(errno == EINVAL);
+ ATF_REQUIRE(ferror(fp));
+ fclose(fp);
+}
+
+ATF_TC_WITHOUT_HEAD(eof);
+ATF_TC_BODY(eof, tc)
+{
+ FILE *fp;
+ char *line;
+ size_t linecap;
+
+ /* Make sure getline() allocates memory as needed if fp is at EOF. */
+ errno = 0;
+ fp = mkfilebuf();
+ while (!feof(fp)) /* advance to EOF; can't fseek this stream */
+ getc(fp);
+ line = NULL;
+ linecap = 0;
+ printf("getline\n");
+ ATF_REQUIRE(getline(&line, &linecap, fp) == -1);
+ ATF_REQUIRE(line[0] == '\0');
+ ATF_REQUIRE(linecap > 0);
+ ATF_REQUIRE(errno == 0);
+ printf("feof\n");
+ ATF_REQUIRE(feof(fp));
+ ATF_REQUIRE(!ferror(fp));
+ fclose(fp);
+}
+
+ATF_TC_WITHOUT_HEAD(nul);
+ATF_TC_BODY(nul, tc)
+{
+ FILE *fp;
+ char *line;
+ size_t linecap, n;
+
+ line = NULL;
+ linecap = 0;
+ /* Make sure a NUL delimiter works. */
+ fp = mkfilebuf();
+ n = strlen(apothegm);
+ printf("getdelim\n");
+ ATF_REQUIRE(getdelim(&line, &linecap, '\0', fp) == n + 1);
+ ATF_REQUIRE(strcmp(line, apothegm) == 0);
+ ATF_REQUIRE(line[n + 1] == '\0');
+ ATF_REQUIRE(linecap > n + 1);
+ n = strlen(apothegm + n + 1);
+ printf("getdelim 2\n");
+ ATF_REQUIRE(getdelim(&line, &linecap, '\0', fp) == n + 1);
+ ATF_REQUIRE(line[n + 1] == '\0');
+ ATF_REQUIRE(linecap > n + 1);
+ ATF_REQUIRE(errno == 0);
+ ATF_REQUIRE(!ferror(fp));
+ fclose(fp);
+}
+
+ATF_TC_WITHOUT_HEAD(empty_NULL_buffer);
+ATF_TC_BODY(empty_NULL_buffer, tc)
+{
+ FILE *fp;
+ char *line;
+ size_t linecap;
+
+ /* Make sure NULL *linep and zero *linecapp are handled. */
+ fp = mkfilebuf();
+ free(line);
+ line = NULL;
+ linecap = 42;
+ ATF_REQUIRE(getline(&line, &linecap, fp) == sizeof(apothegm) - 1);
+ ATF_REQUIRE(memcmp(line, apothegm, sizeof(apothegm)) == 0);
+ fp = mkfilebuf();
+ free(line);
+ line = malloc(100);
+ linecap = 0;
+ ATF_REQUIRE(getline(&line, &linecap, fp) == sizeof(apothegm) - 1);
+ ATF_REQUIRE(memcmp(line, apothegm, sizeof(apothegm)) == 0);
+ free(line);
+ ATF_REQUIRE(!ferror(fp));
+ fclose(fp);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, getline_basic);
+ ATF_TP_ADD_TC(tp, stream_error);
+ ATF_TP_ADD_TC(tp, eof);
+ ATF_TP_ADD_TC(tp, invalid_params);
+ ATF_TP_ADD_TC(tp, nul);
+ ATF_TP_ADD_TC(tp, empty_NULL_buffer);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/stdio/mkostemp_test.c b/lib/libc/tests/stdio/mkostemp_test.c
new file mode 100644
index 0000000..0dd475b
--- /dev/null
+++ b/lib/libc/tests/stdio/mkostemp_test.c
@@ -0,0 +1,185 @@
+/*-
+ * Copyright (c) 2013 Jilles Tjoelker
+ * 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.
+ */
+
+/*
+ * Test program for mkostemp().
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <atf-c.h>
+
+static const char template[] = "mkostemp.XXXXXXXX";
+static int testnum;
+
+#define MISCFLAGS (O_APPEND | O_DIRECT | O_SHLOCK | O_EXLOCK | O_SYNC)
+
+static void
+test_one(int oflags)
+{
+ char tmpf[sizeof(template)];
+ struct stat st1, st2;
+ int fd;
+
+ memcpy(tmpf, template, sizeof(tmpf));
+ fd = mkostemp(tmpf, oflags);
+ if (fd < 0) {
+ printf("not ok %d - oflags=%#x "
+ "mkostemp() reported failure: %s\n",
+ testnum++, oflags, strerror(errno));
+ return;
+ }
+ if (memcmp(tmpf, template, sizeof(tmpf) - 8 - 1) != 0) {
+ printf("not ok %d - oflags=%#x "
+ "returned pathname does not match template: %s\n",
+ testnum++, oflags, tmpf);
+ return;
+ }
+ do {
+ if (fcntl(fd, F_GETFD) !=
+ (oflags & O_CLOEXEC ? FD_CLOEXEC : 0)) {
+ printf("not ok %d - oflags=%#x "
+ "close-on-exec flag incorrect\n",
+ testnum++, oflags);
+ break;
+ }
+ if ((fcntl(fd, F_GETFL) & MISCFLAGS) != (oflags & MISCFLAGS)) {
+ printf("not ok %d - oflags=%#x "
+ "open flags incorrect\n",
+ testnum++, oflags);
+ break;
+ }
+ if (stat(tmpf, &st1) == -1) {
+ printf("not ok %d - oflags=%#x "
+ "cannot stat returned pathname %s: %s\n",
+ testnum++, oflags, tmpf, strerror(errno));
+ break;
+ }
+ if (fstat(fd, &st2) == -1) {
+ printf("not ok %d - oflags=%#x "
+ "cannot fstat returned fd %d: %s\n",
+ testnum++, oflags, fd, strerror(errno));
+ break;
+ }
+ if (!S_ISREG(st1.st_mode) || (st1.st_mode & 0777) != 0600 ||
+ st1.st_nlink != 1 || st1.st_size != 0) {
+ printf("not ok %d - oflags=%#x "
+ "named file attributes incorrect\n",
+ testnum++, oflags);
+ break;
+ }
+ if (!S_ISREG(st2.st_mode) || (st2.st_mode & 0777) != 0600 ||
+ st2.st_nlink != 1 || st2.st_size != 0) {
+ printf("not ok %d - oflags=%#x "
+ "opened file attributes incorrect\n",
+ testnum++, oflags);
+ break;
+ }
+ if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) {
+ printf("not ok %d - oflags=%#x "
+ "named and opened file do not match\n",
+ testnum++, oflags);
+ break;
+ }
+ (void)unlink(tmpf);
+ if (fstat(fd, &st2) == -1)
+ printf("not ok %d - oflags=%#x "
+ "cannot fstat returned fd %d again: %s\n",
+ testnum++, oflags, fd, strerror(errno));
+ else if (st2.st_nlink != 0)
+ printf("not ok %d - oflags=%#x "
+ "st_nlink is not 0 after unlink\n",
+ testnum++, oflags);
+ else
+ printf("ok %d - oflags=%#x\n", testnum++, oflags);
+ (void)close(fd);
+ return;
+ } while (0);
+ (void)close(fd);
+ (void)unlink(tmpf);
+}
+
+ATF_TC_WITHOUT_HEAD(zero);
+ATF_TC_BODY(zero, tc)
+{
+
+ test_one(0);
+}
+
+ATF_TC_WITHOUT_HEAD(O_CLOEXEC);
+ATF_TC_BODY(O_CLOEXEC, tc)
+{
+
+ test_one(O_CLOEXEC);
+}
+
+ATF_TC_WITHOUT_HEAD(O_APPEND);
+ATF_TC_BODY(O_APPEND, tc)
+{
+
+ test_one(O_APPEND);
+}
+
+ATF_TC_WITHOUT_HEAD(O_APPEND__O_CLOEXEC);
+ATF_TC_BODY(O_APPEND__O_CLOEXEC, tc)
+{
+
+ test_one(O_APPEND|O_CLOEXEC);
+}
+
+ATF_TC_WITHOUT_HEAD(bad_flags);
+ATF_TC_BODY(bad_flags, tc)
+{
+
+ char tmpf[sizeof(template)];
+
+ memcpy(tmpf, template, sizeof(tmpf));
+ ATF_REQUIRE_MSG(mkostemp(tmpf, O_CREAT) == -1,
+ "mkostemp(O_CREAT) succeeded unexpectedly");
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, zero);
+ ATF_TP_ADD_TC(tp, O_CLOEXEC);
+ ATF_TP_ADD_TC(tp, O_APPEND);
+ ATF_TP_ADD_TC(tp, O_APPEND__O_CLOEXEC);
+ ATF_TP_ADD_TC(tp, bad_flags);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/stdio/open_memstream_test.c b/lib/libc/tests/stdio/open_memstream_test.c
new file mode 100644
index 0000000..3c9e3ec
--- /dev/null
+++ b/lib/libc/tests/stdio/open_memstream_test.c
@@ -0,0 +1,201 @@
+/*-
+ * Copyright (c) 2013 Hudson River Trading LLC
+ * Written by: John H. Baldwin <jhb@FreeBSD.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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include <atf-c.h>
+
+static char *buf;
+static size_t len;
+
+static void
+assert_stream(const char *contents)
+{
+ if (strlen(contents) != len)
+ printf("bad length %zd for \"%s\"\n", len, contents);
+ else if (strncmp(buf, contents, strlen(contents)) != 0)
+ printf("bad buffer \"%s\" for \"%s\"\n", buf, contents);
+}
+
+ATF_TC_WITHOUT_HEAD(open_group_test);
+ATF_TC_BODY(open_group_test, tc)
+{
+ FILE *fp;
+ off_t eob;
+
+ fp = open_memstream(&buf, &len);
+ ATF_REQUIRE_MSG(fp != NULL, "open_memstream failed");
+
+ fprintf(fp, "hello my world");
+ fflush(fp);
+ assert_stream("hello my world");
+ eob = ftello(fp);
+ rewind(fp);
+ fprintf(fp, "good-bye");
+ fseeko(fp, eob, SEEK_SET);
+ fclose(fp);
+ assert_stream("good-bye world");
+ free(buf);
+}
+
+ATF_TC_WITHOUT_HEAD(simple_tests);
+ATF_TC_BODY(simple_tests, tc)
+{
+ static const char zerobuf[] =
+ { 'f', 'o', 'o', 0, 0, 0, 0, 'b', 'a', 'r', 0 };
+ char c;
+ FILE *fp;
+
+ fp = open_memstream(&buf, NULL);
+ ATF_REQUIRE_MSG(fp == NULL, "open_memstream did not fail");
+ ATF_REQUIRE_MSG(errno == EINVAL,
+ "open_memstream didn't fail with EINVAL");
+ fp = open_memstream(NULL, &len);
+ ATF_REQUIRE_MSG(fp == NULL, "open_memstream did not fail");
+ ATF_REQUIRE_MSG(errno == EINVAL,
+ "open_memstream didn't fail with EINVAL");
+ fp = open_memstream(&buf, &len);
+ ATF_REQUIRE_MSG(fp != NULL, "open_memstream failed; errno=%d", errno);
+ fflush(fp);
+ assert_stream("");
+ if (fwide(fp, 0) >= 0)
+ printf("stream is not byte-oriented\n");
+
+ fprintf(fp, "fo");
+ fflush(fp);
+ assert_stream("fo");
+ fputc('o', fp);
+ fflush(fp);
+ assert_stream("foo");
+ rewind(fp);
+ fflush(fp);
+ assert_stream("");
+ fseek(fp, 0, SEEK_END);
+ fflush(fp);
+ assert_stream("foo");
+
+ /*
+ * Test seeking out past the current end. Should zero-fill the
+ * intermediate area.
+ */
+ fseek(fp, 4, SEEK_END);
+ fprintf(fp, "bar");
+ fflush(fp);
+
+ /*
+ * Can't use assert_stream() here since this should contain
+ * embedded null characters.
+ */
+ if (len != 10)
+ printf("bad length %zd for zero-fill test\n", len);
+ else if (memcmp(buf, zerobuf, sizeof(zerobuf)) != 0)
+ printf("bad buffer for zero-fill test\n");
+
+ fseek(fp, 3, SEEK_SET);
+ fprintf(fp, " in ");
+ fflush(fp);
+ assert_stream("foo in ");
+ fseek(fp, 0, SEEK_END);
+ fflush(fp);
+ assert_stream("foo in bar");
+
+ rewind(fp);
+ if (fread(&c, sizeof(c), 1, fp) != 0)
+ printf("fread did not fail\n");
+ else if (!ferror(fp))
+ printf("error indicator not set after fread\n");
+ else
+ clearerr(fp);
+
+ fseek(fp, 4, SEEK_SET);
+ fprintf(fp, "bar baz");
+ fclose(fp);
+ assert_stream("foo bar baz");
+ free(buf);
+}
+
+ATF_TC_WITHOUT_HEAD(seek_tests);
+ATF_TC_BODY(seek_tests, tc)
+{
+ FILE *fp;
+
+ fp = open_memstream(&buf, &len);
+ ATF_REQUIRE_MSG(fp != NULL, "open_memstream failed: %d", errno);
+
+#define SEEK_FAIL(offset, whence, error) do { \
+ errno = 0; \
+ ATF_REQUIRE_MSG(fseeko(fp, (offset), (whence)) != 0, \
+ "fseeko(%s, %s) did not fail, set pos to %jd\n", \
+ __STRING(offset), __STRING(whence), \
+ (intmax_t)ftello(fp)); \
+ ATF_REQUIRE_MSG(errno == (error), \
+ "fseeko(%s, %s) failed with %d rather than %s\n", \
+ __STRING(offset), __STRING(whence), errno, \
+ __STRING(error)); \
+} while (0)
+
+#define SEEK_OK(offset, whence, result) do { \
+ ATF_REQUIRE_MSG(fseeko(fp, (offset), (whence)) == 0, \
+ "fseeko(%s, %s) failed: %s", \
+ __STRING(offset), __STRING(whence), strerror(errno)); \
+ ATF_REQUIRE_MSG(ftello(fp) == (result), \
+ "fseeko(%s, %s) seeked to %jd rather than %s\n", \
+ __STRING(offset), __STRING(whence), \
+ (intmax_t)ftello(fp), __STRING(result)); \
+} while (0)
+
+ SEEK_FAIL(-1, SEEK_SET, EINVAL);
+ SEEK_FAIL(-1, SEEK_CUR, EINVAL);
+ SEEK_FAIL(-1, SEEK_END, EINVAL);
+ fprintf(fp, "foo");
+ SEEK_OK(-1, SEEK_CUR, 2);
+ SEEK_OK(0, SEEK_SET, 0);
+ SEEK_OK(-1, SEEK_END, 2);
+ SEEK_OK(OFF_MAX - 1, SEEK_SET, OFF_MAX - 1);
+ SEEK_FAIL(2, SEEK_CUR, EOVERFLOW);
+ fclose(fp);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, open_group_test);
+ ATF_TP_ADD_TC(tp, simple_tests);
+ ATF_TP_ADD_TC(tp, seek_tests);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/stdio/open_wmemstream_test.c b/lib/libc/tests/stdio/open_wmemstream_test.c
new file mode 100644
index 0000000..d6ae2ea
--- /dev/null
+++ b/lib/libc/tests/stdio/open_wmemstream_test.c
@@ -0,0 +1,201 @@
+/*-
+ * Copyright (c) 2013 Hudson River Trading LLC
+ * Written by: John H. Baldwin <jhb@FreeBSD.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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include <atf-c.h>
+
+static wchar_t *buf;
+static size_t len;
+
+static void
+assert_stream(const wchar_t *contents)
+{
+ if (wcslen(contents) != len)
+ printf("bad length %zd for \"%ls\"\n", len, contents);
+ else if (wcsncmp(buf, contents, wcslen(contents)) != 0)
+ printf("bad buffer \"%ls\" for \"%ls\"\n", buf, contents);
+}
+
+ATF_TC_WITHOUT_HEAD(open_group_test);
+ATF_TC_BODY(open_group_test, tc)
+{
+ FILE *fp;
+ off_t eob;
+
+ fp = open_wmemstream(&buf, &len);
+ ATF_REQUIRE_MSG(fp != NULL, "open_wmemstream failed");
+
+ fwprintf(fp, L"hello my world");
+ fflush(fp);
+ assert_stream(L"hello my world");
+ eob = ftello(fp);
+ rewind(fp);
+ fwprintf(fp, L"good-bye");
+ fseeko(fp, eob, SEEK_SET);
+ fclose(fp);
+ assert_stream(L"good-bye world");
+ free(buf);
+}
+
+ATF_TC_WITHOUT_HEAD(simple_tests);
+ATF_TC_BODY(simple_tests, tc)
+{
+ static const wchar_t zerobuf[] =
+ { L'f', L'o', L'o', 0, 0, 0, 0, L'b', L'a', L'r', 0 };
+ wchar_t c;
+ FILE *fp;
+
+ fp = open_wmemstream(&buf, NULL);
+ ATF_REQUIRE_MSG(fp == NULL, "open_wmemstream did not fail");
+ ATF_REQUIRE_MSG(errno == EINVAL,
+ "open_wmemstream didn't fail with EINVAL");
+ fp = open_wmemstream(NULL, &len);
+ ATF_REQUIRE_MSG(fp == NULL, "open_wmemstream did not fail");
+ ATF_REQUIRE_MSG(errno == EINVAL,
+ "open_wmemstream didn't fail with EINVAL");
+ fp = open_wmemstream(&buf, &len);
+ ATF_REQUIRE_MSG(fp != NULL, "open_memstream failed; errno=%d", errno);
+ fflush(fp);
+ assert_stream(L"");
+ if (fwide(fp, 0) <= 0)
+ printf("stream is not wide-oriented\n");
+
+ fwprintf(fp, L"fo");
+ fflush(fp);
+ assert_stream(L"fo");
+ fputwc(L'o', fp);
+ fflush(fp);
+ assert_stream(L"foo");
+ rewind(fp);
+ fflush(fp);
+ assert_stream(L"");
+ fseek(fp, 0, SEEK_END);
+ fflush(fp);
+ assert_stream(L"foo");
+
+ /*
+ * Test seeking out past the current end. Should zero-fill the
+ * intermediate area.
+ */
+ fseek(fp, 4, SEEK_END);
+ fwprintf(fp, L"bar");
+ fflush(fp);
+
+ /*
+ * Can't use assert_stream() here since this should contain
+ * embedded null characters.
+ */
+ if (len != 10)
+ printf("bad length %zd for zero-fill test\n", len);
+ else if (memcmp(buf, zerobuf, sizeof(zerobuf)) != 0)
+ printf("bad buffer for zero-fill test\n");
+
+ fseek(fp, 3, SEEK_SET);
+ fwprintf(fp, L" in ");
+ fflush(fp);
+ assert_stream(L"foo in ");
+ fseek(fp, 0, SEEK_END);
+ fflush(fp);
+ assert_stream(L"foo in bar");
+
+ rewind(fp);
+ if (fread(&c, sizeof(c), 1, fp) != 0)
+ printf("fread did not fail\n");
+ else if (!ferror(fp))
+ printf("error indicator not set after fread\n");
+ else
+ clearerr(fp);
+
+ fseek(fp, 4, SEEK_SET);
+ fwprintf(fp, L"bar baz");
+ fclose(fp);
+ assert_stream(L"foo bar baz");
+ free(buf);
+}
+
+ATF_TC_WITHOUT_HEAD(seek_tests);
+ATF_TC_BODY(seek_tests, tc)
+{
+ FILE *fp;
+
+ fp = open_wmemstream(&buf, &len);
+ ATF_REQUIRE_MSG(fp != NULL, "open_wmemstream failed; errno=%d", errno);
+
+#define SEEK_FAIL(offset, whence, error) do { \
+ errno = 0; \
+ ATF_REQUIRE_MSG(fseeko(fp, (offset), (whence)) != 0, \
+ "fseeko(%s, %s) did not fail, set pos to %jd\n", \
+ __STRING(offset), __STRING(whence), \
+ (intmax_t)ftello(fp)); \
+ ATF_REQUIRE_MSG(errno == (error), \
+ "fseeko(%s, %s) failed with %d rather than %s\n", \
+ __STRING(offset), __STRING(whence), errno, \
+ __STRING(error)); \
+} while (0)
+
+#define SEEK_OK(offset, whence, result) do { \
+ ATF_REQUIRE_MSG(fseeko(fp, (offset), (whence)) == 0, \
+ "fseeko(%s, %s) failed: %s", \
+ __STRING(offset), __STRING(whence), strerror(errno)); \
+ ATF_REQUIRE_MSG(ftello(fp) == (result), \
+ "fseeko(%s, %s) seeked to %jd rather than %s\n", \
+ __STRING(offset), __STRING(whence), \
+ (intmax_t)ftello(fp), __STRING(result)); \
+} while (0)
+
+ SEEK_FAIL(-1, SEEK_SET, EINVAL);
+ SEEK_FAIL(-1, SEEK_CUR, EINVAL);
+ SEEK_FAIL(-1, SEEK_END, EINVAL);
+ fwprintf(fp, L"foo");
+ SEEK_OK(-1, SEEK_CUR, 2);
+ SEEK_OK(0, SEEK_SET, 0);
+ SEEK_OK(-1, SEEK_END, 2);
+ SEEK_OK(OFF_MAX - 1, SEEK_SET, OFF_MAX - 1);
+ SEEK_FAIL(2, SEEK_CUR, EOVERFLOW);
+ fclose(fp);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, open_group_test);
+ ATF_TP_ADD_TC(tp, simple_tests);
+ ATF_TP_ADD_TC(tp, seek_tests);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/stdio/perror_test.c b/lib/libc/tests/stdio/perror_test.c
new file mode 100644
index 0000000..989f1ff
--- /dev/null
+++ b/lib/libc/tests/stdio/perror_test.c
@@ -0,0 +1,107 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * 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.
+ */
+
+/*
+ * Test program for perror() as specified by IEEE Std. 1003.1-2001 and
+ * ISO/IEC 9899:1999.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <atf-c.h>
+
+static char tmpfil[PATH_MAX];
+
+ATF_TC_WITHOUT_HEAD(perror_test);
+ATF_TC_BODY(perror_test, tc)
+{
+ char lbuf[512];
+ int i;
+ char *s;
+
+ strcpy(tmpfil, "perror.XXXXXXXX");
+ ATF_REQUIRE(mkstemp(tmpfil) >= 0);
+ /* Reopen stderr on a file descriptor other than 2. */
+ fclose(stderr);
+ for (i = 0; i < 3; i++)
+ dup(0);
+ ATF_REQUIRE(freopen(tmpfil, "r+", stderr) != NULL);
+
+ /*
+ * Test that perror() doesn't call strerror() (4.4BSD bug),
+ * the two ways of omitting a program name, and the formatting when
+ * a program name is specified.
+ */
+ s = strerror(ENOENT);
+ ATF_REQUIRE_MSG(strcmp(s, "No such file or directory") == 0,
+ "message obtained was: %s", s);
+ errno = EPERM;
+ perror(NULL);
+ perror("");
+ perror("perror_test");
+ ATF_REQUIRE_MSG(strcmp(s, "No such file or directory") == 0,
+ "message obtained was: %s", s);
+
+ /*
+ * Read it back to check...
+ */
+ rewind(stderr);
+ s = fgets(lbuf, sizeof(lbuf), stderr);
+ ATF_REQUIRE(s != NULL);
+ ATF_REQUIRE_MSG(strcmp(s, "Operation not permitted\n") == 0,
+ "message obtained was: %s", s);
+ s = fgets(lbuf, sizeof(lbuf), stderr);
+ ATF_REQUIRE(s != NULL);
+ ATF_REQUIRE_MSG(strcmp(s, "Operation not permitted\n") == 0,
+ "message obtained was: %s", s);
+ s = fgets(lbuf, sizeof(lbuf), stderr);
+ ATF_REQUIRE(s != NULL);
+ ATF_REQUIRE_MSG(
+ strcmp(s, "perror_test: Operation not permitted\n") == 0,
+ "message obtained was: %s", s);
+ s = fgets(lbuf, sizeof(lbuf), stderr);
+ ATF_REQUIRE(s == NULL);
+ fclose(stderr);
+
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, perror_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/stdio/print_positional_test.c b/lib/libc/tests/stdio/print_positional_test.c
new file mode 100644
index 0000000..1de43a1
--- /dev/null
+++ b/lib/libc/tests/stdio/print_positional_test.c
@@ -0,0 +1,156 @@
+/* $OpenBSD: sprintf_test.c,v 1.3 2004/09/16 20:22:26 otto Exp $ */
+
+/*
+ * Copyright (c) 2003 Theo de Raadt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - 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 COPYRIGHT HOLDERS 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
+ * COPYRIGHT HOLDERS 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include <atf-c.h>
+
+const char correct[] =
+ "|xx 01 02 03 04\n"
+ "|xx 05 06 07 08\n"
+ "|xx 09 10 11 12\n"
+ "|xx 13 14 15 16\n"
+ "|xx 17 18 19 20\n"
+ "|xx 21 22 23 24\n"
+ "|xx 25 26 27 28\n"
+ "|xx 29 30 31 32\n"
+ "|xx 33 34 35 36\n"
+ "|xx 37 38 39 40\n"
+ "|xx 41 42 43 44\n"
+ "|xx 45 -1 1 -1 1\n";
+
+const char correct2[] =
+ "b bs BSD";
+static char buf[1024];
+static wchar_t wbuf1[1024], wbuf2[1024];
+static const char *temp;
+
+ATF_TC_WITHOUT_HEAD(positional_normal);
+ATF_TC_BODY(positional_normal, tc)
+{
+
+ /* Test positional arguments */
+ snprintf(buf, sizeof buf,
+ "|xx %1$s %2$s %3$s %4$s\n"
+ "|xx %5$s %6$s %7$s %8$s\n"
+ "|xx %9$s %10$s %11$s %12$s\n"
+ "|xx %13$s %14$s %15$s %16$s\n"
+ "|xx %17$s %18$s %19$s %20$s\n"
+ "|xx %21$s %22$s %23$s %24$s\n"
+ "|xx %25$s %26$s %27$s %28$s\n"
+ "|xx %29$s %30$s %31$s %32$s\n"
+ "|xx %33$s %34$s %35$s %36$s\n"
+ "|xx %37$s %38$s %39$s %40$s\n"
+ "|xx %41$s %42$s %43$s %44$s\n"
+ "|xx %45$d %46$ld %47$lld %48$d %49$lld\n",
+ "01", "02", "03", "04", "05", "06",
+ "07", "08", "09", "10", "11", "12",
+ "13", "14", "15", "16", "17", "18",
+ "19", "20", "21", "22", "23", "24",
+ "25", "26", "27", "28", "29", "30",
+ "31", "32", "33", "34", "35", "36",
+ "37", "38", "39", "40", "41", "42",
+ "43", "44", 45, -1L, 1LL, -1, 1LL
+ );
+ ATF_REQUIRE_MSG(wcscmp(wbuf1, wbuf2) == 0,
+ "buffers didn't match");
+}
+
+ATF_TC_WITHOUT_HEAD(positional_wide);
+ATF_TC_BODY(positional_wide, tc)
+{
+
+ swprintf(wbuf1, sizeof wbuf1,
+ L"|xx %1$s %2$s %3$s %4$s\n"
+ "|xx %5$s %6$s %7$s %8$s\n"
+ "|xx %9$s %10$s %11$s %12$s\n"
+ "|xx %13$s %14$s %15$s %16$s\n"
+ "|xx %17$s %18$s %19$s %20$s\n"
+ "|xx %21$s %22$s %23$s %24$s\n"
+ "|xx %25$s %26$s %27$s %28$s\n"
+ "|xx %29$s %30$s %31$s %32$s\n"
+ "|xx %33$s %34$s %35$s %36$s\n"
+ "|xx %37$s %38$s %39$s %40$s\n"
+ "|xx %41$s %42$s %43$s %44$s\n"
+ "|xx %45$d %46$ld %47$lld %48$d %49$lld\n",
+ "01", "02", "03", "04", "05", "06",
+ "07", "08", "09", "10", "11", "12",
+ "13", "14", "15", "16", "17", "18",
+ "19", "20", "21", "22", "23", "24",
+ "25", "26", "27", "28", "29", "30",
+ "31", "32", "33", "34", "35", "36",
+ "37", "38", "39", "40", "41", "42",
+ "43", "44", 45, -1L, 1LL, -1, 1LL
+ );
+ temp = correct;
+ mbsrtowcs(wbuf2, &temp, sizeof wbuf2, NULL);
+ ATF_REQUIRE_MSG(wcscmp(wbuf1, wbuf2) == 0,
+ "buffers didn't match");
+}
+
+ATF_TC_WITHOUT_HEAD(positional_precision);
+ATF_TC_BODY(positional_precision, tc)
+{
+
+ snprintf(buf, sizeof buf, "%2$.*4$s %2$.*3$s %1$s",
+ "BSD", "bsd", 2, 1);
+ ATF_REQUIRE_MSG(strcmp(buf, correct2) == 0,
+ "buffers didn't match");
+}
+
+ATF_TC_WITHOUT_HEAD(positional_precision_wide);
+ATF_TC_BODY(positional_precision_wide, tc)
+{
+
+ swprintf(wbuf1, sizeof buf, L"%2$.*4$s %2$.*3$s %1$s",
+ "BSD", "bsd", 2, 1);
+ temp = correct2;
+ mbsrtowcs(wbuf2, &temp, sizeof wbuf2, NULL);
+ ATF_REQUIRE_MSG(wcscmp(wbuf1, wbuf2) == 0,
+ "buffers didn't match");
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, positional_normal);
+ ATF_TP_ADD_TC(tp, positional_wide);
+ ATF_TP_ADD_TC(tp, positional_precision);
+ ATF_TP_ADD_TC(tp, positional_precision_wide);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/stdio/printbasic_test.c b/lib/libc/tests/stdio/printbasic_test.c
new file mode 100644
index 0000000..d1fab29
--- /dev/null
+++ b/lib/libc/tests/stdio/printbasic_test.c
@@ -0,0 +1,158 @@
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.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.
+ */
+
+/*
+ * Tests for basic and miscellaneous printf() formats.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <err.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include <atf-c.h>
+
+#define S_UINT64MAX "18446744073709551615"
+#define S_UINT32MAX "4294967295"
+#define S_INT64MIN "-9223372036854775808"
+#define S_INT32MIN "-2147483648"
+
+#define S_SIZEMAX (SIZE_MAX == UINT64_MAX ? S_UINT64MAX : S_UINT32MAX)
+#define S_ULONGMAX (ULONG_MAX == UINT64_MAX ? S_UINT64MAX : S_UINT32MAX)
+#define S_ULLONGMAX (ULLONG_MAX == UINT64_MAX ? S_UINT64MAX : S_UINT32MAX)
+
+static void
+smash_stack(void)
+{
+ static uint32_t junk = 0xdeadbeef;
+ uint32_t buf[512];
+ int i;
+
+ for (i = 0; i < sizeof(buf) / sizeof(buf[0]); i++)
+ buf[i] = junk;
+}
+
+#define testfmt(result, fmt, ...) \
+ _testfmt((result), #__VA_ARGS__, fmt, __VA_ARGS__)
+static void
+_testfmt(const char *result, const char *argstr, const char *fmt,...)
+{
+#define BUF 100
+ wchar_t ws[BUF], wfmt[BUF], wresult[BUF];
+ char s[BUF];
+ va_list ap, ap2;
+
+ va_start(ap, fmt);
+ va_copy(ap2, ap);
+ smash_stack();
+ vsnprintf(s, sizeof(s), fmt, ap);
+ if (strcmp(result, s) != 0) {
+ atf_tc_fail(
+ "printf(\"%s\", %s) ==> [%s], expected [%s]\n",
+ fmt, argstr, s, result);
+ }
+
+ smash_stack();
+ mbstowcs(ws, s, BUF - 1);
+ mbstowcs(wfmt, fmt, BUF - 1);
+ mbstowcs(wresult, result, BUF - 1);
+ vswprintf(ws, sizeof(ws) / sizeof(ws[0]), wfmt, ap2);
+ if (wcscmp(wresult, ws) != 0) {
+ atf_tc_fail(
+ "wprintf(\"%ls\", %s) ==> [%ls], expected [%ls]\n",
+ wfmt, argstr, ws, wresult);
+ }
+}
+
+ATF_TC_WITHOUT_HEAD(int_within_limits);
+ATF_TC_BODY(int_within_limits, tc)
+{
+
+ ATF_REQUIRE(setlocale(LC_NUMERIC, "C"));
+
+ /* The test requires these to be true. */
+ ATF_REQUIRE(UINTMAX_MAX == UINT64_MAX);
+ ATF_REQUIRE(UINT_MAX == UINT32_MAX);
+ ATF_REQUIRE(USHRT_MAX == 0xffff);
+ ATF_REQUIRE(UCHAR_MAX == 0xff);
+
+ /* Make sure we handle signed vs. unsigned args correctly. */
+ testfmt("-1", "%jd", (intmax_t)-1);
+ testfmt(S_UINT64MAX, "%ju", UINT64_MAX);
+
+ testfmt("-1", "%td", (ptrdiff_t)-1);
+ testfmt(S_SIZEMAX, "%tu", (size_t)-1);
+
+ testfmt("-1", "%zd", (ssize_t)-1);
+ testfmt(S_SIZEMAX, "%zu", (ssize_t)-1);
+
+ testfmt("-1", "%ld", (long)-1);
+ testfmt(S_ULONGMAX, "%lu", ULONG_MAX);
+
+ testfmt("-1", "%lld", (long long)-1);
+ testfmt(S_ULONGMAX, "%lu", ULLONG_MAX);
+
+ testfmt("-1", "%d", -1);
+ testfmt(S_UINT32MAX, "%lu", UINT32_MAX);
+
+ testfmt("-1", "%hd", -1);
+ testfmt("65535", "%hu", USHRT_MAX);
+
+ testfmt("-1", "%hhd", -1);
+ testfmt("255", "%hhu", UCHAR_MAX);
+}
+
+ATF_TC_WITHOUT_HEAD(int_limits);
+ATF_TC_BODY(int_limits, tc)
+{
+
+ ATF_REQUIRE(setlocale(LC_NUMERIC, "C"));
+
+ /*
+ * Check that printing the largest negative number does not cause
+ * overflow when it is negated.
+ */
+ testfmt(S_INT32MIN, "%d", INT_MIN);
+ testfmt(S_INT64MIN, "%jd", INTMAX_MIN);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, int_within_limits);
+ ATF_TP_ADD_TC(tp, int_limits);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/stdio/printfloat_test.c b/lib/libc/tests/stdio/printfloat_test.c
new file mode 100644
index 0000000..6b4e455
--- /dev/null
+++ b/lib/libc/tests/stdio/printfloat_test.c
@@ -0,0 +1,390 @@
+/*-
+ * Copyright (c) 2002-2009 David Schultz <das@FreeBSD.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.
+ */
+
+/*
+ * Test for printf() floating point formats.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <err.h>
+#include <fenv.h>
+#include <float.h>
+#include <locale.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include <atf-c.h>
+
+static void
+smash_stack(void)
+{
+ static uint32_t junk = 0xdeadbeef;
+ uint32_t buf[512];
+ int i;
+
+ for (i = 0; i < sizeof(buf) / sizeof(buf[0]); i++)
+ buf[i] = junk;
+}
+
+#define testfmt(result, fmt, ...) \
+ _testfmt((result), #__VA_ARGS__, fmt, __VA_ARGS__)
+static void
+_testfmt(const char *result, const char *argstr, const char *fmt,...)
+{
+#define BUF 100
+ wchar_t ws[BUF], wfmt[BUF], wresult[BUF];
+ char s[BUF];
+ va_list ap, ap2;
+
+ va_start(ap, fmt);
+ va_copy(ap2, ap);
+ smash_stack();
+ vsnprintf(s, sizeof(s), fmt, ap);
+ if (strcmp(result, s) != 0) {
+ atf_tc_fail(
+ "printf(\"%s\", %s) ==> [%s], expected [%s]\n",
+ fmt, argstr, s, result);
+ }
+
+ smash_stack();
+ mbstowcs(ws, s, BUF - 1);
+ mbstowcs(wfmt, fmt, BUF - 1);
+ mbstowcs(wresult, result, BUF - 1);
+ vswprintf(ws, sizeof(ws) / sizeof(ws[0]), wfmt, ap2);
+ if (wcscmp(wresult, ws) != 0) {
+ atf_tc_fail(
+ "wprintf(\"%ls\", %s) ==> [%ls], expected [%ls]\n",
+ wfmt, argstr, ws, wresult);
+ }
+}
+
+ATF_TC_WITHOUT_HEAD(float_within_limits);
+ATF_TC_BODY(float_within_limits, tc)
+{
+
+ ATF_REQUIRE(setlocale(LC_NUMERIC, "C"));
+
+ /* Basic tests of decimal output functionality. */
+ testfmt(" 1.000000E+00", "%13E", 1.0);
+ testfmt(" 1.000000", "%13f", 1.0);
+ testfmt(" 1", "%13G", 1.0);
+ testfmt(" 1.000000E+00", "%13LE", 1.0L);
+ testfmt(" 1.000000", "%13Lf", 1.0L);
+ testfmt(" 1", "%13LG", 1.0L);
+
+ testfmt("2.718282", "%.*f", -2, 2.7182818);
+
+ testfmt("1.234568e+06", "%e", 1234567.8);
+ testfmt("1234567.800000", "%f", 1234567.8);
+ testfmt("1.23457E+06", "%G", 1234567.8);
+ testfmt("1.234568e+06", "%Le", 1234567.8L);
+ testfmt("1234567.800000", "%Lf", 1234567.8L);
+ testfmt("1.23457E+06", "%LG", 1234567.8L);
+
+#if (LDBL_MANT_DIG > DBL_MANT_DIG) && !defined(__i386__)
+ testfmt("123456789.864210", "%Lf", 123456789.8642097531L);
+ testfmt("-1.23457E+08", "%LG", -123456789.8642097531L);
+ testfmt("123456789.8642097531", "%.10Lf", 123456789.8642097531L);
+ testfmt(" 3.141592653589793238e-4000", "%L27.18Le",
+ 3.14159265358979323846e-4000L);
+#endif
+}
+
+ATF_TC_WITHOUT_HEAD(infinities_and_nans);
+ATF_TC_BODY(infinities_and_nans, tc)
+{
+
+ ATF_REQUIRE(setlocale(LC_NUMERIC, "C"));
+
+ testfmt("nan", "%e", NAN);
+ testfmt("NAN", "%F", NAN);
+ testfmt("nan", "%g", NAN);
+ testfmt("NAN", "%LE", (long double)NAN);
+ testfmt(" nan", "%05e", NAN);
+
+ testfmt("INF", "%E", HUGE_VAL);
+ testfmt("-inf", "%f", -HUGE_VAL);
+ testfmt("+inf", "%+g", HUGE_VAL);
+ testfmt(" inf", "%4.2Le", HUGE_VALL);
+ testfmt("-inf", "%Lf", -HUGE_VALL);
+ testfmt(" inf", "%05e", HUGE_VAL);
+ testfmt(" -inf", "%05e", -HUGE_VAL);
+}
+
+ATF_TC_WITHOUT_HEAD(padding);
+ATF_TC_BODY(padding, tc)
+{
+
+ ATF_REQUIRE(setlocale(LC_NUMERIC, "C"));
+
+ testfmt("0.000000e+00", "%e", 0.0);
+ testfmt("0.000000", "%F", (double)0.0);
+ testfmt("0", "%G", 0.0);
+ testfmt(" 0", "%3.0Lg", 0.0L);
+ testfmt(" 0", "%5.0f", 0.001);
+}
+
+ATF_TC_WITHOUT_HEAD(precision_specifiers);
+ATF_TC_BODY(precision_specifiers, tc)
+{
+
+ ATF_REQUIRE(setlocale(LC_NUMERIC, "C"));
+
+ testfmt("1.0123e+00", "%.4e", 1.0123456789);
+ testfmt("1.0123", "%.4f", 1.0123456789);
+ testfmt("1.012", "%.4g", 1.0123456789);
+ testfmt("1.2346e-02", "%.4e", 0.0123456789);
+ testfmt("0.0123", "%.4f", 0.0123456789);
+ testfmt("0.01235", "%.4g", 0.0123456789);
+}
+
+ATF_TC_WITHOUT_HEAD(thousands_separator_and_other_locale_tests);
+ATF_TC_BODY(thousands_separator_and_other_locale_tests, tc)
+{
+
+ ATF_REQUIRE(setlocale(LC_NUMERIC, "C"));
+
+ testfmt("12345678.0625", "%'.04f", 12345678.0625);
+ testfmt("0012345678.0625", "%'015.4F", 12345678.0625);
+
+ ATF_REQUIRE(setlocale(LC_NUMERIC, "hi_IN.ISCII-DEV")); /* grouping == 2;3 */
+ testfmt("1,23,45,678.0625", "%'.4f", 12345678.0625);
+ testfmt("01,23,45,678.0625", "%'017.4F", 12345678.0625);
+ testfmt(" 9,000", "%'6.0f", 9000.0);
+ testfmt("9,000.0", "%'.1f", 9000.0);
+
+ ATF_REQUIRE(setlocale(LC_NUMERIC, "ru_RU.ISO8859-5")); /* decimalpoint==, */
+ testfmt("3,1415", "%g", 3.1415);
+
+ /* thousands=. decimalpoint=, grouping=3;3 */
+ ATF_REQUIRE(setlocale(LC_NUMERIC, "el_GR.ISO8859-7")); /* decimalpoint==, */
+ testfmt("1.234,00", "%'.2f", 1234.00);
+ testfmt("123.456,789", "%'.3f", 123456.789);
+
+ ATF_REQUIRE(setlocale(LC_NUMERIC, "C"));
+ testfmt("12345678.062500", "%'f", 12345678.0625);
+ testfmt("9000.000000", "%'f", 9000.0);
+}
+
+ATF_TC_WITHOUT_HEAD(signed_conversions);
+ATF_TC_BODY(signed_conversions, tc)
+{
+
+ ATF_REQUIRE(setlocale(LC_NUMERIC, "C"));
+
+ testfmt("+2.500000e-01", "%+e", 0.25);
+ testfmt("+0.000000", "%+F", 0.0);
+ testfmt("-1", "%+g", -1.0);
+
+ testfmt("-1.000000e+00", "% e", -1.0);
+ testfmt("+1.000000", "% +f", 1.0);
+ testfmt(" 1", "% g", 1.0);
+ testfmt(" 0", "% g", 0.0);
+}
+
+ATF_TC_WITHOUT_HEAD(alternate_form);
+ATF_TC_BODY(alternate_form, tc)
+{
+
+ ATF_REQUIRE(setlocale(LC_NUMERIC, "C"));
+
+ testfmt("1.250e+00", "%#.3e", 1.25);
+ testfmt("123.000000", "%#f", 123.0);
+ testfmt(" 12345.", "%#7.5g", 12345.0);
+ testfmt(" 1.00000", "%#8g", 1.0);
+ testfmt("0.0", "%#.2g", 0.0);
+}
+
+ATF_TC_WITHOUT_HEAD(padding_and_decimal_point_placement);
+ATF_TC_BODY(padding_and_decimal_point_placement, tc)
+{
+
+ ATF_REQUIRE(setlocale(LC_NUMERIC, "C"));
+
+ testfmt("03.2E+00", "%08.1E", 3.25);
+ testfmt("003.25", "%06.2F", 3.25);
+ testfmt("0003.25", "%07.4G", 3.25);
+
+ testfmt("3.14159e-05", "%g", 3.14159e-5);
+ testfmt("0.000314159", "%g", 3.14159e-4);
+ testfmt("3.14159e+06", "%g", 3.14159e6);
+ testfmt("314159", "%g", 3.14159e5);
+ testfmt("314159.", "%#g", 3.14159e5);
+
+ testfmt(" 9.000000e+03", "%13e", 9000.0);
+ testfmt(" 9000.000000", "%12f", 9000.0);
+ testfmt(" 9000", "%5g", 9000.0);
+ testfmt(" 900000.", "%#8g", 900000.0);
+ testfmt(" 9e+06", "%6g", 9000000.0);
+ testfmt(" 9.000000e-04", "%13e", 0.0009);
+ testfmt(" 0.000900", "%9f", 0.0009);
+ testfmt(" 0.0009", "%7g", 0.0009);
+ testfmt(" 9e-05", "%6g", 0.00009);
+ testfmt(" 9.00000e-05", "%#12g", 0.00009);
+ testfmt(" 9.e-05", "%#7.1g", 0.00009);
+
+ testfmt(" 0.0", "%4.1f", 0.0);
+ testfmt("90.0", "%4.1f", 90.0);
+ testfmt(" 100", "%4.0f", 100.0);
+ testfmt("9.0e+01", "%4.1e", 90.0);
+ testfmt("1e+02", "%4.0e", 100.0);
+}
+
+ATF_TC_WITHOUT_HEAD(decimal_rounding);
+ATF_TC_BODY(decimal_rounding, tc)
+{
+
+ ATF_REQUIRE(setlocale(LC_NUMERIC, "C"));
+
+ fesetround(FE_DOWNWARD);
+ testfmt("4.437", "%.3f", 4.4375);
+ testfmt("-4.438", "%.3f", -4.4375);
+ testfmt("4.437", "%.3Lf", 4.4375L);
+ testfmt("-4.438", "%.3Lf", -4.4375L);
+
+ fesetround(FE_UPWARD);
+ testfmt("4.438", "%.3f", 4.4375);
+ testfmt("-4.437", "%.3f", -4.4375);
+ testfmt("4.438", "%.3Lf", 4.4375L);
+ testfmt("-4.437", "%.3Lf", -4.4375L);
+
+ fesetround(FE_TOWARDZERO);
+ testfmt("4.437", "%.3f", 4.4375);
+ testfmt("-4.437", "%.3f", -4.4375);
+ testfmt("4.437", "%.3Lf", 4.4375L);
+ testfmt("-4.437", "%.3Lf", -4.4375L);
+
+ fesetround(FE_TONEAREST);
+ testfmt("4.438", "%.3f", 4.4375);
+ testfmt("-4.438", "%.3f", -4.4375);
+ testfmt("4.438", "%.3Lf", 4.4375L);
+ testfmt("-4.438", "%.3Lf", -4.4375L);
+}
+
+ATF_TC_WITHOUT_HEAD(hexadecimal_floating_point);
+ATF_TC_BODY(hexadecimal_floating_point, tc)
+{
+
+ ATF_REQUIRE(setlocale(LC_NUMERIC, "C"));
+
+ /*
+ * Hexadecimal floating point (%a, %A) tests. Some of these
+ * are only valid if the implementation converts to hex digits
+ * on nibble boundaries.
+ */
+ testfmt("0x0p+0", "%a", 0x0.0p0);
+ testfmt("0X0.P+0", "%#LA", 0x0.0p0L);
+ testfmt("inf", "%La", (long double)INFINITY);
+ testfmt("+INF", "%+A", INFINITY);
+ testfmt("nan", "%La", (long double)NAN);
+ testfmt("NAN", "%A", NAN);
+
+ testfmt(" 0x1.23p+0", "%10a", 0x1.23p0);
+ testfmt(" 0x1.23p-500", "%12a", 0x1.23p-500);
+ testfmt(" 0x1.2p+40", "%10.1a", 0x1.23p40);
+ testfmt(" 0X1.230000000000000000000000P-4", "%32.24A", 0x1.23p-4);
+ testfmt("0x1p-1074", "%a", 0x1p-1074);
+ testfmt("0x1.2345p-1024", "%a", 0x1.2345p-1024);
+
+#if (LDBL_MANT_DIG == 64) && !defined(__i386__)
+ testfmt("0x1.921fb54442d18468p+1", "%La", 0x3.243f6a8885a308dp0L);
+ testfmt("0x1p-16445", "%La", 0x1p-16445L);
+ testfmt("0x1.30ecap-16381", "%La", 0x9.8765p-16384L);
+#elif (LDBL_MANT_DIG == 113)
+ testfmt("0x1.921fb54442d18469898cc51701b8p+1", "%La",
+ 0x3.243f6a8885a308d313198a2e037p0L);
+ testfmt("0x1p-16494", "%La", 0x1p-16494L);
+ testfmt("0x1.2345p-16384", "%La", 0x1.2345p-16384L);
+#else
+ testfmt("0x1.921fb54442d18p+1", "%La", 0x3.243f6a8885a31p0L);
+ testfmt("0x1p-1074", "%La", 0x1p-1074L);
+ testfmt("0x1.30ecap-1021", "%La", 0x9.8765p-1024L);
+#endif
+}
+
+ATF_TC_WITHOUT_HEAD(hexadecimal_rounding);
+ATF_TC_BODY(hexadecimal_rounding, tc)
+{
+
+ ATF_REQUIRE(setlocale(LC_NUMERIC, "C"));
+
+ fesetround(FE_TOWARDZERO);
+ testfmt("0X1.23456789ABCP+0", "%.11A", 0x1.23456789abcdep0);
+ testfmt("-0x1.23456p+0", "%.5a", -0x1.23456789abcdep0);
+ testfmt("0x1.23456p+0", "%.5a", 0x1.23456789abcdep0);
+ testfmt("0x1.234567p+0", "%.6a", 0x1.23456789abcdep0);
+ testfmt("-0x1.234566p+0", "%.6a", -0x1.23456689abcdep0);
+
+ fesetround(FE_DOWNWARD);
+ testfmt("0X1.23456789ABCP+0", "%.11A", 0x1.23456789abcdep0);
+ testfmt("-0x1.23457p+0", "%.5a", -0x1.23456789abcdep0);
+ testfmt("0x1.23456p+0", "%.5a", 0x1.23456789abcdep0);
+ testfmt("0x1.234567p+0", "%.6a", 0x1.23456789abcdep0);
+ testfmt("-0x1.234567p+0", "%.6a", -0x1.23456689abcdep0);
+
+ fesetround(FE_UPWARD);
+ testfmt("0X1.23456789ABDP+0", "%.11A", 0x1.23456789abcdep0);
+ testfmt("-0x1.23456p+0", "%.5a", -0x1.23456789abcdep0);
+ testfmt("0x1.23457p+0", "%.5a", 0x1.23456789abcdep0);
+ testfmt("0x1.234568p+0", "%.6a", 0x1.23456789abcdep0);
+ testfmt("-0x1.234566p+0", "%.6a", -0x1.23456689abcdep0);
+
+ fesetround(FE_TONEAREST);
+ testfmt("0x1.23456789abcdep+4", "%a", 0x1.23456789abcdep4);
+ testfmt("0X1.23456789ABDP+0", "%.11A", 0x1.23456789abcdep0);
+ testfmt("-0x1.23456p+0", "%.5a", -0x1.23456789abcdep0);
+ testfmt("0x1.23456p+0", "%.5a", 0x1.23456789abcdep0);
+ testfmt("0x1.234568p+0", "%.6a", 0x1.23456789abcdep0);
+ testfmt("-0x1.234567p+0", "%.6a", -0x1.23456689abcdep0);
+ testfmt("0x1.00p-1029", "%.2a", 0x1.fffp-1030);
+ testfmt("0x1.00p-1026", "%.2a", 0xf.fffp-1030);
+ testfmt("0x1.83p+0", "%.2a", 1.51);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, float_within_limits);
+ ATF_TP_ADD_TC(tp, infinities_and_nans);
+ ATF_TP_ADD_TC(tp, padding);
+ ATF_TP_ADD_TC(tp, precision_specifiers);
+ ATF_TP_ADD_TC(tp, thousands_separator_and_other_locale_tests);
+ ATF_TP_ADD_TC(tp, signed_conversions);
+ ATF_TP_ADD_TC(tp, alternate_form);
+ ATF_TP_ADD_TC(tp, padding_and_decimal_point_placement);
+ ATF_TP_ADD_TC(tp, decimal_rounding);
+ ATF_TP_ADD_TC(tp, hexadecimal_floating_point);
+ ATF_TP_ADD_TC(tp, hexadecimal_rounding);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/stdio/scanfloat_test.c b/lib/libc/tests/stdio/scanfloat_test.c
new file mode 100644
index 0000000..7e27e69
--- /dev/null
+++ b/lib/libc/tests/stdio/scanfloat_test.c
@@ -0,0 +1,316 @@
+/*-
+ * Copyright (C) 2003, 2005 David Schultz <das@FreeBSD.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.
+ */
+
+/*
+ * Test for scanf() floating point formats.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <fenv.h>
+#include <float.h>
+#include <locale.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <atf-c.h>
+
+#define eq(type, a, b) _eq(type##_EPSILON, (a), (b))
+static int
+_eq(long double epsilon, long double a, long double b)
+{
+ long double delta;
+
+ delta = fabsl(a - b);
+ return (delta <= epsilon);
+}
+
+ATF_TC_WITHOUT_HEAD(normalized_numbers);
+ATF_TC_BODY(normalized_numbers, tc)
+{
+ char buf[128];
+ long double ld = 0.0;
+ double d = 0.0;
+ float f = 0.0;
+
+ buf[0] = '\0';
+ ATF_REQUIRE(setlocale(LC_NUMERIC, ""));
+
+ sscanf("3.141592", "%e", &f);
+ ATF_REQUIRE(eq(FLT, f, 3.141592));
+
+ sscanf("3.141592653589793", "%lf", &d);
+ ATF_REQUIRE(eq(DBL, d, 3.141592653589793));
+
+ sscanf("1.234568e+06", "%E", &f);
+ ATF_REQUIRE(eq(FLT, f, 1.234568e+06));
+
+ sscanf("-1.234568e6", "%lF", &d);
+ ATF_REQUIRE(eq(DBL, d, -1.234568e6));
+
+ sscanf("+1.234568e-52", "%LG", &ld);
+ ATF_REQUIRE(eq(LDBL, ld, 1.234568e-52L));
+
+ sscanf("0.1", "%la", &d);
+ ATF_REQUIRE(eq(DBL, d, 0.1));
+
+ sscanf("00.2", "%lA", &d);
+ ATF_REQUIRE(eq(DBL, d, 0.2));
+
+ sscanf("123456", "%5le%s", &d, buf);
+ ATF_REQUIRE(eq(DBL, d, 12345.));
+ ATF_REQUIRE(strcmp(buf, "6") == 0);
+
+ sscanf("1.0Q", "%*5le%s", buf);
+ ATF_REQUIRE(strcmp(buf, "Q") == 0);
+
+ sscanf("-1.23e", "%e%s", &f, buf);
+ ATF_REQUIRE(eq(FLT, f, -1.23));
+ ATF_REQUIRE(strcmp(buf, "e") == 0);
+
+ sscanf("1.25e+", "%le%s", &d, buf);
+ ATF_REQUIRE(eq(DBL, d, 1.25));
+ ATF_REQUIRE(strcmp(buf, "e+") == 0);
+
+ sscanf("1.23E4E5", "%le%s", &d, buf);
+ ATF_REQUIRE(eq(DBL, d, 1.23e4));
+ ATF_REQUIRE(strcmp(buf, "E5") == 0);
+
+ sscanf("12e6", "%le", &d);
+ ATF_REQUIRE(eq(DBL, d, 12e6));
+
+ sscanf("1.a", "%le%s", &d, buf);
+ ATF_REQUIRE(eq(DBL, d, 1.0));
+ ATF_REQUIRE(strcmp(buf, "a") == 0);
+
+ sscanf(".0p4", "%le%s", &d, buf);
+ ATF_REQUIRE(eq(DBL, d, 0.0));
+ ATF_REQUIRE(strcmp(buf, "p4") == 0);
+
+ d = 0.25;
+ ATF_REQUIRE(sscanf(".", "%le", &d) == 0);
+ ATF_REQUIRE(d == 0.25);
+
+ sscanf("0x08", "%le", &d);
+ ATF_REQUIRE(d == 0x8p0);
+
+ sscanf("0x90a.bcdefP+09a", "%le%s", &d, buf);
+ ATF_REQUIRE(d == 0x90a.bcdefp+09);
+ ATF_REQUIRE(strcmp(buf, "a") == 0);
+
+#if (LDBL_MANT_DIG > DBL_MANT_DIG) && !defined(__i386__)
+ sscanf("3.14159265358979323846", "%Lg", &ld);
+ ATF_REQUIRE(eq(LDBL, ld, 3.14159265358979323846L));
+
+ sscanf(" 0X.0123456789abcdefffp-3g", "%Le%s", &ld, buf);
+ ATF_REQUIRE(ld == 0x0.0123456789abcdefffp-3L);
+ ATF_REQUIRE(strcmp(buf, "g") == 0);
+#endif
+
+ sscanf("0xg", "%le%s", &d, buf);
+ ATF_REQUIRE(d == 0.0);
+ ATF_REQUIRE(strcmp(buf, "xg") == 0);
+
+ ATF_REQUIRE(setlocale(LC_NUMERIC, "ru_RU.ISO8859-5")); /* decimalpoint==, */
+
+ sscanf("1.23", "%le%s", &d, buf);
+ ATF_REQUIRE(d == 1.0);
+ ATF_REQUIRE(strcmp(buf, ".23") == 0);
+
+ sscanf("1,23", "%le", &d);
+ ATF_REQUIRE(d == 1.23);
+
+ ATF_REQUIRE(setlocale(LC_NUMERIC, ""));
+}
+
+ATF_TC_WITHOUT_HEAD(infinities_and_nans);
+ATF_TC_BODY(infinities_and_nans, tc)
+{
+ char buf[128];
+ long double ld = 0.0;
+ double d = 0.0;
+ float f = 0.0;
+
+ ATF_REQUIRE(setlocale(LC_NUMERIC, "C"));
+
+ sscanf("-Inf", "%le", &d);
+ ATF_REQUIRE(d < 0.0 && isinf(d));
+
+ sscanf("iNfInItY and beyond", "%le%s", &d, buf);
+ ATF_REQUIRE(d > 0.0 && isinf(d));
+ ATF_REQUIRE(strcmp(buf, " and beyond"));
+
+ sscanf("NaN", "%le", &d);
+ ATF_REQUIRE(isnan(d));
+
+ sscanf("NAN(123Y", "%le%s", &d, buf);
+ ATF_REQUIRE(isnan(d));
+ ATF_REQUIRE(strcmp(buf, "(123Y") == 0);
+
+ sscanf("nan(f00f)plugh", "%le%s", &d, buf);
+ ATF_REQUIRE(isnan(d));
+ ATF_REQUIRE(strcmp(buf, "plugh") == 0);
+
+ sscanf("-nan", "%le", &d);
+ ATF_REQUIRE(isnan(d));
+
+ /* Only quiet NaNs should be returned. */
+ sscanf("NaN", "%e", &f);
+ sscanf("nan", "%le", &d);
+ sscanf("nan", "%Le", &ld);
+ feclearexcept(FE_ALL_EXCEPT);
+ ATF_REQUIRE(f != f);
+ ATF_REQUIRE(d != d);
+ ATF_REQUIRE(ld != ld);
+ ATF_REQUIRE(fetestexcept(FE_INVALID) == 0);
+ sscanf("nan(1234)", "%e", &f);
+ sscanf("nan(1234)", "%le", &d);
+ sscanf("nan(1234)", "%Le", &ld);
+ feclearexcept(FE_ALL_EXCEPT);
+ ATF_REQUIRE(f != f);
+ ATF_REQUIRE(d != d);
+ ATF_REQUIRE(ld != ld);
+ /* POSIX says we should only generate quiet NaNs. */
+ ATF_REQUIRE(fetestexcept(FE_INVALID) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(rounding_tests);
+ATF_TC_BODY(rounding_tests, tc)
+{
+ long double ld = 0.0;
+ double d = 0.0;
+
+ ATF_REQUIRE(setlocale(LC_NUMERIC, "C"));
+
+ fesetround(FE_DOWNWARD);
+
+ sscanf("1.999999999999999999999999999999999", "%le", &d);
+ ATF_REQUIRE(d < 2.0);
+ sscanf("0x1.ffffffffffffffp0", "%le", &d);
+ ATF_REQUIRE(d < 2.0);
+ sscanf("1.999999999999999999999999999999999", "%Le", &ld);
+ ATF_REQUIRE(ld < 2.0);
+
+ sscanf("1.0571892669084007", "%le", &d);
+ ATF_REQUIRE(d == 0x1.0ea3f4af0dc59p0);
+ sscanf("-1.0571892669084007", "%le", &d);
+ ATF_REQUIRE(d == -0x1.0ea3f4af0dc5ap0);
+ sscanf("1.0571892669084010", "%le", &d);
+ ATF_REQUIRE(d == 0x1.0ea3f4af0dc5ap0);
+
+ sscanf("0x1.23p-5000", "%le", &d);
+ ATF_REQUIRE(d == 0.0);
+
+ sscanf("0x1.2345678p-1050", "%le", &d);
+ ATF_REQUIRE(d == 0x1.234567p-1050);
+
+ fesetround(FE_UPWARD);
+
+ sscanf("1.0571892669084007", "%le", &d);
+ ATF_REQUIRE(d == 0x1.0ea3f4af0dc5ap0);
+ sscanf("-1.0571892669084007", "%le", &d);
+ ATF_REQUIRE(d == -0x1.0ea3f4af0dc59p0);
+ sscanf("1.0571892669084010", "%le", &d);
+ ATF_REQUIRE(d == 0x1.0ea3f4af0dc5bp0);
+
+ sscanf("0x1.23p-5000", "%le", &d);
+ ATF_REQUIRE(d == 0x1p-1074);
+
+ sscanf("0x1.2345678p-1050", "%le", &d);
+ ATF_REQUIRE(d == 0x1.234568p-1050);
+
+ fesetround(FE_TOWARDZERO);
+
+ sscanf("1.0571892669084007", "%le", &d);
+ ATF_REQUIRE(d == 0x1.0ea3f4af0dc59p0);
+ sscanf("-1.0571892669084007", "%le", &d);
+ ATF_REQUIRE(d == -0x1.0ea3f4af0dc59p0);
+ sscanf("1.0571892669084010", "%le", &d);
+ ATF_REQUIRE(d == 0x1.0ea3f4af0dc5ap0);
+
+ sscanf("0x1.23p-5000", "%le", &d);
+ ATF_REQUIRE(d == 0.0);
+
+ sscanf("0x1.2345678p-1050", "%le", &d);
+ ATF_REQUIRE(d == 0x1.234567p-1050);
+
+ fesetround(FE_TONEAREST);
+
+ /* 1.0571892669084007 is slightly closer to 0x1.0ea3f4af0dc59p0 */
+ sscanf("1.0571892669084007", "%le", &d);
+ ATF_REQUIRE(d == 0x1.0ea3f4af0dc59p0);
+ sscanf("-1.0571892669084007", "%le", &d);
+ ATF_REQUIRE(d == -0x1.0ea3f4af0dc59p0);
+ sscanf("1.0571892669084010", "%le", &d);
+ ATF_REQUIRE(d == 0x1.0ea3f4af0dc5bp0);
+
+ /* strtod() should round small numbers to 0. */
+ sscanf("0x1.23p-5000", "%le", &d);
+ ATF_REQUIRE(d == 0.0);
+
+ /* Extra digits in a denormal shouldn't break anything. */
+ sscanf("0x1.2345678p-1050", "%le", &d);
+ ATF_REQUIRE(d == 0x1.234568p-1050);
+}
+
+ATF_TC_WITHOUT_HEAD(strtod);
+ATF_TC_BODY(strtod, tc)
+{
+ char *endp;
+
+ ATF_REQUIRE(setlocale(LC_NUMERIC, "C"));
+
+ ATF_REQUIRE(strtod("0xy", &endp) == 0);
+ ATF_REQUIRE(strcmp("xy", endp) == 0);
+
+ /* This used to cause an infinite loop and round the wrong way. */
+ fesetround(FE_DOWNWARD);
+ ATF_REQUIRE(strtof("3.5e38", &endp) == FLT_MAX);
+ ATF_REQUIRE(strtod("2e308", &endp) == DBL_MAX);
+ fesetround(FE_UPWARD);
+ ATF_REQUIRE(strtof("3.5e38", &endp) == INFINITY);
+ ATF_REQUIRE(strtod("2e308", &endp) == INFINITY);
+ fesetround(FE_TOWARDZERO);
+ ATF_REQUIRE(strtof("3.5e38", &endp) == FLT_MAX);
+ ATF_REQUIRE(strtod("2e308", &endp) == DBL_MAX);
+ fesetround(FE_TONEAREST);
+ ATF_REQUIRE(strtof("3.5e38", &endp) == INFINITY);
+ ATF_REQUIRE(strtod("2e308", &endp) == INFINITY);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, normalized_numbers);
+ ATF_TP_ADD_TC(tp, infinities_and_nans);
+ ATF_TP_ADD_TC(tp, rounding_tests);
+ ATF_TP_ADD_TC(tp, strtod);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/stdlib/Makefile b/lib/libc/tests/stdlib/Makefile
index 187ca5b..cd2c06e 100644
--- a/lib/libc/tests/stdlib/Makefile
+++ b/lib/libc/tests/stdlib/Makefile
@@ -1,9 +1,11 @@
# $FreeBSD$
-.include <bsd.own.mk>
+ATF_TESTS_C+= heapsort_test
+ATF_TESTS_C+= mergesort_test
+ATF_TESTS_C+= qsort_test
# TODO: t_getenv_thread, t_mi_vector_hash
-NETBSD_ATF_TESTS_C= abs_test
+NETBSD_ATF_TESTS_C+= abs_test
NETBSD_ATF_TESTS_C+= atoi_test
NETBSD_ATF_TESTS_C+= div_test
NETBSD_ATF_TESTS_C+= getenv_test
@@ -28,6 +30,8 @@ BINDIR= ${TESTSDIR}
#PROGS+= h_atexit
PROGS+= h_getopt h_getopt_long
+CFLAGS+= -I${.CURDIR}
+
.for t in h_getopt h_getopt_long
CFLAGS.$t+= -I${LIBNETBSD_SRCDIR} -I${SRCTOP}/contrib/netbsd-tests
LDFLAGS.$t+= -L${LIBNETBSD_OBJDIR}
diff --git a/lib/libc/tests/stdlib/heapsort_test.c b/lib/libc/tests/stdlib/heapsort_test.c
new file mode 100644
index 0000000..a83786d
--- /dev/null
+++ b/lib/libc/tests/stdlib/heapsort_test.c
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (C) 2004 Maxim Sobolev <sobomax@FreeBSD.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.
+ */
+
+/*
+ * Test for heapsort() routine.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "test-sort.h"
+
+ATF_TC_WITHOUT_HEAD(heapsort_test);
+ATF_TC_BODY(heapsort_test, tc)
+{
+ int sresvector[IVEC_LEN];
+ int testvector[IVEC_LEN];
+ int i, j;
+
+ for (j = 2; j < IVEC_LEN; j++) {
+ /* Populate test vectors */
+ for (i = 0; i < j; i++)
+ testvector[i] = sresvector[i] = initvector[i];
+
+ /* Sort using heapsort(3) */
+ heapsort(testvector, j, sizeof(testvector[0]), sorthelp);
+ /* Sort using reference slow sorting routine */
+ ssort(sresvector, j);
+
+ /* Compare results */
+ for (i = 0; i < j; i++)
+ ATF_CHECK_MSG(testvector[i] == sresvector[i],
+ "item at index %d didn't match: %d != %d",
+ i, testvector[i], sresvector[i]);
+ }
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, heapsort_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/stdlib/mergesort_test.c b/lib/libc/tests/stdlib/mergesort_test.c
new file mode 100644
index 0000000..4334b92
--- /dev/null
+++ b/lib/libc/tests/stdlib/mergesort_test.c
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (C) 2004 Maxim Sobolev <sobomax@FreeBSD.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.
+ */
+
+/*
+ * Test for mergesort() routine.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "test-sort.h"
+
+ATF_TC_WITHOUT_HEAD(mergesort_test);
+ATF_TC_BODY(mergesort_test, tc)
+{
+ int sresvector[IVEC_LEN];
+ int testvector[IVEC_LEN];
+ int i, j;
+
+ for (j = 2; j < IVEC_LEN; j++) {
+ /* Populate test vectors */
+ for (i = 0; i < j; i++)
+ testvector[i] = sresvector[i] = initvector[i];
+
+ /* Sort using mergesort(3) */
+ mergesort(testvector, j, sizeof(testvector[0]), sorthelp);
+ /* Sort using reference slow sorting routine */
+ ssort(sresvector, j);
+
+ /* Compare results */
+ for (i = 0; i < j; i++)
+ ATF_CHECK_MSG(testvector[i] == sresvector[i],
+ "item at index %d didn't match: %d != %d",
+ i, testvector[i], sresvector[i]);
+ }
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, mergesort_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/stdlib/qsort_test.c b/lib/libc/tests/stdlib/qsort_test.c
new file mode 100644
index 0000000..14e0292
--- /dev/null
+++ b/lib/libc/tests/stdlib/qsort_test.c
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (C) 2004 Maxim Sobolev <sobomax@FreeBSD.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.
+ */
+
+/*
+ * Test for qsort() routine.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "test-sort.h"
+
+ATF_TC_WITHOUT_HEAD(qsort_test);
+ATF_TC_BODY(qsort_test, tc)
+{
+ int testvector[IVEC_LEN];
+ int sresvector[IVEC_LEN];
+ int i, j;
+
+ for (j = 2; j < IVEC_LEN; j++) {
+ /* Populate test vectors */
+ for (i = 0; i < j; i++)
+ testvector[i] = sresvector[i] = initvector[i];
+
+ /* Sort using qsort(3) */
+ qsort(testvector, j, sizeof(testvector[0]), sorthelp);
+ /* Sort using reference slow sorting routine */
+ ssort(sresvector, j);
+
+ /* Compare results */
+ for (i = 0; i < j; i++)
+ ATF_CHECK_MSG(testvector[i] == sresvector[i],
+ "item at index %d didn't match: %d != %d",
+ i, testvector[i], sresvector[i]);
+ }
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, qsort_test);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/stdlib/test-sort.h b/lib/libc/tests/stdlib/test-sort.h
new file mode 100644
index 0000000..f038acd
--- /dev/null
+++ b/lib/libc/tests/stdlib/test-sort.h
@@ -0,0 +1,273 @@
+/*-
+ * Copyright (C) 2004 Maxim Sobolev <sobomax@FreeBSD.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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _TEST_SORT_H
+#define _TEST_SORT_H
+
+#include <sys/param.h>
+
+#include <atf-c.h>
+
+static int
+sorthelp(const void *a, const void *b)
+{
+ const int *oa, *ob;
+
+ oa = a;
+ ob = b;
+ /* Don't use "return *oa - *ob" since it's easy to cause overflow! */
+ if (*oa > *ob)
+ return (1);
+ if (*oa < *ob)
+ return (-1);
+ return (0);
+}
+
+/* Reference sorting routine (slooow!) */
+static void
+ssort(int v[], int nmemb)
+{
+ int i, j, k;
+
+ for (i = 0; i < nmemb; i++) {
+ for (j = i + 1; j < nmemb; j++) {
+ if (v[j] < v[i]) {
+ k = v[i];
+ v[i] = v[j];
+ v[j] = k;
+ }
+ }
+ }
+}
+
+/* Some random data */
+static int initvector[1024] = {
+ 599853225, 371951333, -428880425, 1450668530, 85530178, -460170550,
+ -270680269, 717137591, 106244401, -1138072905, -113532586,
+ 599690958, 464993720, 107690177, 24249019, -1151018550, 794225588,
+ 1494905642, -62951716, -734531757, 1197251494, 1020063925,
+ -634536734, -216634704, 617366508, -18840190, 481010395,
+ -1555785724, 128221950, -1747743676, 1119012320, -252160437,
+ 617137855, 1159833073, -106647920, -1570719046, -769400990,
+ -130308848, 1186546396, 215253591, 445832488, 160263176, 777264170,
+ -274636650, -696134447, 1057957088, -626175254, 188632134,
+ -98941793, -1602334908, -373717125, 885013862, 571258221,
+ -399572192, 407761463, -733249776, 12094800, -367046815, 178974501,
+ -452638559, -516580143, -94282073, 1411115180, -1151792797,
+ 1442815268, 1106583674, 515269284, -74019972, 598818901, 696848474,
+ -657910766, -287309335, 1538095746, 143543003, 851444033,
+ -947573348, 296222973, 1339592140, -947505360, 872027891,
+ -418844714, -583075597, -324758197, -964531573, 1016795914,
+ -866842580, -304084402, -286930819, 338975583, 803597943,
+ -452483372, 1525283506, -1185830826, -596405894, 905191340,
+ -1638026278, 106749913, 582771197, -730713796, 56052422,
+ 1498040174, 644967266, 182541575, 280483468, -1932835017,
+ -435546874, 940106007, 1753388509, -340355019, -231577358,
+ -714879035, 1051182949, 204261785, 1321346243, -895289878,
+ -240369893, 566608506, -350777580, -1384849829, -876816409,
+ 1013787299, -1408035937, -222626650, 1708168486, -645148461,
+ 1854654, -393012507, 179327030, -1607975548, -715202732, 730588290,
+ 246968517, -550975254, -101136772, -174103176, 1188941016,
+ 2004650834, -1501389866, -2021225998, 1219042515, -464113898,
+ 268565342, 126451123, -1045877126, -198918003, 310177444,
+ 1578314812, 1828867082, 453336898, -908485523, 749777130,
+ -1028565802, 61360571, 241484853, -175693399, 1816211059,
+ 533940889, -1496933703, 385185125, -821132413, -8923391,
+ -1429546239, 46190992, 449247332, -20432494, 778761611, -178782699,
+ -811194695, -632276211, 70196094, 890817525, -1447776908,
+ -323783741, -62333222, 954929503, 247668507, -1394420605,
+ 367913886, 1364926759, 1298781924, 357923028, -73644747,
+ -319744305, 61718202, -1454549286, 387493522, 2018321449,
+ 861026653, 289973298, 1755939093, -84772204, 43425266, -1325753781,
+ -679938775, 1228500370, -763816405, 548903035, 1765563727,
+ 425183052, 1424621863, -188287424, 554385654, 751831998,
+ 1377088085, 66622090, 139224450, -1305816167, 650140724, 593988868,
+ -444913321, 589045097, 1261428989, 101292769, -780376786,
+ 559307348, 1644593236, -1838606833, 53570301, -680576100,
+ -44969538, 268718267, -632104125, 276904628, 626299449, -11761453,
+ 545899086, -1027343598, -432251872, 539353494, -399575006,
+ -568383580, -677802882, 1296513472, 801202048, 806425805, 1983363,
+ 850487421, 38046173, 1535399484, 1998285544, -1301751898,
+ -46561973, 56545408, -1107662676, 456041145, -452923904,
+ -262219453, -371849200, 392524281, 1650231392, 1185585356,
+ 126610511, -1125389657, 1015981177, -1318481342, -213835789,
+ 1263484054, -654361441, 1408272041, -231555284, -1121778152,
+ -395512897, 332277674, -349703586, 1809474399, -223731607,
+ -1342224737, 736165236, 67535587, 89879082, 471445838, 423788300,
+ -384354470, 907475706, 154886390, -1406736539, -8558766,
+ -203405718, -422127884, 1048520863, 747418501, 87438975, 727668160,
+ -914936981, 428266976, -455742009, -949014605, 487159058,
+ -262526850, -309451504, -76928461, 1072951428, -1370953830,
+ 238231681, -1831047244, -405735199, -35941848, 469048670,
+ 505307987, -660553590, 876537439, -314195871, 999234339,
+ -1405846240, -579885695, 629067031, 863481510, -742301385,
+ -1723403128, -153070386, 782682839, -343111818, -877101810,
+ 1438467302, -319951459, -1585702508, -338381888, 484108815,
+ -1726935191, -749923706, 1657932127, -816151395, -566321865,
+ -133542331, 84961164, 598275578, 1302065347, -533098653,
+ -1766383037, 53169714, -464201288, 617735133, 862536123,
+ -141730724, -1967377125, -1023736305, -1012511106, 64484992,
+ -1250856831, 426409332, -355670055, -298251663, -867634978,
+ -776124819, 74018333, -425385214, -108004251, -1192766130,
+ 1294193867, -109867195, -78667637, 1164855393, -826007552,
+ -522528066, 1160283046, -1095276403, -1218917472, -396475366,
+ -77394733, -425603169, 251928357, -393559355, 1488845184,
+ 898455978, -773338691, -37627855, -345014717, 204298578, 209084274,
+ 1047080643, -414348222, 26496664, 705759824, 575149152, 604904761,
+ 624988690, 1446041250, 1000757225, -1354896151, 1422958189,
+ -1607165311, -832757521, 365074225, 1171764999, 1200795217,
+ -203957828, 23166236, -846818698, -547439867, -790192498,
+ -122123561, 914298013, 66225525, -36163174, -480698856,
+ -1269421818, 624641703, 254923102, 1564329013, -583609221,
+ -649433551, -743396069, 1182455435, 102658744, 285599336,
+ 692480463, -852737563, -660090184, 1374350065, 72300985, 690541659,
+ -1194212957, -1151816525, 157415641, 487398246, 1030153072,
+ 933723020, 1359181027, -1303457764, -1543773272, 774306017,
+ -854382652, 755485667, -864943584, -63242545, -1271480354,
+ 157720215, -205001173, 889984130, -581583822, -473779111,
+ -932136577, 735326252, 428638717, 1888884222, 561493709,
+ -1966427364, -1710208603, 340121869, 918894036, 927172509,
+ 904178436, 1476687667, 90796414, 651591731, -550913123, -42218158,
+ 637756529, 1091478400, 124976584, -48739309, -798898083, 393581349,
+ -1078624722, -789291577, 1010582542, -512317005, 1222773656,
+ 466454593, 1183558811, 822782663, -851624703, -850404012,
+ 1473672600, 852527073, 1073953362, 137635828, 936104739, -86567759,
+ -882563252, 1845232980, -737978404, -104703380, 149802989,
+ -349118325, 1479797538, 1966007488, 1254228842, 414304661,
+ -790805785, 31583329, -76864151, 558202855, -1447047313, 716720607,
+ -404224238, -54107627, 1747385914, -657407390, 202940208,
+ 1083067056, -532861378, 163426933, -130289277, 1301785258,
+ -302920320, -637947485, -644895903, -1668027530, 391890467,
+ -126586485, -536836984, -1154536413, -339505118, -1187229462,
+ -670985870, -601310813, -1350055158, -482479784, 139847714,
+ -253955849, 5190414, -542857077, 1175835684, -584165057,
+ 1132775766, -592091269, -891445655, -340995936, 736395810,
+ 779967964, 515095845, -1138437307, -259226729, -167820100,
+ -801611617, -282451622, -1313679283, -1436126694, 1258773990,
+ -717601098, -583559645, -1307478759, 1238647247, 1589011223,
+ -1029216445, -107030650, 400152690, -1349079913, 1428582247,
+ 21546946, 208807686, -169450574, -1086213374, -1242715198,
+ 669098277, 416626722, -1122525014, -1389466669, -391843085,
+ -56318357, 421040094, 212303518, 738666684, -1185364904,
+ -506192760, 646735912, -1424722633, 745226976, 1019191717,
+ -190891744, -310320868, -373655022, -665117060, 830760000,
+ 583906512, -330536027, 611092636, -321344259, -1255008904,
+ -777959046, -523043472, 88896910, 346062204, -163734816, 336635665,
+ 906060268, -128891583, 740952564, 916767203, 296514859, 198670559,
+ 358136672, -152253676, 12038867, -1469916749, -1020980597,
+ -897143313, 354240970, -97959800, 814172811, 1983363241, 264990663,
+ 105154676, 1060463014, 430172143, 375111946, -824526943,
+ -708877751, -1377442616, -236559551, 684724584, 1602131358,
+ -42140186, -763499840, -605167, 98575879, -376577598, 1689746083,
+ -777973879, -1396984691, -187780326, 281040966, 1858859521,
+ 158395760, 1022807978, -218458812, 811779708, 1495113833,
+ 1192561226, 629539535, -1365196683, -1120253162, 1091681956,
+ 134286445, 1172218369, -34093658, -137087343, -27869226,
+ -180889478, 55705436, 52362743, -1745516232, -926564477,
+ -513701675, -1666272054, 1457952810, 843953275, -478275722,
+ -1240291080, 101859661, -1606687523, 916365333, 314713310,
+ -22002688, 1019022641, -1171741314, -129050627, -211955813,
+ -1020176299, 1357865293, -609819628, 724533854, -1141449545,
+ 22285231, -97731145, -302329687, 191910894, -1300709885,
+ -644951895, 640448036, -1289009824, 1445456129, 846416471,
+ 1821291740, -1639640821, -712724532, -447475807, 132156847,
+ 258067455, 324301319, 278586969, -1544082357, 636007277, 977122066,
+ 127462480, 365126129, 1086276825, -432124148, 896598926,
+ -388550179, 273357331, -845018695, -1089465389, 384439820,
+ -558419772, 1476422025, 730712769, 190665059, -764968927,
+ -789708218, 637873581, 348429858, 1386000168, -638123594,
+ -842010345, -607926448, 19535163, -742771490, -18323344, 246155488,
+ 350409468, 1290907730, -492566468, 300358636, 501876267, 252441807,
+ 1233551975, -1431067042, 517177374, -1540299707, -948380761,
+ 1253997663, 693795998, 148707823, 152894502, 98729538, -30042824,
+ -563057441, 723726409, 367338961, 1395435261, 217868876,
+ 1220652431, 953572083, -1134905155, -734486813, -587470130,
+ -864647866, 1030737023, 781798521, -321076732, -460548153,
+ 122681678, -873728847, -1286304399, -75472885, 113390881,
+ -1556849198, -1070802176, 924389470, 957478910, 5974049, 709413506,
+ 476334647, 572869787, 776298405, -8822420, -99326499, -707855342,
+ -1187216303, 668038414, 262454769, -1120293198, -32011040,
+ 249812104, -101835410, 1082281087, -570183855, -954535179,
+ 1384361473, -983199686, 2017611313, 328926483, -878162849,
+ -1202254181, -225604951, 966898955, 247213529, -1257544612,
+ -197005970, -1039902730, -1947925142, 1752780907, -313410699,
+ -464474556, 416580338, -1063356643, -292212702, 57509168,
+ 1034124629, 1059212593, 468522867, 845369497, 1872717306,
+ -1216544764, -1419907623, 1376869956, -66585488, -1590974467,
+ -367070705, -1456529060, 791844031, 336217635, -1106832215,
+ 1476739427, -751018210, -1411671555, -1880387375, -1714242595,
+ 1169006474, -479442380, -892267555, -1471250266, -267888858,
+ 808634418, 1324777189, -585449929, 1127186951, 468768901,
+ -2002989138, -52352849, 186493053, 1258464606, 117157186,
+ 445919258, 908401949, -1112221136, 863904453, -942718649,
+ 796754809, -38943966, -781978872, -56814078, 1273857459,
+ -1781920832, 209979504, 811828269, -1150814437, 850061883,
+ -532968763, 252506408, -885025629, 391567580, -1295702482,
+ 574894420, 1462248349, 1622584325, -88443443, -1122006092,
+ -169758578, 456282338, -443233309, 436693483, -956563815,
+ -480221349, 435252860, -1114099391, 1060053979, -470893945,
+ -1273682879, -734596176, 639950927, -1278648701, 306274747,
+ -410562146, 1137869228, -1970746553, 1313830798, 1248071822,
+ -247297704, 1015218053, -1607348116, -261817613, -821413148,
+ -782942639, -628711083, 240953091, -629550668, -1584736319,
+ 856616893, -186759752, 197905373, 541638393, 603407919, -278480495,
+ 410077039, 544065371, -1509627427, 402918436, -450463799,
+ -131169308, 249920630, 1079548609, -927911828, 1444577689,
+ -353002528, -224292462, 1247795279, -790844631, -40427503,
+ 59829765, -332587567, 1319862109, -1261340753, 121711726,
+ 1342756342, -643495787, 100326201, -934436714, -69134888,
+ -898880561, -379524737, -577234570, -805827092, -1575493557,
+ -289920678, -476605057, 1235714994, -317239591, 418553949,
+ 410053338, -204985448, 1206503615, 202610372, -932244873,
+ 782207875, -288661931, -806814809, 1270953679, 2060991595,
+ -311412846, 327279979, 1148562672, 55239149, -610114433,
+ -1511688434, 87619740, -433503545, 326150519, -581293393,
+ -97417688, -289736140, -1543886029, -1251976119, 1585774446,
+ 1570011421, 432602745, 486343696, -834680922, 265004849,
+ -1132107706, 502627197, -815873818, 249635389, 1985714127,
+ -1095817653, -130743522, -645266828, -334621094, 199921747,
+ 1059256177, 378031303, 1519740920, 925540689, 1405957844,
+ 1387748290, -56138046, -770637828, -187984510, -1361735163,
+ 1294823206, -608941238, 451860688, -510549867, 1143516283,
+ -779090703, 1459305047, -600335915, -1684168049, 1516622316,
+ -631733335, -4360068, 499778796, 587600402, -1296000335, -37959743,
+ -1084203927, 1162902556, 246374600, -515103645, 341724568,
+ -702303954, 452229900, 485108287, 1170048553, -1510148355,
+ 611133912, 1997927484, -142022671, -724776653, -336090522,
+ 708283514, -1409637378, -2052637687, 376055110, 226628105,
+ -1714452033, -1776158002, 369167930, 1800807012, 710680889,
+ -69951947, -1223849766, -1862239787, 218536127, -656411794,
+ -1202269188, 609634805, -224425858, 519797951, 284223080,
+ 869408930, 270750206, -544967439, 2097168510, 31650971, -600985417,
+ -165303097, -257809088, -1043223971, 1827891621, -156827355,
+ 499719603
+};
+
+#define IVEC_LEN (nitems(initvector))
+
+#endif
diff --git a/lib/libc/tests/string/Makefile b/lib/libc/tests/string/Makefile
index d91af08..14044f4 100644
--- a/lib/libc/tests/string/Makefile
+++ b/lib/libc/tests/string/Makefile
@@ -1,31 +1,36 @@
# $FreeBSD$
-.include <bsd.own.mk>
+ATF_TESTS_C+= stpncpy_test
+ATF_TESTS_C+= strerror2_test
+ATF_TESTS_C+= wcscasecmp_test
+ATF_TESTS_C+= wcsnlen_test
# TODO: popcount, stresep
-NETBSD_ATF_TESTS_C+= memchr
-NETBSD_ATF_TESTS_C+= memcpy
-NETBSD_ATF_TESTS_C+= memmem
-NETBSD_ATF_TESTS_C+= memset
-NETBSD_ATF_TESTS_C+= strcat
-NETBSD_ATF_TESTS_C+= strchr
-NETBSD_ATF_TESTS_C+= strcmp
-NETBSD_ATF_TESTS_C+= strcpy
-NETBSD_ATF_TESTS_C+= strcspn
-NETBSD_ATF_TESTS_C+= strerror
-NETBSD_ATF_TESTS_C+= strlen
-NETBSD_ATF_TESTS_C+= strpbrk
-NETBSD_ATF_TESTS_C+= strrchr
-NETBSD_ATF_TESTS_C+= strspn
-NETBSD_ATF_TESTS_C+= swab
+NETBSD_ATF_TESTS_C+= memchr_test
+NETBSD_ATF_TESTS_C+= memcpy_test
+NETBSD_ATF_TESTS_C+= memmem_test
+NETBSD_ATF_TESTS_C+= memset_test
+NETBSD_ATF_TESTS_C+= strcat_test
+NETBSD_ATF_TESTS_C+= strchr_test
+NETBSD_ATF_TESTS_C+= strcmp_test
+NETBSD_ATF_TESTS_C+= strcpy_test
+NETBSD_ATF_TESTS_C+= strcspn_test
+NETBSD_ATF_TESTS_C+= strerror_test
+NETBSD_ATF_TESTS_C+= strlen_test
+NETBSD_ATF_TESTS_C+= strpbrk_test
+NETBSD_ATF_TESTS_C+= strrchr_test
+NETBSD_ATF_TESTS_C+= strspn_test
+NETBSD_ATF_TESTS_C+= swab_test
+
+SRCS.strerror2_test= strerror_test.c
.include "../Makefile.netbsd-tests"
-LDADD.memchr+= -lmd
-DPADD.memchr+= ${LIBMD}
+LDADD.memchr_test+= -lmd
+DPADD.memchr_test+= ${LIBMD}
-LDADD.memcpy+= -lmd
-DPADD.memcpy+= ${LIBMD}
+LDADD.memcpy_test+= -lmd
+DPADD.memcpy_test+= ${LIBMD}
.include <bsd.test.mk>
diff --git a/lib/libc/tests/string/stpncpy_test.c b/lib/libc/tests/string/stpncpy_test.c
new file mode 100644
index 0000000..0a7b1d2
--- /dev/null
+++ b/lib/libc/tests/string/stpncpy_test.c
@@ -0,0 +1,110 @@
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/mman.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <atf-c.h>
+
+static char *
+makebuf(size_t len, int guard_at_end)
+{
+ char *buf;
+ size_t alloc_size = roundup2(len, PAGE_SIZE) + PAGE_SIZE;
+
+ buf = mmap(NULL, alloc_size, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0);
+ assert(buf);
+ if (guard_at_end) {
+ assert(munmap(buf + alloc_size - PAGE_SIZE, PAGE_SIZE) == 0);
+ return (buf + alloc_size - PAGE_SIZE - len);
+ } else {
+ assert(munmap(buf, PAGE_SIZE) == 0);
+ return (buf + PAGE_SIZE);
+ }
+}
+
+static void
+test_stpncpy(const char *s)
+{
+ char *src, *dst;
+ size_t size, len, bufsize, x;
+ int i, j;
+
+ size = strlen(s) + 1;
+ for (i = 0; i <= 1; i++) {
+ for (j = 0; j <= 1; j++) {
+ for (bufsize = 0; bufsize <= size + 10; bufsize++) {
+ src = makebuf(size, i);
+ memcpy(src, s, size);
+ dst = makebuf(bufsize, j);
+ memset(dst, 'X', bufsize);
+ len = (bufsize < size) ? bufsize : size - 1;
+ assert(stpncpy(dst, src, bufsize) == dst+len);
+ assert(memcmp(src, dst, len) == 0);
+ for (x = len; x < bufsize; x++)
+ assert(dst[x] == '\0');
+ }
+ }
+ }
+}
+
+ATF_TC_WITHOUT_HEAD(nul);
+ATF_TC_BODY(nul, tc)
+{
+
+ test_stpncpy("");
+}
+
+ATF_TC_WITHOUT_HEAD(foo);
+ATF_TC_BODY(foo, tc)
+{
+
+ test_stpncpy("foo");
+}
+
+ATF_TC_WITHOUT_HEAD(glorp);
+ATF_TC_BODY(glorp, tc)
+{
+
+ test_stpncpy("glorp");
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, nul);
+ ATF_TP_ADD_TC(tp, foo);
+ ATF_TP_ADD_TC(tp, glorp);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/string/strerror_test.c b/lib/libc/tests/string/strerror_test.c
new file mode 100644
index 0000000..51bbf17
--- /dev/null
+++ b/lib/libc/tests/string/strerror_test.c
@@ -0,0 +1,206 @@
+/*-
+ * Copyright (c) 2001 Wes Peters <wes@FreeBSD.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.
+ *
+ * $FreeBSD$
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <atf-c.h>
+
+static char buf[64];
+static char *sret;
+static int iret;
+
+ATF_TC_WITHOUT_HEAD(strerror_unknown_error);
+ATF_TC_BODY(strerror_unknown_error, tc)
+{
+
+ errno = 0;
+ sret = strerror(INT_MAX);
+ snprintf(buf, sizeof(buf), "Unknown error: %d", INT_MAX);
+ ATF_CHECK(strcmp(sret, buf) == 0);
+ ATF_CHECK(errno == EINVAL);
+}
+
+ATF_TC_WITHOUT_HEAD(strerror_no_error);
+ATF_TC_BODY(strerror_no_error, tc)
+{
+
+ errno = 0;
+ sret = strerror(0);
+ ATF_CHECK(strcmp(sret, "No error: 0") == 0);
+ ATF_CHECK(errno == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(strerror_EPERM_test);
+ATF_TC_BODY(strerror_EPERM_test, tc)
+{
+
+ errno = 0;
+ sret = strerror(EPERM);
+ ATF_CHECK(strcmp(sret, "Operation not permitted") == 0);
+ ATF_CHECK(errno == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(strerror_EPFNOSUPPORT_test);
+ATF_TC_BODY(strerror_EPFNOSUPPORT_test, tc)
+{
+
+ errno = 0;
+ sret = strerror(EPFNOSUPPORT);
+ ATF_CHECK(strcmp(sret, "Protocol family not supported") == 0);
+ ATF_CHECK(errno == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(strerror_ELAST_test);
+ATF_TC_BODY(strerror_ELAST_test, tc)
+{
+
+ errno = 0;
+ sret = strerror(ELAST);
+ ATF_CHECK(errno == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(strerror_r__unknown_error);
+ATF_TC_BODY(strerror_r__unknown_error, tc)
+{
+
+ memset(buf, '*', sizeof(buf));
+ iret = strerror_r(-1, buf, sizeof(buf));
+ ATF_CHECK(strcmp(buf, "Unknown error: -1") == 0);
+ ATF_CHECK(iret == EINVAL);
+}
+
+ATF_TC_WITHOUT_HEAD(strerror_r__EPERM_one_byte_short);
+ATF_TC_BODY(strerror_r__EPERM_one_byte_short, tc)
+{
+
+ memset(buf, '*', sizeof(buf));
+ /* One byte too short. */
+ iret = strerror_r(EPERM, buf, strlen("Operation not permitted"));
+ ATF_CHECK(strcmp(buf, "Operation not permitte") == 0);
+ ATF_CHECK(iret == ERANGE);
+}
+
+ATF_TC_WITHOUT_HEAD(strerror_r__EPERM_unknown_error_one_byte_short);
+ATF_TC_BODY(strerror_r__EPERM_unknown_error_one_byte_short, tc)
+{
+
+ memset(buf, '*', sizeof(buf));
+ /* One byte too short. */
+ iret = strerror_r(-1, buf, strlen("Unknown error: -1"));
+ ATF_CHECK(strcmp(buf, "Unknown error: -") == 0);
+ ATF_CHECK(iret == EINVAL);
+}
+
+ATF_TC_WITHOUT_HEAD(strerror_r__EPERM_unknown_error_two_bytes_short);
+ATF_TC_BODY(strerror_r__EPERM_unknown_error_two_bytes_short, tc)
+{
+
+ memset(buf, '*', sizeof(buf));
+ /* Two bytes too short. */
+ iret = strerror_r(-2, buf, strlen("Unknown error: -2") - 1);
+ ATF_CHECK(strcmp(buf, "Unknown error: ") == 0);
+ ATF_CHECK(iret == EINVAL);
+}
+
+ATF_TC_WITHOUT_HEAD(strerror_r__EPERM_unknown_error_three_bytes_short);
+ATF_TC_BODY(strerror_r__EPERM_unknown_error_three_bytes_short, tc)
+{
+
+ memset(buf, '*', sizeof(buf));
+ /* Three bytes too short. */
+ iret = strerror_r(-2, buf, strlen("Unknown error: -2") - 2);
+ ATF_CHECK(strcmp(buf, "Unknown error:") == 0);
+ ATF_CHECK(iret == EINVAL);
+}
+
+ATF_TC_WITHOUT_HEAD(strerror_r__EPERM_unknown_error_12345_one_byte_short);
+ATF_TC_BODY(strerror_r__EPERM_unknown_error_12345_one_byte_short, tc)
+{
+
+ memset(buf, '*', sizeof(buf));
+ /* One byte too short. */
+ iret = strerror_r(12345, buf, strlen("Unknown error: 12345"));
+ ATF_CHECK(strcmp(buf, "Unknown error: 1234") == 0);
+ ATF_CHECK(iret == EINVAL);
+}
+
+ATF_TC_WITHOUT_HEAD(strerror_r__no_error);
+ATF_TC_BODY(strerror_r__no_error, tc)
+{
+
+ memset(buf, '*', sizeof(buf));
+ iret = strerror_r(0, buf, sizeof(buf));
+ ATF_CHECK(strcmp(buf, "No error: 0") == 0);
+ ATF_CHECK(iret == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(strerror_r__EDEADLK);
+ATF_TC_BODY(strerror_r__EDEADLK, tc)
+{
+
+ memset(buf, '*', sizeof(buf));
+ iret = strerror_r(EDEADLK, buf, sizeof(buf));
+ ATF_CHECK(strcmp(buf, "Resource deadlock avoided") == 0);
+ ATF_CHECK(iret == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(strerror_r__EPROCLIM);
+ATF_TC_BODY(strerror_r__EPROCLIM, tc)
+{
+
+ memset(buf, '*', sizeof(buf));
+ iret = strerror_r(EPROCLIM, buf, sizeof(buf));
+ ATF_CHECK(strcmp(buf, "Too many processes") == 0);
+ ATF_CHECK(iret == 0);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, strerror_unknown_error);
+ ATF_TP_ADD_TC(tp, strerror_no_error);
+ ATF_TP_ADD_TC(tp, strerror_EPERM_test);
+ ATF_TP_ADD_TC(tp, strerror_EPFNOSUPPORT_test);
+ ATF_TP_ADD_TC(tp, strerror_ELAST_test);
+ ATF_TP_ADD_TC(tp, strerror_r__unknown_error);
+ ATF_TP_ADD_TC(tp, strerror_r__EPERM_one_byte_short);
+ ATF_TP_ADD_TC(tp, strerror_r__EPERM_unknown_error_one_byte_short);
+ ATF_TP_ADD_TC(tp, strerror_r__EPERM_unknown_error_two_bytes_short);
+ ATF_TP_ADD_TC(tp, strerror_r__EPERM_unknown_error_three_bytes_short);
+ ATF_TP_ADD_TC(tp, strerror_r__EPERM_unknown_error_12345_one_byte_short);
+ ATF_TP_ADD_TC(tp, strerror_r__no_error);
+ ATF_TP_ADD_TC(tp, strerror_r__EDEADLK);
+ ATF_TP_ADD_TC(tp, strerror_r__EPROCLIM);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/string/wcscasecmp_test.c b/lib/libc/tests/string/wcscasecmp_test.c
new file mode 100644
index 0000000..4385f3a
--- /dev/null
+++ b/lib/libc/tests/string/wcscasecmp_test.c
@@ -0,0 +1,128 @@
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include <atf-c.h>
+
+ATF_TC_WITHOUT_HEAD(nul);
+ATF_TC_BODY(nul, tc)
+{
+
+ ATF_REQUIRE(setlocale(LC_CTYPE, "C") != NULL);
+
+ ATF_CHECK(wcscasecmp(L"", L"") == 0);
+ ATF_CHECK(wcsncasecmp(L"", L"", 50) == 0);
+ ATF_CHECK(wcsncasecmp(L"", L"", 0) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(wcscasecmp_equal);
+ATF_TC_BODY(wcscasecmp_equal, tc)
+{
+
+ ATF_REQUIRE(setlocale(LC_CTYPE, "C") != NULL);
+
+ ATF_CHECK(wcscasecmp(L"abc", L"abc") == 0);
+ ATF_CHECK(wcscasecmp(L"ABC", L"ABC") == 0);
+ ATF_CHECK(wcscasecmp(L"abc", L"ABC") == 0);
+ ATF_CHECK(wcscasecmp(L"ABC", L"abc") == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(wcscasecmp_same_len_buffers);
+ATF_TC_BODY(wcscasecmp_same_len_buffers, tc)
+{
+
+ ATF_REQUIRE(setlocale(LC_CTYPE, "C") != NULL);
+
+ ATF_CHECK(wcscasecmp(L"abc", L"xyz") < 0);
+ ATF_CHECK(wcscasecmp(L"ABC", L"xyz") < 0);
+ ATF_CHECK(wcscasecmp(L"abc", L"XYZ") < 0);
+ ATF_CHECK(wcscasecmp(L"ABC", L"XYZ") < 0);
+ ATF_CHECK(wcscasecmp(L"xyz", L"abc") > 0);
+ ATF_CHECK(wcscasecmp(L"XYZ", L"abc") > 0);
+ ATF_CHECK(wcscasecmp(L"xyz", L"ABC") > 0);
+ ATF_CHECK(wcscasecmp(L"XYZ", L"ABC") > 0);
+}
+
+ATF_TC_WITHOUT_HEAD(wcscasecmp_mismatched_len_buffers);
+ATF_TC_BODY(wcscasecmp_mismatched_len_buffers, tc)
+{
+
+ ATF_REQUIRE(setlocale(LC_CTYPE, "C") != NULL);
+
+ ATF_CHECK(wcscasecmp(L"abc", L"ABCD") < 0);
+ ATF_CHECK(wcscasecmp(L"ABC", L"abcd") < 0);
+ ATF_CHECK(wcscasecmp(L"abcd", L"ABC") > 0);
+ ATF_CHECK(wcscasecmp(L"ABCD", L"abc") > 0);
+}
+
+ATF_TC_WITHOUT_HEAD(wcsncasecmp);
+ATF_TC_BODY(wcsncasecmp, tc)
+{
+
+ ATF_REQUIRE(setlocale(LC_CTYPE, "C") != NULL);
+
+ ATF_CHECK(wcsncasecmp(L"abc", L"ABCD", 4) < 0);
+ ATF_CHECK(wcsncasecmp(L"ABC", L"abcd", 4) < 0);
+ ATF_CHECK(wcsncasecmp(L"abcd", L"ABC", 4) > 0);
+ ATF_CHECK(wcsncasecmp(L"ABCD", L"abc", 4) > 0);
+ ATF_CHECK(wcsncasecmp(L"abc", L"ABCD", 3) == 0);
+ ATF_CHECK(wcsncasecmp(L"ABC", L"abcd", 3) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(wcscasecmp_greek);
+ATF_TC_BODY(wcscasecmp_greek, tc)
+{
+
+ ATF_REQUIRE(setlocale(LC_CTYPE, "C") != NULL);
+
+ ATF_CHECK(wcscasecmp(L"λ", L"Λ") != 0);
+ ATF_REQUIRE(setlocale(LC_CTYPE, "el_GR.UTF-8") != NULL);
+ ATF_CHECK(wcscasecmp(L"λ", L"Λ") == 0);
+ ATF_CHECK(wcscasecmp(L"λ", L"Ω") < 0);
+ ATF_CHECK(wcscasecmp(L"Ω", L"λ") > 0);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, nul);
+ ATF_TP_ADD_TC(tp, wcscasecmp_equal);
+ ATF_TP_ADD_TC(tp, wcscasecmp_same_len_buffers);
+ ATF_TP_ADD_TC(tp, wcscasecmp_mismatched_len_buffers);
+ ATF_TP_ADD_TC(tp, wcsncasecmp);
+ ATF_TP_ADD_TC(tp, wcscasecmp_greek);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/string/wcsnlen_test.c b/lib/libc/tests/string/wcsnlen_test.c
new file mode 100644
index 0000000..ec11938
--- /dev/null
+++ b/lib/libc/tests/string/wcsnlen_test.c
@@ -0,0 +1,104 @@
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/mman.h>
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include <atf-c.h>
+
+static void *
+makebuf(size_t len, int guard_at_end)
+{
+ char *buf;
+ size_t alloc_size = roundup2(len, PAGE_SIZE) + PAGE_SIZE;
+
+ buf = mmap(NULL, alloc_size, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0);
+ ATF_CHECK(buf);
+ if (guard_at_end) {
+ ATF_CHECK(munmap(buf + alloc_size - PAGE_SIZE, PAGE_SIZE) == 0);
+ return (buf + alloc_size - PAGE_SIZE - len);
+ } else {
+ ATF_CHECK(munmap(buf, PAGE_SIZE) == 0);
+ return (buf + PAGE_SIZE);
+ }
+}
+
+static void
+test_wcsnlen(const wchar_t *s)
+{
+ wchar_t *s1;
+ size_t size, len, bufsize;
+ int i;
+
+ size = wcslen(s) + 1;
+ for (i = 0; i <= 1; i++) {
+ for (bufsize = 0; bufsize <= size + 10; bufsize++) {
+ s1 = makebuf(bufsize * sizeof(wchar_t), i);
+ wmemcpy(s1, s, bufsize);
+ len = (size > bufsize) ? bufsize : size - 1;
+ ATF_CHECK(wcsnlen(s1, bufsize) == len);
+ }
+ }
+}
+
+ATF_TC_WITHOUT_HEAD(nul);
+ATF_TC_BODY(nul, tc)
+{
+
+ test_wcsnlen(L"");
+}
+
+ATF_TC_WITHOUT_HEAD(foo);
+ATF_TC_BODY(foo, tc)
+{
+
+ test_wcsnlen(L"foo");
+}
+
+ATF_TC_WITHOUT_HEAD(glorp);
+ATF_TC_BODY(glorp, tc)
+{
+
+ test_wcsnlen(L"glorp");
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, nul);
+ ATF_TP_ADD_TC(tp, foo);
+ ATF_TP_ADD_TC(tp, glorp);
+
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/tls_dso/Makefile b/lib/libc/tests/tls_dso/Makefile
index b37ffec..5449799 100644
--- a/lib/libc/tests/tls_dso/Makefile
+++ b/lib/libc/tests/tls_dso/Makefile
@@ -1,7 +1,5 @@
# $FreeBSD$
-SRCDIR= ${SRCTOP}/contrib/netbsd/
-
.include <bsd.own.mk>
LIB= h_tls_dynamic
OpenPOWER on IntegriCloud