diff options
-rw-r--r-- | libc/Android.bp | 4 | ||||
-rw-r--r-- | libc/stdio/floatio.h | 58 | ||||
-rw-r--r-- | libc/stdio/local.h | 29 | ||||
-rw-r--r-- | libc/stdio/parsefloat.c | 1 | ||||
-rw-r--r-- | libc/stdio/vfprintf.cpp (renamed from libc/stdio/vfprintf.c) | 177 | ||||
-rw-r--r-- | libc/stdio/vfscanf.c | 2 | ||||
-rw-r--r-- | libc/stdio/vfwprintf.cpp (renamed from libc/stdio/vfwprintf.c) | 165 | ||||
-rw-r--r-- | libc/stdio/vfwscanf.c | 2 | ||||
-rw-r--r-- | tests/stdio_test.cpp | 72 |
9 files changed, 265 insertions, 245 deletions
diff --git a/libc/Android.bp b/libc/Android.bp index 050d2f5d4..27e90be4e 100644 --- a/libc/Android.bp +++ b/libc/Android.bp @@ -524,8 +524,8 @@ cc_library_static { name: "libc_openbsd_large_stack", defaults: ["libc_defaults"], srcs: [ - "stdio/vfprintf.c", - "stdio/vfwprintf.c", + "stdio/vfprintf.cpp", + "stdio/vfwprintf.cpp", ], cflags: [ "-include openbsd-compat.h", diff --git a/libc/stdio/floatio.h b/libc/stdio/floatio.h deleted file mode 100644 index 976903084..000000000 --- a/libc/stdio/floatio.h +++ /dev/null @@ -1,58 +0,0 @@ -/* $OpenBSD: floatio.h,v 1.4 2008/09/07 20:36:08 martynas Exp $ */ - -/*- - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Chris Torek. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 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. - * - * 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. - */ - -/* - * Floating point scanf/printf (input/output) definitions. - */ - -/* 11-bit exponent (VAX G floating point) is 308 decimal digits */ -#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 **); diff --git a/libc/stdio/local.h b/libc/stdio/local.h index 155c70bf9..0ff078572 100644 --- a/libc/stdio/local.h +++ b/libc/stdio/local.h @@ -261,10 +261,35 @@ extern void __sinit(void); // Not actually implemented. size_t parsefloat(FILE*, char*, char*); size_t wparsefloat(FILE*, wchar_t*, wchar_t*); -__END_DECLS - // Sanity check a FILE* for nullptr, so we can emit a message while crashing // instead of doing a blind null-dereference. #define CHECK_FP(fp) if (fp == nullptr) __fortify_fatal("%s: null FILE*", __FUNCTION__) +/* + * Floating point scanf/printf (input/output) definitions. + */ + +/* 11-bit exponent (VAX G floating point) is 308 decimal digits */ +#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**); + +__END_DECLS + #endif diff --git a/libc/stdio/parsefloat.c b/libc/stdio/parsefloat.c index e911da412..d81e71359 100644 --- a/libc/stdio/parsefloat.c +++ b/libc/stdio/parsefloat.c @@ -34,7 +34,6 @@ #include <stdlib.h> #include "local.h" -#include "floatio.h" #define BUF 513 /* Maximum length of numeric string. */ diff --git a/libc/stdio/vfprintf.c b/libc/stdio/vfprintf.cpp index 5713b4406..6d1682894 100644 --- a/libc/stdio/vfprintf.c +++ b/libc/stdio/vfprintf.cpp @@ -31,18 +31,17 @@ * SUCH DAMAGE. */ -/* - * Actual printf innards. - * - * This code is large and complicated... - */ +#define CHAR_TYPE char #include <sys/mman.h> #include <sys/types.h> #include <errno.h> +#include <float.h> #include <langinfo.h> #include <limits.h> +#include <locale.h> +#include <math.h> #include <stdarg.h> #include <stddef.h> #include <stdint.h> @@ -53,6 +52,7 @@ #include <wchar.h> #include "fvwrite.h" +#include "gdtoa.h" #include "local.h" union arg { @@ -172,7 +172,7 @@ static char* __wcsconv(wchar_t* wcsarg, int prec) { if (clen == (size_t)-1) return (NULL); } } - if ((convbuf = malloc(nbytes + 1)) == NULL) return (NULL); + if ((convbuf = static_cast<char*>(malloc(nbytes + 1))) == NULL) return NULL; /* Fill the output buffer. */ p = wcsarg; @@ -185,15 +185,43 @@ static char* __wcsconv(wchar_t* wcsarg, int prec) { return (convbuf); } -#include <float.h> -#include <locale.h> -#include <math.h> -#include "floatio.h" -#include "gdtoa.h" - #define DEFPREC 6 -static int exponent(char*, int, int); +#define to_digit(c) ((c) - '0') +#define is_digit(c) ((unsigned)to_digit(c) <= 9) +#define to_char(n) ((CHAR_TYPE)((n) + '0')) + +template <typename CharT> +static int exponent(CharT* p0, int exp, int fmtch) { + CharT* p = p0; + *p++ = fmtch; + if (exp < 0) { + exp = -exp; + *p++ = '-'; + } else { + *p++ = '+'; + } + + CharT expbuf[MAXEXPDIG]; + CharT* t = expbuf + MAXEXPDIG; + if (exp > 9) { + do { + *--t = to_char(exp % 10); + } while ((exp /= 10) > 9); + *--t = to_char(exp); + for (; t < expbuf + MAXEXPDIG; *p++ = *t++) /* nothing */; + } else { + /* + * Exponents for decimal floating point conversions + * (%[eEgG]) must be at least two characters long, + * whereas exponents for hexadecimal conversions can + * be only one character long. + */ + if (fmtch == 'e' || fmtch == 'E') *p++ = '0'; + *p++ = to_char(exp); + } + return (p - p0); +} /* * The size of the buffer we use as scratch space for integer @@ -207,13 +235,6 @@ static int exponent(char*, int, int); #define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */ /* - * Macros for converting digits to letters and vice versa - */ -#define to_digit(c) ((c) - '0') -#define is_digit(c) ((unsigned)to_digit(c) <= 9) -#define to_char(n) ((n) + '0') - -/* * Flags used during conversion. */ #define ALT 0x0001 /* alternate form */ @@ -310,8 +331,8 @@ int __vfprintf(FILE* fp, const char* fmt0, __va_list ap) { static char zeroes[PADSIZE] = { '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0' }; - static const char xdigs_lower[16] = "0123456789abcdef"; - static const char xdigs_upper[16] = "0123456789ABCDEF"; + static const char xdigs_lower[] = "0123456789abcdef"; + static const char xdigs_upper[] = "0123456789ABCDEF"; /* * BEWARE, these `goto error' on error, and PAD uses `n'. @@ -612,6 +633,9 @@ int __vfprintf(FILE* fp, const char* fmt0, __va_list ap) { case 'z': flags |= SIZEINT; goto rflag; + case 'C': + flags |= LONGINT; + /*FALLTHROUGH*/ case 'c': if (flags & LONGINT) { mbstate_t mbs; @@ -712,10 +736,11 @@ int __vfprintf(FILE* fp, const char* fmt0, __va_list ap) { fp_common: if (signflag) sign = '-'; if (expt == INT_MAX) { /* inf or nan */ - if (*cp == 'N') - cp = (ch >= 'a') ? "nan" : "NAN"; - else - cp = (ch >= 'a') ? "inf" : "INF"; + if (*cp == 'N') { + cp = const_cast<char*>((ch >= 'a') ? "nan" : "NAN"); + } else { + cp = const_cast<char*>((ch >= 'a') ? "inf" : "INF"); + } size = 3; flags &= ~ZEROPAD; break; @@ -794,6 +819,9 @@ int __vfprintf(FILE* fp, const char* fmt0, __va_list ap) { xdigs = xdigs_lower; ox[1] = 'x'; goto nosign; + case 'S': + flags |= LONGINT; + /*FALLTHROUGH*/ case 's': if (flags & LONGINT) { wchar_t* wcp; @@ -801,7 +829,7 @@ int __vfprintf(FILE* fp, const char* fmt0, __va_list ap) { free(convbuf); convbuf = NULL; if ((wcp = GETARG(wchar_t*)) == NULL) { - cp = "(null)"; + cp = const_cast<char*>("(null)"); } else { convbuf = __wcsconv(wcp, prec); if (convbuf == NULL) { @@ -810,17 +838,11 @@ int __vfprintf(FILE* fp, const char* fmt0, __va_list ap) { } cp = convbuf; } - } else if ((cp = GETARG(char*)) == NULL) - cp = "(null)"; + } else if ((cp = GETARG(char*)) == NULL) { + cp = const_cast<char*>("(null)"); + } if (prec >= 0) { - /* - * can't use strlen; can only look for the - * NUL in the first `prec' characters, and - * strlen() will go further. - */ - char* p = memchr(cp, 0, prec); - - size = p ? (p - cp) : prec; + size = strnlen(cp, prec); } else { size_t len; @@ -897,15 +919,11 @@ int __vfprintf(FILE* fp, const char* fmt0, __va_list ap) { break; default: - cp = "bug in vfprintf: bad base"; - size = strlen(cp); - goto skipsize; + abort(); } } size = buf + BUF - cp; - if (size > BUF) /* should never happen */ - abort(); - skipsize: + if (size > BUF) abort(); /* should never happen */ break; default: /* "%?" prints ?, unless ? is NUL */ if (ch == '\0') goto done; @@ -1228,6 +1246,9 @@ static int __find_arguments(const char* fmt0, va_list ap, union arg** argtable, case 'z': flags |= SIZEINT; goto rflag; + case 'C': + flags |= LONGINT; + /*FALLTHROUGH*/ case 'c': if (flags & LONGINT) ADDTYPE(T_WINT); @@ -1281,6 +1302,9 @@ static int __find_arguments(const char* fmt0, va_list ap, union arg** argtable, case 'p': ADDTYPE(TP_VOID); break; + case 'S': + flags |= LONGINT; + /*FALLTHROUGH*/ case 's': if (flags & LONGINT) ADDTYPE(TP_WCHAR); @@ -1306,8 +1330,10 @@ done: */ if (tablemax >= STATIC_ARG_TBL_SIZE) { *argtablesiz = sizeof(union arg) * (tablemax + 1); - *argtable = mmap(NULL, *argtablesiz, PROT_WRITE | PROT_READ, MAP_ANON | MAP_PRIVATE, -1, 0); - if (*argtable == MAP_FAILED) return (-1); + *argtable = static_cast<arg*>(mmap(NULL, *argtablesiz, + PROT_WRITE | PROT_READ, + MAP_ANON | MAP_PRIVATE, -1, 0)); + if (*argtable == MAP_FAILED) return -1; } #if 0 @@ -1413,55 +1439,28 @@ finish: * Increase the size of the type table. */ static int __grow_type_table(unsigned char** typetable, int* tablesize) { - unsigned char* oldtable = *typetable; - int newsize = *tablesize * 2; + unsigned char* old_table = *typetable; + int new_size = *tablesize * 2; - if (newsize < getpagesize()) newsize = getpagesize(); + if (new_size < getpagesize()) new_size = getpagesize(); if (*tablesize == STATIC_ARG_TBL_SIZE) { - *typetable = mmap(NULL, newsize, PROT_WRITE | PROT_READ, MAP_ANON | MAP_PRIVATE, -1, 0); - if (*typetable == MAP_FAILED) return (-1); - bcopy(oldtable, *typetable, *tablesize); + *typetable = static_cast<unsigned char*>(mmap(NULL, new_size, + PROT_WRITE | PROT_READ, + MAP_ANON | MAP_PRIVATE, -1, 0)); + if (*typetable == MAP_FAILED) return -1; + bcopy(old_table, *typetable, *tablesize); } else { - unsigned char* new = mmap(NULL, newsize, PROT_WRITE | PROT_READ, MAP_ANON | MAP_PRIVATE, -1, 0); - if (new == MAP_FAILED) return (-1); - memmove(new, *typetable, *tablesize); + unsigned char* new_table = static_cast<unsigned char*>(mmap(NULL, new_size, + PROT_WRITE | PROT_READ, + MAP_ANON | MAP_PRIVATE, -1, 0)); + if (new_table == MAP_FAILED) return -1; + memmove(new_table, *typetable, *tablesize); munmap(*typetable, *tablesize); - *typetable = new; + *typetable = new_table; } - memset(*typetable + *tablesize, T_UNUSED, (newsize - *tablesize)); - - *tablesize = newsize; - return (0); -} + memset(*typetable + *tablesize, T_UNUSED, (new_size - *tablesize)); -static int exponent(char* p0, int exp, int fmtch) { - char *p, *t; - char expbuf[MAXEXPDIG]; - - p = p0; - *p++ = fmtch; - if (exp < 0) { - exp = -exp; - *p++ = '-'; - } else - *p++ = '+'; - t = expbuf + MAXEXPDIG; - if (exp > 9) { - do { - *--t = to_char(exp % 10); - } while ((exp /= 10) > 9); - *--t = to_char(exp); - for (; t < expbuf + MAXEXPDIG; *p++ = *t++) /* nothing */; - } else { - /* - * Exponents for decimal floating point conversions - * (%[eEgG]) must be at least two characters long, - * whereas exponents for hexadecimal conversions can - * be only one character long. - */ - if (fmtch == 'e' || fmtch == 'E') *p++ = '0'; - *p++ = to_char(exp); - } - return (p - p0); + *tablesize = new_size; + return 0; } diff --git a/libc/stdio/vfscanf.c b/libc/stdio/vfscanf.c index c18e214a3..c09132f3d 100644 --- a/libc/stdio/vfscanf.c +++ b/libc/stdio/vfscanf.c @@ -41,8 +41,6 @@ #include <wctype.h> #include "local.h" -#include "floatio.h" - #define BUF 513 /* Maximum length of numeric string. */ /* diff --git a/libc/stdio/vfwprintf.c b/libc/stdio/vfwprintf.cpp index 647b59af1..80eb78a67 100644 --- a/libc/stdio/vfwprintf.c +++ b/libc/stdio/vfwprintf.cpp @@ -31,18 +31,17 @@ * SUCH DAMAGE. */ -/* - * Actual wprintf innards. - * - * This code is large and complicated... - */ +#define CHAR_TYPE wchar_t #include <sys/mman.h> #include <sys/types.h> #include <errno.h> +#include <float.h> #include <langinfo.h> #include <limits.h> +#include <locale.h> +#include <math.h> #include <stdarg.h> #include <stddef.h> #include <stdint.h> @@ -53,6 +52,7 @@ #include <wchar.h> #include "fvwrite.h" +#include "gdtoa.h" #include "local.h" union arg { @@ -190,7 +190,7 @@ static wchar_t* __mbsconv(char* mbsarg, int prec) { * converting at most `size' bytes of the input multibyte string to * wide characters for printing. */ - convbuf = calloc(insize + 1, sizeof(*convbuf)); + convbuf = static_cast<wchar_t*>(calloc(insize + 1, sizeof(*convbuf))); if (convbuf == NULL) return (NULL); wcp = convbuf; p = mbsarg; @@ -212,15 +212,43 @@ static wchar_t* __mbsconv(char* mbsarg, int prec) { return (convbuf); } -#include <float.h> -#include <locale.h> -#include <math.h> -#include "floatio.h" -#include "gdtoa.h" - #define DEFPREC 6 -static int exponent(wchar_t*, int, int); +#define to_digit(c) ((c) - '0') +#define is_digit(c) ((unsigned)to_digit(c) <= 9) +#define to_char(n) ((CHAR_TYPE)((n) + '0')) + +template <typename CharT> +static int exponent(CharT* p0, int exp, int fmtch) { + CharT* p = p0; + *p++ = fmtch; + if (exp < 0) { + exp = -exp; + *p++ = '-'; + } else { + *p++ = '+'; + } + + CharT expbuf[MAXEXPDIG]; + CharT* t = expbuf + MAXEXPDIG; + if (exp > 9) { + do { + *--t = to_char(exp % 10); + } while ((exp /= 10) > 9); + *--t = to_char(exp); + for (; t < expbuf + MAXEXPDIG; *p++ = *t++) /* nothing */; + } else { + /* + * Exponents for decimal floating point conversions + * (%[eEgG]) must be at least two characters long, + * whereas exponents for hexadecimal conversions can + * be only one character long. + */ + if (fmtch == 'e' || fmtch == 'E') *p++ = '0'; + *p++ = to_char(exp); + } + return (p - p0); +} /* * The size of the buffer we use as scratch space for integer @@ -234,13 +262,6 @@ static int exponent(wchar_t*, int, int); #define STATIC_ARG_TBL_SIZE 8 /* Size of static argument table. */ /* - * Macros for converting digits to letters and vice versa - */ -#define to_digit(c) ((c) - '0') -#define is_digit(c) ((unsigned)to_digit(c) <= 9) -#define to_char(n) ((wchar_t)((n) + '0')) - -/* * Flags used during conversion. */ #define ALT 0x0001 /* alternate form */ @@ -321,8 +342,8 @@ int __vfwprintf(FILE* __restrict fp, const wchar_t* __restrict fmt0, __va_list a static wchar_t zeroes[PADSIZE] = { '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0' }; - static const char xdigs_lower[16] = "0123456789abcdef"; - static const char xdigs_upper[16] = "0123456789ABCDEF"; + static const char xdigs_lower[] = "0123456789abcdef"; + static const char xdigs_upper[] = "0123456789ABCDEF"; /* * BEWARE, these `goto error' on error, PRINT uses 'n3', @@ -689,10 +710,11 @@ int __vfwprintf(FILE* __restrict fp, const wchar_t* __restrict fmt0, __va_list a fp_common: if (signflag) sign = '-'; if (expt == INT_MAX) { /* inf or nan */ - if (*cp == 'N') - cp = (ch >= 'a') ? L"nan" : L"NAN"; - else - cp = (ch >= 'a') ? L"inf" : L"INF"; + if (*cp == 'N') { + cp = const_cast<wchar_t*>((ch >= 'a') ? L"nan" : L"NAN"); + } else { + cp = const_cast<wchar_t*>((ch >= 'a') ? L"inf" : L"INF"); + } size = 3; flags &= ~ZEROPAD; break; @@ -775,27 +797,21 @@ int __vfwprintf(FILE* __restrict fp, const wchar_t* __restrict fmt0, __va_list a /*FALLTHROUGH*/ case 's': if (flags & LONGINT) { - if ((cp = GETARG(wchar_t*)) == NULL) cp = L"(null)"; + if ((cp = GETARG(wchar_t*)) == NULL) cp = const_cast<wchar_t*>(L"(null)"); } else { char* mbsarg; - if ((mbsarg = GETARG(char*)) == NULL) mbsarg = "(null)"; + if ((mbsarg = GETARG(char*)) == NULL) mbsarg = const_cast<char*>("(null)"); free(convbuf); convbuf = __mbsconv(mbsarg, prec); if (convbuf == NULL) { fp->_flags |= __SERR; goto error; - } else + } else { cp = convbuf; + } } if (prec >= 0) { - /* - * can't use wcslen; can only look for the - * NUL in the first `prec' characters, and - * wcslen() will go further. - */ - wchar_t* p = wmemchr(cp, 0, prec); - - size = p ? (p - cp) : prec; + size = wcsnlen(cp, prec); } else { size_t len; @@ -872,15 +888,11 @@ int __vfwprintf(FILE* __restrict fp, const wchar_t* __restrict fmt0, __va_list a break; default: - cp = L"bug in vfwprintf: bad base"; - size = wcslen(cp); - goto skipsize; + abort(); } } size = buf + BUF - cp; - if (size > BUF) /* should never happen */ - abort(); - skipsize: + if (size > BUF) abort(); /* should never happen */ break; default: /* "%?" prints ?, unless ? is NUL */ if (ch == '\0') goto done; @@ -1281,8 +1293,10 @@ done: */ if (tablemax >= STATIC_ARG_TBL_SIZE) { *argtablesiz = sizeof(union arg) * (tablemax + 1); - *argtable = mmap(NULL, *argtablesiz, PROT_WRITE | PROT_READ, MAP_ANON | MAP_PRIVATE, -1, 0); - if (*argtable == MAP_FAILED) return (-1); + *argtable = static_cast<arg*>(mmap(NULL, *argtablesiz, + PROT_WRITE | PROT_READ, + MAP_ANON | MAP_PRIVATE, -1, 0)); + if (*argtable == MAP_FAILED) return -1; } #if 0 @@ -1382,55 +1396,28 @@ finish: * Increase the size of the type table. */ static int __grow_type_table(unsigned char** typetable, int* tablesize) { - unsigned char* oldtable = *typetable; - int newsize = *tablesize * 2; + unsigned char* old_table = *typetable; + int new_size = *tablesize * 2; - if (newsize < getpagesize()) newsize = getpagesize(); + if (new_size < getpagesize()) new_size = getpagesize(); if (*tablesize == STATIC_ARG_TBL_SIZE) { - *typetable = mmap(NULL, newsize, PROT_WRITE | PROT_READ, MAP_ANON | MAP_PRIVATE, -1, 0); - if (*typetable == MAP_FAILED) return (-1); - bcopy(oldtable, *typetable, *tablesize); + *typetable = static_cast<unsigned char*>(mmap(NULL, new_size, + PROT_WRITE | PROT_READ, + MAP_ANON | MAP_PRIVATE, -1, 0)); + if (*typetable == MAP_FAILED) return -1; + bcopy(old_table, *typetable, *tablesize); } else { - unsigned char* new = mmap(NULL, newsize, PROT_WRITE | PROT_READ, MAP_ANON | MAP_PRIVATE, -1, 0); - if (new == MAP_FAILED) return (-1); - memmove(new, *typetable, *tablesize); + unsigned char* new_table = static_cast<unsigned char*>(mmap(NULL, new_size, + PROT_WRITE | PROT_READ, + MAP_ANON | MAP_PRIVATE, -1, 0)); + if (new_table == MAP_FAILED) return -1; + memmove(new_table, *typetable, *tablesize); munmap(*typetable, *tablesize); - *typetable = new; + *typetable = new_table; } - memset(*typetable + *tablesize, T_UNUSED, (newsize - *tablesize)); - - *tablesize = newsize; - return (0); -} + memset(*typetable + *tablesize, T_UNUSED, (new_size - *tablesize)); -static int exponent(wchar_t* p0, int exp, int fmtch) { - wchar_t *p, *t; - wchar_t expbuf[MAXEXPDIG]; - - p = p0; - *p++ = fmtch; - if (exp < 0) { - exp = -exp; - *p++ = '-'; - } else - *p++ = '+'; - t = expbuf + MAXEXPDIG; - if (exp > 9) { - do { - *--t = to_char(exp % 10); - } while ((exp /= 10) > 9); - *--t = to_char(exp); - for (; t < expbuf + MAXEXPDIG; *p++ = *t++) /* nothing */; - } else { - /* - * Exponents for decimal floating point conversions - * (%[eEgG]) must be at least two characters long, - * whereas exponents for hexadecimal conversions can - * be only one character long. - */ - if (fmtch == 'e' || fmtch == 'E') *p++ = '0'; - *p++ = to_char(exp); - } - return (p - p0); + *tablesize = new_size; + return 0; } diff --git a/libc/stdio/vfwscanf.c b/libc/stdio/vfwscanf.c index c74c6e7c8..bbe534c1b 100644 --- a/libc/stdio/vfwscanf.c +++ b/libc/stdio/vfwscanf.c @@ -42,8 +42,6 @@ #include <wctype.h> #include "local.h" -#include "floatio.h" - #define BUF 513 /* Maximum length of numeric string. */ /* diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp index 97b222c48..e07980e77 100644 --- a/tests/stdio_test.cpp +++ b/tests/stdio_test.cpp @@ -302,6 +302,13 @@ TEST(STDIO_TEST, snprintf_lc) { EXPECT_STREQ("<a>", buf); } +TEST(STDIO_TEST, snprintf_C) { // Synonym for %lc. + char buf[BUFSIZ]; + wchar_t wc = L'a'; + EXPECT_EQ(3, snprintf(buf, sizeof(buf), "<%C>", wc)); + EXPECT_STREQ("<a>", buf); +} + TEST(STDIO_TEST, snprintf_ls) { char buf[BUFSIZ]; wchar_t* ws = NULL; @@ -314,6 +321,18 @@ TEST(STDIO_TEST, snprintf_ls) { EXPECT_STREQ("<hi>", buf); } +TEST(STDIO_TEST, snprintf_S) { // Synonym for %ls. + char buf[BUFSIZ]; + wchar_t* ws = NULL; + EXPECT_EQ(8, snprintf(buf, sizeof(buf), "<%S>", ws)); + EXPECT_STREQ("<(null)>", buf); + + wchar_t chars[] = { L'h', L'i', 0 }; + ws = chars; + EXPECT_EQ(4, snprintf(buf, sizeof(buf), "<%S>", ws)); + EXPECT_STREQ("<hi>", buf); +} + TEST(STDIO_TEST, snprintf_n) { #if defined(__BIONIC__) // http://b/14492135 @@ -584,6 +603,24 @@ TEST(STDIO_TEST, swprintf_a) { ASSERT_EQ(std::wstring(L"0x1.921fb54411744p+1"), buf); } +TEST(STDIO_TEST, swprintf_lc) { + constexpr size_t nchars = 32; + wchar_t buf[nchars]; + + wint_t wc = L'a'; + EXPECT_EQ(3, swprintf(buf, nchars, L"<%lc>", wc)); + EXPECT_EQ(std::wstring(L"<a>"), buf); +} + +TEST(STDIO_TEST, swprintf_C) { // Synonym for %lc. + constexpr size_t nchars = 32; + wchar_t buf[nchars]; + + wint_t wc = L'a'; + EXPECT_EQ(3, swprintf(buf, nchars, L"<%C>", wc)); + EXPECT_EQ(std::wstring(L"<a>"), buf); +} + TEST(STDIO_TEST, swprintf_ls) { constexpr size_t nchars = 32; wchar_t buf[nchars]; @@ -595,6 +632,17 @@ TEST(STDIO_TEST, swprintf_ls) { ASSERT_EQ(std::wstring(kWideString), buf); } +TEST(STDIO_TEST, swprintf_S) { // Synonym for %ls. + constexpr size_t nchars = 32; + wchar_t buf[nchars]; + + static const wchar_t kWideString[] = L"Hello\uff41 World"; + ASSERT_EQ(12, swprintf(buf, nchars, L"%S", kWideString)); + ASSERT_EQ(std::wstring(kWideString), buf); + ASSERT_EQ(12, swprintf(buf, 13, L"%S", kWideString)); + ASSERT_EQ(std::wstring(kWideString), buf); +} + TEST(STDIO_TEST, snprintf_d_INT_MAX) { char buf[BUFSIZ]; snprintf(buf, sizeof(buf), "%d", INT_MAX); @@ -639,6 +687,30 @@ TEST(STDIO_TEST, snprintf_lld_LLONG_MIN) { EXPECT_STREQ("-9223372036854775808", buf); } +TEST(STDIO_TEST, snprintf_o_UINT_MAX) { + char buf[BUFSIZ]; + snprintf(buf, sizeof(buf), "%o", UINT_MAX); + EXPECT_STREQ("37777777777", buf); +} + +TEST(STDIO_TEST, snprintf_u_UINT_MAX) { + char buf[BUFSIZ]; + snprintf(buf, sizeof(buf), "%u", UINT_MAX); + EXPECT_STREQ("4294967295", buf); +} + +TEST(STDIO_TEST, snprintf_x_UINT_MAX) { + char buf[BUFSIZ]; + snprintf(buf, sizeof(buf), "%x", UINT_MAX); + EXPECT_STREQ("ffffffff", buf); +} + +TEST(STDIO_TEST, snprintf_X_UINT_MAX) { + char buf[BUFSIZ]; + snprintf(buf, sizeof(buf), "%X", UINT_MAX); + EXPECT_STREQ("FFFFFFFF", buf); +} + TEST(STDIO_TEST, snprintf_e) { char buf[BUFSIZ]; |