am b88da065
: Merge "Upgrade to current vfprintf."
* commit 'b88da06580a22d9a1ee5a1c573c49e89207bc71b': Upgrade to current vfprintf.
This commit is contained in:
commit
06b5431eaa
@ -79,7 +79,6 @@ libc_common_src_files := \
|
||||
stdio/fvwrite.c \
|
||||
stdio/snprintf.c\
|
||||
stdio/sprintf.c \
|
||||
stdio/vfprintf.c \
|
||||
stdlib/atexit.c \
|
||||
stdlib/getenv.c \
|
||||
stdlib/putenv.c \
|
||||
@ -395,6 +394,7 @@ libc_upstream_openbsd_src_files := \
|
||||
upstream-openbsd/lib/libc/stdio/tmpnam.c \
|
||||
upstream-openbsd/lib/libc/stdio/ungetc.c \
|
||||
upstream-openbsd/lib/libc/stdio/vasprintf.c \
|
||||
upstream-openbsd/lib/libc/stdio/vfprintf.c \
|
||||
upstream-openbsd/lib/libc/stdio/vfscanf.c \
|
||||
upstream-openbsd/lib/libc/stdio/vprintf.c \
|
||||
upstream-openbsd/lib/libc/stdio/vscanf.c \
|
||||
|
@ -243,21 +243,42 @@ size_t wcsftime(wchar_t* wcs, size_t maxsize, const wchar_t* format, const stru
|
||||
return strftime(reinterpret_cast<char*>(wcs), maxsize, reinterpret_cast<const char*>(format), timptr);
|
||||
}
|
||||
|
||||
size_t wcsrtombs(char* dst, const wchar_t** src, size_t len, mbstate_t* /*ps*/) {
|
||||
const char* s = reinterpret_cast<const char*>(*src);
|
||||
const char* s2 = reinterpret_cast<const char*>(memchr(s, 0, len));
|
||||
if (s2 != NULL) {
|
||||
len = (s2 - s)+1;
|
||||
size_t wcsrtombs(char* dst, const wchar_t** src, size_t n, mbstate_t* /*ps*/) {
|
||||
size_t i = 0; // Number of input characters read.
|
||||
size_t o = 0; // Number of output bytes written.
|
||||
for (; (*src)[i] != 0; ++i) {
|
||||
// TODO: UTF-8 support.
|
||||
if ((*src)[i] > 0x7f) {
|
||||
errno = EILSEQ;
|
||||
return static_cast<size_t>(-1);
|
||||
}
|
||||
if (dst != NULL) {
|
||||
memcpy( dst, s, len );
|
||||
if (o + 1 > n) {
|
||||
break;
|
||||
}
|
||||
*src = (wchar_t*)(s + len);
|
||||
return len;
|
||||
dst[o++] = static_cast<char>((*src)[i]);
|
||||
} else {
|
||||
++o;
|
||||
}
|
||||
}
|
||||
// If we consumed all the input, terminate the output.
|
||||
if (dst != NULL && o < n) {
|
||||
dst[o] = 0;
|
||||
}
|
||||
// If we were actually consuming input, record how far we got.
|
||||
if (dst != NULL) {
|
||||
if ((*src)[i] != 0) {
|
||||
*src = &(*src)[i]; // This is where the next call should pick up.
|
||||
} else {
|
||||
*src = NULL; // We consumed everything.
|
||||
}
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
size_t wcstombs(char* dst, const wchar_t* src, size_t len) {
|
||||
return wcsrtombs(dst, &src, len, NULL);
|
||||
const wchar_t* p = src;
|
||||
return wcsrtombs(dst, &p, len, NULL);
|
||||
}
|
||||
|
||||
double wcstod(const wchar_t* nptr, wchar_t** endptr) {
|
||||
|
@ -95,6 +95,8 @@ extern int __sdidinit;
|
||||
#define FUNLOCKFILE(fp) funlockfile(fp)
|
||||
|
||||
#define FLOATING_POINT
|
||||
#define PRINTF_WIDE_CHAR
|
||||
#define SCANF_WIDE_CHAR
|
||||
|
||||
/* OpenBSD exposes these in <stdio.h>, but we only want them exposed to the implementation. */
|
||||
__BEGIN_DECLS
|
||||
|
3
libc/upstream-openbsd/lib/libc/include/langinfo.h
Normal file
3
libc/upstream-openbsd/lib/libc/include/langinfo.h
Normal file
@ -0,0 +1,3 @@
|
||||
/* Hack to build "vfprintf.c". */
|
||||
#define RADIXCHAR 1
|
||||
#define nl_langinfo(i) ((i == RADIXCHAR) ? (char*) "." : NULL)
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: floatio.h,v 1.3 2003/06/02 20:18:37 millert Exp $ */
|
||||
/* $OpenBSD: floatio.h,v 1.4 2008/09/07 20:36:08 martynas Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
@ -40,3 +40,19 @@
|
||||
#define MAXEXP 308
|
||||
/* 128 bit fraction takes up 39 decimal digits; max reasonable precision */
|
||||
#define MAXFRACT 39
|
||||
|
||||
/*
|
||||
* MAXEXPDIG is the maximum number of decimal digits needed to store a
|
||||
* floating point exponent in the largest supported format. It should
|
||||
* be ceil(log10(LDBL_MAX_10_EXP)) or, if hexadecimal floating point
|
||||
* conversions are supported, ceil(log10(LDBL_MAX_EXP)). But since it
|
||||
* is presently never greater than 5 in practice, we fudge it.
|
||||
*/
|
||||
#define MAXEXPDIG 6
|
||||
#if LDBL_MAX_EXP > 999999
|
||||
#error "floating point buffers too small"
|
||||
#endif
|
||||
|
||||
char *__hdtoa(double, const char *, int, int *, int *, char **);
|
||||
char *__hldtoa(long double, const char *, int, int *, int *, char **);
|
||||
char *__ldtoa(long double *, int, int, int *, int *, char **);
|
File diff suppressed because it is too large
Load Diff
@ -23,6 +23,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <wchar.h>
|
||||
|
||||
TEST(stdio, tmpfile_fileno_fprintf_rewind_fgets) {
|
||||
FILE* fp = tmpfile();
|
||||
@ -192,18 +193,38 @@ TEST(stdio, printf_ssize_t) {
|
||||
snprintf(buf, sizeof(buf), "%zd", v);
|
||||
}
|
||||
|
||||
TEST(stdio, snprintf_n_format_specifier_not_implemented) {
|
||||
#if defined(__BIONIC__)
|
||||
// https://code.google.com/p/android/issues/detail?id=64886
|
||||
TEST(stdio, snprintf_a) {
|
||||
char buf[BUFSIZ];
|
||||
EXPECT_EQ(23, snprintf(buf, sizeof(buf), "<%a>", 9990.235));
|
||||
EXPECT_STREQ("<0x1.3831e147ae148p+13>", buf);
|
||||
}
|
||||
|
||||
TEST(stdio, snprintf_lc) {
|
||||
char buf[BUFSIZ];
|
||||
wint_t wc = L'a';
|
||||
EXPECT_EQ(3, snprintf(buf, sizeof(buf), "<%lc>", wc));
|
||||
EXPECT_STREQ("<a>", buf);
|
||||
}
|
||||
|
||||
TEST(stdio, snprintf_ls) {
|
||||
char buf[BUFSIZ];
|
||||
wchar_t* ws = NULL;
|
||||
EXPECT_EQ(8, snprintf(buf, sizeof(buf), "<%ls>", ws));
|
||||
EXPECT_STREQ("<(null)>", buf);
|
||||
|
||||
wchar_t chars[] = { L'h', L'i', 0 };
|
||||
ws = chars;
|
||||
EXPECT_EQ(4, snprintf(buf, sizeof(buf), "<%ls>", ws));
|
||||
EXPECT_STREQ("<hi>", buf);
|
||||
}
|
||||
|
||||
TEST(stdio, snprintf_n) {
|
||||
char buf[32];
|
||||
int i = 0;
|
||||
// We deliberately don't implement %n, so it's treated like
|
||||
// any other unrecognized format specifier.
|
||||
EXPECT_EQ(5, snprintf(buf, sizeof(buf), "a %n b", &i));
|
||||
EXPECT_EQ(0, i);
|
||||
EXPECT_STREQ("a n b", buf);
|
||||
#else // __BIONIC__
|
||||
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
||||
#endif // __BIONIC__
|
||||
EXPECT_EQ(4, snprintf(buf, sizeof(buf), "a %n b", &i));
|
||||
EXPECT_EQ(2, i);
|
||||
EXPECT_STREQ("a b", buf);
|
||||
}
|
||||
|
||||
TEST(stdio, snprintf_smoke) {
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <wchar.h>
|
||||
|
||||
@ -55,3 +56,102 @@ TEST(wchar, wctomb_wcrtomb) {
|
||||
EXPECT_EQ(1U, wcrtomb(bytes, L'h', NULL));
|
||||
EXPECT_EQ('h', bytes[0]);
|
||||
}
|
||||
|
||||
TEST(wchar, wcstombs_wcrtombs) {
|
||||
wchar_t chars[] = { L'h', L'e', L'l', L'l', L'o', 0 };
|
||||
wchar_t bad_chars[] = { L'h', L'i', 666, 0 };
|
||||
const wchar_t* src;
|
||||
char bytes[BUFSIZ];
|
||||
|
||||
// Given a NULL destination, these functions count valid characters.
|
||||
EXPECT_EQ(5U, wcstombs(NULL, chars, 0));
|
||||
EXPECT_EQ(5U, wcstombs(NULL, chars, 4));
|
||||
EXPECT_EQ(5U, wcstombs(NULL, chars, 256));
|
||||
src = chars;
|
||||
EXPECT_EQ(5U, wcsrtombs(NULL, &src, 0, NULL));
|
||||
EXPECT_EQ(&chars[0], src);
|
||||
src = chars;
|
||||
EXPECT_EQ(5U, wcsrtombs(NULL, &src, 4, NULL));
|
||||
EXPECT_EQ(&chars[0], src);
|
||||
src = chars;
|
||||
EXPECT_EQ(5U, wcsrtombs(NULL, &src, 256, NULL));
|
||||
EXPECT_EQ(&chars[0], src);
|
||||
|
||||
// An unrepresentable char just returns an error from wcstombs...
|
||||
errno = 0;
|
||||
EXPECT_EQ(static_cast<size_t>(-1), wcstombs(NULL, bad_chars, 0));
|
||||
EXPECT_EQ(EILSEQ, errno);
|
||||
errno = 0;
|
||||
EXPECT_EQ(static_cast<size_t>(-1), wcstombs(NULL, bad_chars, 256));
|
||||
EXPECT_EQ(EILSEQ, errno);
|
||||
|
||||
// And wcsrtombs doesn't tell us where it got stuck because we didn't ask it
|
||||
// to actually convert anything...
|
||||
errno = 0;
|
||||
src = bad_chars;
|
||||
EXPECT_EQ(static_cast<size_t>(-1), wcsrtombs(NULL, &src, 0, NULL));
|
||||
EXPECT_EQ(&bad_chars[0], src);
|
||||
EXPECT_EQ(EILSEQ, errno);
|
||||
errno = 0;
|
||||
src = bad_chars;
|
||||
EXPECT_EQ(static_cast<size_t>(-1), wcsrtombs(NULL, &src, 256, NULL));
|
||||
EXPECT_EQ(&bad_chars[0], src);
|
||||
EXPECT_EQ(EILSEQ, errno);
|
||||
|
||||
// Okay, now let's test actually converting something...
|
||||
memset(bytes, 'x', sizeof(bytes));
|
||||
EXPECT_EQ(0U, wcstombs(bytes, chars, 0));
|
||||
memset(bytes, 'x', sizeof(bytes));
|
||||
EXPECT_EQ(4U, wcstombs(bytes, chars, 4));
|
||||
bytes[5] = 0;
|
||||
EXPECT_STREQ("hellx", bytes);
|
||||
memset(bytes, 'x', sizeof(bytes));
|
||||
EXPECT_EQ(5U, wcstombs(bytes, chars, 256));
|
||||
EXPECT_STREQ("hello", bytes);
|
||||
memset(bytes, 'x', sizeof(bytes));
|
||||
EXPECT_EQ(5U, wcstombs(bytes, chars, 6));
|
||||
EXPECT_STREQ("hello", bytes);
|
||||
errno = 0;
|
||||
memset(bytes, 'x', sizeof(bytes));
|
||||
EXPECT_EQ(static_cast<size_t>(-1), wcstombs(bytes, bad_chars, 256));
|
||||
EXPECT_EQ(EILSEQ, errno);
|
||||
bytes[3] = 0;
|
||||
EXPECT_STREQ("hix", bytes);
|
||||
|
||||
// wcsrtombs is a bit more informative...
|
||||
memset(bytes, 'x', sizeof(bytes));
|
||||
src = chars;
|
||||
EXPECT_EQ(0U, wcsrtombs(bytes, &src, 0, NULL));
|
||||
EXPECT_EQ(&chars[0], src); // No input consumed.
|
||||
EXPECT_EQ(EILSEQ, errno);
|
||||
|
||||
memset(bytes, 'x', sizeof(bytes));
|
||||
src = chars;
|
||||
EXPECT_EQ(4U, wcsrtombs(bytes, &src, 4, NULL));
|
||||
EXPECT_EQ(&chars[4], src); // Some input consumed.
|
||||
EXPECT_EQ(EILSEQ, errno);
|
||||
bytes[5] = 0;
|
||||
EXPECT_STREQ("hellx", bytes);
|
||||
|
||||
memset(bytes, 'x', sizeof(bytes));
|
||||
src = chars;
|
||||
EXPECT_EQ(5U, wcsrtombs(bytes, &src, 256, NULL));
|
||||
EXPECT_EQ(NULL, src); // All input consumed!
|
||||
EXPECT_EQ(EILSEQ, errno);
|
||||
EXPECT_STREQ("hello", bytes);
|
||||
|
||||
memset(bytes, 'x', sizeof(bytes));
|
||||
src = chars;
|
||||
EXPECT_EQ(5U, wcsrtombs(bytes, &src, 6, NULL));
|
||||
EXPECT_EQ(NULL, src); // All input consumed.
|
||||
EXPECT_EQ(EILSEQ, errno);
|
||||
EXPECT_STREQ("hello", bytes);
|
||||
|
||||
memset(bytes, 'x', sizeof(bytes));
|
||||
src = bad_chars;
|
||||
EXPECT_EQ(static_cast<size_t>(-1), wcsrtombs(bytes, &src, 256, NULL));
|
||||
EXPECT_EQ(&bad_chars[2], src);
|
||||
EXPECT_EQ(EILSEQ, errno);
|
||||
bytes[3] = 0;
|
||||
EXPECT_STREQ("hix", bytes);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user