Add support for multibyte decimal_point encodings, e.g., U+066B.
This commit is contained in:
parent
96b774f489
commit
5004a238c3
@ -251,6 +251,7 @@ __vfprintf(FILE *fp, const char *fmt0, va_list ap)
|
||||
* F: at least two digits for decimal, at least one digit for hex
|
||||
*/
|
||||
char *decimal_point; /* locale specific decimal point */
|
||||
int decpt_len; /* length of decimal_point */
|
||||
int signflag; /* true if float is negative */
|
||||
union { /* floating point arguments %[aAeEfFgG] */
|
||||
double dbl;
|
||||
@ -389,6 +390,8 @@ __vfprintf(FILE *fp, const char *fmt0, va_list ap)
|
||||
#ifndef NO_FLOATING_POINT
|
||||
dtoaresult = NULL;
|
||||
decimal_point = localeconv()->decimal_point;
|
||||
/* The overwhelmingly common case is decpt_len == 1. */
|
||||
decpt_len = (decimal_point[1] == '\0' ? 1 : strlen(decimal_point));
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -672,7 +675,7 @@ reswitch: switch (ch) {
|
||||
expsize = exponent(expstr, expt - 1, expchar);
|
||||
size = expsize + prec;
|
||||
if (prec > 1 || flags & ALT)
|
||||
++size;
|
||||
size += decpt_len;
|
||||
} else {
|
||||
/* space for digits before decimal point */
|
||||
if (expt > 0)
|
||||
@ -681,7 +684,7 @@ reswitch: switch (ch) {
|
||||
size = 1;
|
||||
/* space for decimal pt and following digits */
|
||||
if (prec || flags & ALT)
|
||||
size += prec + 1;
|
||||
size += prec + decpt_len;
|
||||
if (grouping && expt > 0) {
|
||||
/* space for thousands' grouping */
|
||||
nseps = nrepeats = 0;
|
||||
@ -920,7 +923,7 @@ number: if ((dprec = prec) >= 0)
|
||||
if (expt <= 0) {
|
||||
PRINT(zeroes, 1);
|
||||
if (prec || flags & ALT)
|
||||
PRINT(decimal_point, 1);
|
||||
PRINT(decimal_point,decpt_len);
|
||||
PAD(-expt, zeroes);
|
||||
/* already handled initial 0's */
|
||||
prec += expt;
|
||||
@ -945,14 +948,13 @@ number: if ((dprec = prec) >= 0)
|
||||
cp = dtoaend;
|
||||
}
|
||||
if (prec || flags & ALT)
|
||||
PRINT(decimal_point,1);
|
||||
PRINT(decimal_point,decpt_len);
|
||||
}
|
||||
PRINTANDPAD(cp, dtoaend, prec, zeroes);
|
||||
} else { /* %[eE] or sufficiently long %[gG] */
|
||||
if (prec > 1 || flags & ALT) {
|
||||
buf[0] = *cp++;
|
||||
buf[1] = *decimal_point;
|
||||
PRINT(buf, 2);
|
||||
PRINT(cp++, 1);
|
||||
PRINT(decimal_point, decpt_len);
|
||||
PRINT(cp, ndig-1);
|
||||
PAD(prec - ndig, zeroes);
|
||||
} else /* XeYYY */
|
||||
|
@ -74,6 +74,22 @@ static wchar_t *__mbsconv(char *, int);
|
||||
#define CHAR wchar_t
|
||||
#include "printfcommon.h"
|
||||
|
||||
static const mbstate_t initial_mbs;
|
||||
|
||||
static inline wchar_t
|
||||
get_decpt(void)
|
||||
{
|
||||
mbstate_t mbs;
|
||||
wchar_t decpt;
|
||||
int nconv;
|
||||
|
||||
mbs = initial_mbs;
|
||||
nconv = mbrtowc(&decpt, localeconv()->decimal_point, MB_CUR_MAX, &mbs);
|
||||
if (nconv == (size_t)-1 || nconv == (size_t)-2)
|
||||
decpt = '.'; /* failsafe */
|
||||
return (decpt);
|
||||
}
|
||||
|
||||
/*
|
||||
* Flush out all the vectors defined by the given uio,
|
||||
* then reset it so that it can be reused.
|
||||
@ -147,7 +163,6 @@ __sbprintf(FILE *fp, const wchar_t *fmt, va_list ap)
|
||||
static wint_t
|
||||
__xfputwc(wchar_t wc, FILE *fp)
|
||||
{
|
||||
static const mbstate_t initial;
|
||||
mbstate_t mbs;
|
||||
char buf[MB_LEN_MAX];
|
||||
struct __suio uio;
|
||||
@ -157,7 +172,7 @@ __xfputwc(wchar_t wc, FILE *fp)
|
||||
if ((fp->_flags & __SSTR) == 0)
|
||||
return (__fputwc(wc, fp));
|
||||
|
||||
mbs = initial;
|
||||
mbs = initial_mbs;
|
||||
if ((len = wcrtomb(buf, wc, &mbs)) == (size_t)-1) {
|
||||
fp->_flags |= __SERR;
|
||||
return (WEOF);
|
||||
@ -179,7 +194,6 @@ __xfputwc(wchar_t wc, FILE *fp)
|
||||
static wchar_t *
|
||||
__mbsconv(char *mbsarg, int prec)
|
||||
{
|
||||
static const mbstate_t initial;
|
||||
mbstate_t mbs;
|
||||
wchar_t *convbuf, *wcp;
|
||||
const char *p;
|
||||
@ -199,7 +213,7 @@ __mbsconv(char *mbsarg, int prec)
|
||||
*/
|
||||
p = mbsarg;
|
||||
insize = nchars = 0;
|
||||
mbs = initial;
|
||||
mbs = initial_mbs;
|
||||
while (nchars != (size_t)prec) {
|
||||
nconv = mbrlen(p, MB_CUR_MAX, &mbs);
|
||||
if (nconv == 0 || nconv == (size_t)-1 ||
|
||||
@ -226,7 +240,7 @@ __mbsconv(char *mbsarg, int prec)
|
||||
return (NULL);
|
||||
wcp = convbuf;
|
||||
p = mbsarg;
|
||||
mbs = initial;
|
||||
mbs = initial_mbs;
|
||||
while (insize != 0) {
|
||||
nconv = mbrtowc(wcp, p, insize, &mbs);
|
||||
if (nconv == 0 || nconv == (size_t)-1 || nconv == (size_t)-2)
|
||||
@ -305,7 +319,7 @@ __vfwprintf(FILE *fp, const wchar_t *fmt0, va_list ap)
|
||||
* D: expchar holds this character; '\0' if no exponent, e.g. %f
|
||||
* F: at least two digits for decimal, at least one digit for hex
|
||||
*/
|
||||
char *decimal_point; /* locale specific decimal point */
|
||||
wchar_t decimal_point; /* locale specific decimal point */
|
||||
int signflag; /* true if float is negative */
|
||||
union { /* floating point arguments %[aAeEfFgG] */
|
||||
double dbl;
|
||||
@ -438,7 +452,7 @@ __vfwprintf(FILE *fp, const wchar_t *fmt0, va_list ap)
|
||||
io_init(&io, fp);
|
||||
ret = 0;
|
||||
#ifndef NO_FLOATING_POINT
|
||||
decimal_point = localeconv()->decimal_point;
|
||||
decimal_point = get_decpt();
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -965,10 +979,8 @@ number: if ((dprec = prec) >= 0)
|
||||
if (!expchar) { /* %[fF] or sufficiently short %[gG] */
|
||||
if (expt <= 0) {
|
||||
PRINT(zeroes, 1);
|
||||
if (prec || flags & ALT) {
|
||||
buf[0] = *decimal_point;
|
||||
PRINT(buf, 1);
|
||||
}
|
||||
if (prec || flags & ALT)
|
||||
PRINT(&decimal_point, 1);
|
||||
PAD(-expt, zeroes);
|
||||
/* already handled initial 0's */
|
||||
prec += expt;
|
||||
@ -993,16 +1005,14 @@ number: if ((dprec = prec) >= 0)
|
||||
if (cp > convbuf + ndig)
|
||||
cp = convbuf + ndig;
|
||||
}
|
||||
if (prec || flags & ALT) {
|
||||
buf[0] = *decimal_point;
|
||||
PRINT(buf, 1);
|
||||
}
|
||||
if (prec || flags & ALT)
|
||||
PRINT(&decimal_point, 1);
|
||||
}
|
||||
PRINTANDPAD(cp, convbuf + ndig, prec, zeroes);
|
||||
} else { /* %[eE] or sufficiently long %[gG] */
|
||||
if (prec > 1 || flags & ALT) {
|
||||
buf[0] = *cp++;
|
||||
buf[1] = *decimal_point;
|
||||
buf[1] = decimal_point;
|
||||
PRINT(buf, 2);
|
||||
PRINT(cp, ndig-1);
|
||||
PAD(prec - ndig, zeroes);
|
||||
|
Loading…
Reference in New Issue
Block a user