Add support for multibyte decimal_point encodings, e.g., U+066B.

This commit is contained in:
David Schultz 2009-01-19 06:19:38 +00:00
parent 96b774f489
commit 5004a238c3
2 changed files with 35 additions and 23 deletions

View File

@ -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 */

View File

@ -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);