Start de-duplicating the regular and wide printf implementations.
This patch switches to C++ (in anticipation of needing it later), removes
a little duplication (via a macro for now), and ensures uniform support
for %C/%lc and %S/%ls between regular and wide (with new tests).
Since it's so hard to debug problems in printf (as the time I've wasted
already today will testify), that's all I want to do in this change. The
other 500 lines of diff can wait...
(Also merge "floatio.h" into "local.h" now all the users are in forked
code.)
Bug: http://b/67371539
Test: ran tests
Change-Id: I083353d89c32b9302d759ca6967cc6d8a62cd8a5
diff --git a/libc/stdio/floatio.h b/libc/stdio/floatio.h
deleted file mode 100644
index 9769030..0000000
--- 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 155c70b..0ff0785 100644
--- a/libc/stdio/local.h
+++ b/libc/stdio/local.h
@@ -261,10 +261,35 @@
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 e911da4..d81e713 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
similarity index 94%
rename from libc/stdio/vfprintf.c
rename to libc/stdio/vfprintf.cpp
index 5713b44..6d16828 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 @@
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 @@
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 @@
#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 @@
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 @@
case 'z':
flags |= SIZEINT;
goto rflag;
+ case 'C':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
case 'c':
if (flags & LONGINT) {
mbstate_t mbs;
@@ -712,10 +736,11 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
case 'z':
flags |= SIZEINT;
goto rflag;
+ case 'C':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
case 'c':
if (flags & LONGINT)
ADDTYPE(T_WINT);
@@ -1281,6 +1302,9 @@
case 'p':
ADDTYPE(TP_VOID);
break;
+ case 'S':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
case 's':
if (flags & LONGINT)
ADDTYPE(TP_WCHAR);
@@ -1306,8 +1330,10 @@
*/
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 @@
* 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));
+ memset(*typetable + *tablesize, T_UNUSED, (new_size - *tablesize));
- *tablesize = newsize;
- return (0);
-}
-
-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 c18e214..c09132f 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
similarity index 94%
rename from libc/stdio/vfwprintf.c
rename to libc/stdio/vfwprintf.cpp
index 647b59a..80eb78a 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 @@
* 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 @@
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 @@
#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 @@
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 @@
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 @@
/*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 @@
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 @@
*/
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 @@
* 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));
+ memset(*typetable + *tablesize, T_UNUSED, (new_size - *tablesize));
- *tablesize = newsize;
- return (0);
-}
-
-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 c74c6e7..bbe534c 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. */
/*