printf unification: floating point.
The only remaining differences between vfprintf.cpp and vfwprintf.cpp
after this are the wide/narrow conversions for %c, %m, and %s. I've used
"chars" and "bytes" for the named constants for the directions because
(a) I find -1 and 1 pretty confusing and (b) although "narrow" is the
obvious opposite of "wide", only Windows actually moved to wide
characters, so "narrow" (aka "multibyte", and probably "utf8") is the
default/normal case. Even though C confuses bytes and characters via its
`char` type, "bytes" versus "chars" seems like the appropriate
terminology (and it's what Java/Python use).
Also improve the swprintf tests assertion so failures are readable.
Test: treehugger
Change-Id: Ife8f70f65ec28d96058a7d68df353945524835d2
diff --git a/libc/stdio/vfprintf.cpp b/libc/stdio/vfprintf.cpp
index 54ca7a7..12cceeb 100644
--- a/libc/stdio/vfprintf.cpp
+++ b/libc/stdio/vfprintf.cpp
@@ -39,7 +39,7 @@
#define CHAR_TYPE_inf "inf"
#define CHAR_TYPE_NAN "NAN"
#define CHAR_TYPE_nan "nan"
-#define CHAR_TYPE_ORIENTATION -1
+#define CHAR_TYPE_ORIENTATION ORIENT_BYTES
#define PRINT(ptr, len) \
do { \
@@ -361,14 +361,14 @@
if (dtoaresult) __freedtoa(dtoaresult);
if (flags & LONGDBL) {
fparg.ldbl = GETARG(long double);
- dtoaresult = cp = __hldtoa(fparg.ldbl, xdigs, prec, &expt, &signflag, &dtoaend);
+ dtoaresult = __hldtoa(fparg.ldbl, xdigs, prec, &expt, &signflag, &dtoaend);
if (dtoaresult == nullptr) {
errno = ENOMEM;
goto error;
}
} else {
fparg.dbl = GETARG(double);
- dtoaresult = cp = __hdtoa(fparg.dbl, xdigs, prec, &expt, &signflag, &dtoaend);
+ dtoaresult = __hdtoa(fparg.dbl, xdigs, prec, &expt, &signflag, &dtoaend);
if (dtoaresult == nullptr) {
errno = ENOMEM;
goto error;
@@ -398,14 +398,14 @@
if (dtoaresult) __freedtoa(dtoaresult);
if (flags & LONGDBL) {
fparg.ldbl = GETARG(long double);
- dtoaresult = cp = __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec, &expt, &signflag, &dtoaend);
+ dtoaresult = __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec, &expt, &signflag, &dtoaend);
if (dtoaresult == nullptr) {
errno = ENOMEM;
goto error;
}
} else {
fparg.dbl = GETARG(double);
- dtoaresult = cp = __dtoa(fparg.dbl, expchar ? 2 : 3, prec, &expt, &signflag, &dtoaend);
+ dtoaresult = __dtoa(fparg.dbl, expchar ? 2 : 3, prec, &expt, &signflag, &dtoaend);
if (dtoaresult == nullptr) {
errno = ENOMEM;
goto error;
@@ -413,6 +413,13 @@
if (expt == 9999) expt = INT_MAX;
}
fp_common:
+#if CHAR_TYPE_ORIENTATION == ORIENT_BYTES
+ cp = dtoaresult;
+#else
+ free(convbuf);
+ cp = convbuf = helpers::mbsconv(dtoaresult, -1);
+ if (cp == nullptr) goto error;
+#endif
if (signflag) sign = '-';
if (expt == INT_MAX) { /* inf or nan */
if (*cp == 'N') {
@@ -425,7 +432,7 @@
break;
}
flags |= FPT;
- ndig = dtoaend - cp;
+ ndig = dtoaend - dtoaresult;
if (ch == 'g' || ch == 'G') {
if (expt > -4 && expt <= prec) {
/* Make %[gG] smell like %[fF] */
@@ -662,6 +669,7 @@
} else { /* glue together f_p fragments */
if (decimal_point == nullptr) decimal_point = nl_langinfo(RADIXCHAR);
if (!expchar) { /* %[fF] or sufficiently short %[gG] */
+ CHAR_TYPE* end = cp + ndig;
if (expt <= 0) {
PRINT(zeroes, 1);
if (prec || flags & ALT) PRINT(decimal_point, 1);
@@ -669,11 +677,11 @@
/* already handled initial 0's */
prec += expt;
} else {
- PRINTANDPAD(cp, dtoaend, lead, zeroes);
+ PRINTANDPAD(cp, end, lead, zeroes);
cp += lead;
if (prec || flags & ALT) PRINT(decimal_point, 1);
}
- PRINTANDPAD(cp, dtoaend, prec, zeroes);
+ PRINTANDPAD(cp, end, prec, zeroes);
} else { /* %[eE] or sufficiently long %[gG] */
if (prec > 1 || flags & ALT) {
buf[0] = *cp++;