Author: das
Date: Mon Jan 19 06:19:38 2009
New Revision: 187421
URL: http://svn.freebsd.org/changeset/base/187421

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

Modified:
  head/lib/libc/stdio/vfprintf.c
  head/lib/libc/stdio/vfwprintf.c

Modified: head/lib/libc/stdio/vfprintf.c
==============================================================================
--- head/lib/libc/stdio/vfprintf.c      Mon Jan 19 05:20:52 2009        
(r187420)
+++ head/lib/libc/stdio/vfprintf.c      Mon Jan 19 06:19:38 2009        
(r187421)
@@ -251,6 +251,7 @@ __vfprintf(FILE *fp, const char *fmt0, v
         * 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, v
 #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 @@ fp_common:
                                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 @@ fp_common:
                                        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 */

Modified: head/lib/libc/stdio/vfwprintf.c
==============================================================================
--- head/lib/libc/stdio/vfwprintf.c     Mon Jan 19 05:20:52 2009        
(r187420)
+++ head/lib/libc/stdio/vfwprintf.c     Mon Jan 19 06:19:38 2009        
(r187421)
@@ -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,
 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 *fmt
         * 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 *fmt
        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);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to