mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-01-30 19:10:36 +08:00
* libc/stdio/vfprintf.c: Include locale.h also if _WANT_IO_C99_FORMATS
is defined. Raise conversion buffer size to make sure it has enough room for numbers plus grouping character. Define GROUPING flag. (_VFPRINTF_R): Add PRINTANDPAD macro. Handle grouping flag character. Handle grouping for decimal integer and float values. * libc/stdio/vfwprintf.c: Ditto.
This commit is contained in:
parent
6e3f2c626d
commit
b0776ebd41
@ -1,3 +1,12 @@
|
|||||||
|
2010-02-05 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* libc/stdio/vfprintf.c: Include locale.h also if _WANT_IO_C99_FORMATS
|
||||||
|
is defined. Raise conversion buffer size to make sure it has enough
|
||||||
|
room for numbers plus grouping character. Define GROUPING flag.
|
||||||
|
(_VFPRINTF_R): Add PRINTANDPAD macro. Handle grouping flag character.
|
||||||
|
Handle grouping for decimal integer and float values.
|
||||||
|
* libc/stdio/vfwprintf.c: Ditto.
|
||||||
|
|
||||||
2010-02-01 Christopher Faylor <me+cygwin@cgf.cx>
|
2010-02-01 Christopher Faylor <me+cygwin@cgf.cx>
|
||||||
|
|
||||||
* libc/stdlib/__atexit.c (__atexit_lock): Define a global lock for
|
* libc/stdlib/__atexit.c (__atexit_lock): Define a global lock for
|
||||||
|
@ -375,8 +375,10 @@ _DEFUN(__sbprintf, (rptr, fp, fmt, ap),
|
|||||||
#endif /* !STRING_ONLY */
|
#endif /* !STRING_ONLY */
|
||||||
|
|
||||||
|
|
||||||
#ifdef FLOATING_POINT
|
#if defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS)
|
||||||
# include <locale.h>
|
# include <locale.h>
|
||||||
|
#endif
|
||||||
|
#ifdef FLOATING_POINT
|
||||||
# include <math.h>
|
# include <math.h>
|
||||||
|
|
||||||
/* For %La, an exponent of 15 bits occupies the exponent character, a
|
/* For %La, an exponent of 15 bits occupies the exponent character, a
|
||||||
@ -423,8 +425,16 @@ static int exponent(char *, int, int);
|
|||||||
reentrant storage shared with mprec. All other formats that use
|
reentrant storage shared with mprec. All other formats that use
|
||||||
buf get by with fewer characters. Making BUF slightly bigger
|
buf get by with fewer characters. Making BUF slightly bigger
|
||||||
reduces the need for malloc in %.*a and %S, when large precision or
|
reduces the need for malloc in %.*a and %S, when large precision or
|
||||||
long strings are processed. */
|
long strings are processed.
|
||||||
|
The bigger size of 100 bytes is used on systems which allow number
|
||||||
|
strings using the locale's grouping character. Since that's a multibyte
|
||||||
|
value, we should use a conservative value.
|
||||||
|
*/
|
||||||
|
#ifdef _WANT_IO_C99_FORMATS
|
||||||
|
#define BUF 100
|
||||||
|
#else
|
||||||
#define BUF 40
|
#define BUF 40
|
||||||
|
#endif
|
||||||
#if defined _MB_CAPABLE && MB_LEN_MAX > BUF
|
#if defined _MB_CAPABLE && MB_LEN_MAX > BUF
|
||||||
# undef BUF
|
# undef BUF
|
||||||
# define BUF MB_LEN_MAX
|
# define BUF MB_LEN_MAX
|
||||||
@ -508,6 +518,9 @@ _EXFUN(get_arg, (struct _reent *data, int n, char *fmt,
|
|||||||
#else /* define as 0, to make SARG and UARG occupy fewer instructions */
|
#else /* define as 0, to make SARG and UARG occupy fewer instructions */
|
||||||
# define CHARINT 0
|
# define CHARINT 0
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef _WANT_IO_C99_FORMATS
|
||||||
|
# define GROUPING 0x400 /* use grouping ("'" flag) */
|
||||||
|
#endif
|
||||||
|
|
||||||
int _EXFUN(_VFPRINTF_R, (struct _reent *, FILE *, _CONST char *, va_list));
|
int _EXFUN(_VFPRINTF_R, (struct _reent *, FILE *, _CONST char *, va_list));
|
||||||
|
|
||||||
@ -552,6 +565,12 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap),
|
|||||||
int width; /* width from format (%8d), or 0 */
|
int width; /* width from format (%8d), or 0 */
|
||||||
int prec; /* precision from format (%.3d), or -1 */
|
int prec; /* precision from format (%.3d), or -1 */
|
||||||
char sign; /* sign prefix (' ', '+', '-', or \0) */
|
char sign; /* sign prefix (' ', '+', '-', or \0) */
|
||||||
|
#ifdef _WANT_IO_C99_FORMATS
|
||||||
|
/* locale specific numeric grouping */
|
||||||
|
char *thousands_sep;
|
||||||
|
size_t thsnd_len;
|
||||||
|
const char *grouping;
|
||||||
|
#endif
|
||||||
#ifdef FLOATING_POINT
|
#ifdef FLOATING_POINT
|
||||||
char *decimal_point = _localeconv_r (data)->decimal_point;
|
char *decimal_point = _localeconv_r (data)->decimal_point;
|
||||||
size_t decp_len = strlen (decimal_point);
|
size_t decp_len = strlen (decimal_point);
|
||||||
@ -560,9 +579,16 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap),
|
|||||||
# define _fpvalue (_double_.fp)
|
# define _fpvalue (_double_.fp)
|
||||||
int expt; /* integer value of exponent */
|
int expt; /* integer value of exponent */
|
||||||
int expsize = 0; /* character count for expstr */
|
int expsize = 0; /* character count for expstr */
|
||||||
int ndig = 0; /* actual number of digits returned by cvt */
|
|
||||||
char expstr[MAXEXPLEN]; /* buffer for exponent string */
|
char expstr[MAXEXPLEN]; /* buffer for exponent string */
|
||||||
|
int lead; /* sig figs before decimal or group sep */
|
||||||
#endif /* FLOATING_POINT */
|
#endif /* FLOATING_POINT */
|
||||||
|
#if defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS)
|
||||||
|
int ndig = 0; /* actual number of digits returned by cvt */
|
||||||
|
#endif
|
||||||
|
#ifdef _WANT_IO_C99_FORMATS
|
||||||
|
int nseps; /* number of group separators with ' */
|
||||||
|
int nrepeats; /* number of repeats of the last group */
|
||||||
|
#endif
|
||||||
u_quad_t _uquad; /* integer arguments %[diouxX] */
|
u_quad_t _uquad; /* integer arguments %[diouxX] */
|
||||||
enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
|
enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
|
||||||
int dprec; /* a copy of prec if [diouxX], 0 otherwise */
|
int dprec; /* a copy of prec if [diouxX], 0 otherwise */
|
||||||
@ -617,6 +643,14 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap),
|
|||||||
PRINT (with, n); \
|
PRINT (with, n); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
#define PRINTANDPAD(p, ep, len, with) { \
|
||||||
|
int n = (ep) - (p); \
|
||||||
|
if (n > (len)) \
|
||||||
|
n = (len); \
|
||||||
|
if (n > 0) \
|
||||||
|
PRINT((p), n); \
|
||||||
|
PAD((len) - (n > 0 ? n : 0), (with)); \
|
||||||
|
}
|
||||||
#define FLUSH() { \
|
#define FLUSH() { \
|
||||||
if (uio.uio_resid && __SPRINT(data, fp, &uio)) \
|
if (uio.uio_resid && __SPRINT(data, fp, &uio)) \
|
||||||
goto error; \
|
goto error; \
|
||||||
@ -757,6 +791,12 @@ _DEFUN(_VFPRINTF_R, (data, fp, fmt0, ap),
|
|||||||
width = 0;
|
width = 0;
|
||||||
prec = -1;
|
prec = -1;
|
||||||
sign = '\0';
|
sign = '\0';
|
||||||
|
#ifdef FLOATING_POINT
|
||||||
|
lead = 0;
|
||||||
|
#endif
|
||||||
|
#ifdef _WANT_IO_C99_FORMATS
|
||||||
|
nseps = nrepeats = 0;
|
||||||
|
#endif
|
||||||
#ifndef _NO_POS_ARGS
|
#ifndef _NO_POS_ARGS
|
||||||
N = arg_index;
|
N = arg_index;
|
||||||
is_pos_arg = 0;
|
is_pos_arg = 0;
|
||||||
@ -766,12 +806,12 @@ rflag: ch = *fmt++;
|
|||||||
reswitch: switch (ch) {
|
reswitch: switch (ch) {
|
||||||
#ifdef _WANT_IO_C99_FORMATS
|
#ifdef _WANT_IO_C99_FORMATS
|
||||||
case '\'':
|
case '\'':
|
||||||
/* The ' flag is required by POSIX, but not C99.
|
thousands_sep = _localeconv_r (data)->thousands_sep;
|
||||||
In the C locale, LC_NUMERIC requires
|
thsnd_len = strlen (thousands_sep);
|
||||||
thousands_sep to be the empty string. And since
|
grouping = _localeconv_r (data)->grouping;
|
||||||
no other locales are supported (yet), this flag
|
if (thsnd_len > 0 && grouping && *grouping)
|
||||||
is currently a no-op. */
|
flags |= GROUPING;
|
||||||
goto rflag;
|
goto rflag;
|
||||||
#endif
|
#endif
|
||||||
case ' ':
|
case ' ':
|
||||||
/*
|
/*
|
||||||
@ -1140,22 +1180,46 @@ reswitch: switch (ch) {
|
|||||||
size = expsize + ndig;
|
size = expsize + ndig;
|
||||||
if (ndig > 1 || flags & ALT)
|
if (ndig > 1 || flags & ALT)
|
||||||
++size;
|
++size;
|
||||||
} else if (ch == 'f') { /* f fmt */
|
# ifdef _WANT_IO_C99_FORMATS
|
||||||
if (expt > 0) {
|
flags &= ~GROUPING;
|
||||||
|
# endif
|
||||||
|
} else {
|
||||||
|
if (ch == 'f') { /* f fmt */
|
||||||
|
if (expt > 0) {
|
||||||
|
size = expt;
|
||||||
|
if (prec || flags & ALT)
|
||||||
|
size += prec + 1;
|
||||||
|
} else /* "0.X" */
|
||||||
|
size = (prec || flags & ALT)
|
||||||
|
? prec + 2
|
||||||
|
: 1;
|
||||||
|
} else if (expt >= ndig) { /* fixed g fmt */
|
||||||
size = expt;
|
size = expt;
|
||||||
if (prec || flags & ALT)
|
if (flags & ALT)
|
||||||
size += prec + 1;
|
++size;
|
||||||
} else /* "0.X" */
|
} else
|
||||||
size = (prec || flags & ALT)
|
size = ndig + (expt > 0 ?
|
||||||
? prec + 2
|
1 : 2 - expt);
|
||||||
: 1;
|
# ifdef _WANT_IO_C99_FORMATS
|
||||||
} else if (expt >= ndig) { /* fixed g fmt */
|
if ((flags & GROUPING) && expt > 0) {
|
||||||
size = expt;
|
/* space for thousands' grouping */
|
||||||
if (flags & ALT)
|
nseps = nrepeats = 0;
|
||||||
++size;
|
lead = expt;
|
||||||
} else
|
while (*grouping != CHAR_MAX) {
|
||||||
size = ndig + (expt > 0 ?
|
if (lead <= *grouping)
|
||||||
1 : 2 - expt);
|
break;
|
||||||
|
lead -= *grouping;
|
||||||
|
if (grouping[1]) {
|
||||||
|
nseps++;
|
||||||
|
grouping++;
|
||||||
|
} else
|
||||||
|
nrepeats++;
|
||||||
|
}
|
||||||
|
size += (nseps + nrepeats) * thsnd_len;
|
||||||
|
} else
|
||||||
|
# endif
|
||||||
|
lead = expt;
|
||||||
|
}
|
||||||
|
|
||||||
if (softsign)
|
if (softsign)
|
||||||
sign = '-';
|
sign = '-';
|
||||||
@ -1184,6 +1248,9 @@ reswitch: switch (ch) {
|
|||||||
case 'o':
|
case 'o':
|
||||||
_uquad = UARG ();
|
_uquad = UARG ();
|
||||||
base = OCT;
|
base = OCT;
|
||||||
|
#ifdef _WANT_IO_C99_FORMATS
|
||||||
|
flags &= ~GROUPING;
|
||||||
|
#endif
|
||||||
goto nosign;
|
goto nosign;
|
||||||
case 'p':
|
case 'p':
|
||||||
/*
|
/*
|
||||||
@ -1320,6 +1387,9 @@ hex: _uquad = UARG ();
|
|||||||
flags |= HEXPREFIX;
|
flags |= HEXPREFIX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WANT_IO_C99_FORMATS
|
||||||
|
flags &= ~GROUPING;
|
||||||
|
#endif
|
||||||
/* unsigned conversions */
|
/* unsigned conversions */
|
||||||
nosign: sign = '\0';
|
nosign: sign = '\0';
|
||||||
/*
|
/*
|
||||||
@ -1355,11 +1425,37 @@ number: if ((dprec = prec) >= 0)
|
|||||||
|
|
||||||
case DEC:
|
case DEC:
|
||||||
/* many numbers are 1 digit */
|
/* many numbers are 1 digit */
|
||||||
while (_uquad >= 10) {
|
if (_uquad < 10) {
|
||||||
*--cp = to_char (_uquad % 10);
|
*--cp = to_char(_uquad);
|
||||||
_uquad /= 10;
|
break;
|
||||||
}
|
}
|
||||||
*--cp = to_char (_uquad);
|
#ifdef _WANT_IO_C99_FORMATS
|
||||||
|
ndig = 0;
|
||||||
|
#endif
|
||||||
|
do {
|
||||||
|
*--cp = to_char (_uquad % 10);
|
||||||
|
#ifdef _WANT_IO_C99_FORMATS
|
||||||
|
ndig++;
|
||||||
|
/* If (*grouping == CHAR_MAX) then no
|
||||||
|
more grouping */
|
||||||
|
if ((flags & GROUPING)
|
||||||
|
&& ndig == *grouping
|
||||||
|
&& *grouping != CHAR_MAX
|
||||||
|
&& _uquad > 9) {
|
||||||
|
cp -= thsnd_len;
|
||||||
|
strncpy (cp, thousands_sep,
|
||||||
|
thsnd_len);
|
||||||
|
ndig = 0;
|
||||||
|
/* If (grouping[1] == '\0') then we
|
||||||
|
have to use *grouping character
|
||||||
|
(last grouping rule) for all
|
||||||
|
next cases. */
|
||||||
|
if (grouping[1] != '\0')
|
||||||
|
grouping++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
_uquad /= 10;
|
||||||
|
} while (_uquad != 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HEX:
|
case HEX:
|
||||||
@ -1459,16 +1555,33 @@ number: if ((dprec = prec) >= 0)
|
|||||||
PAD (-expt, zeroes);
|
PAD (-expt, zeroes);
|
||||||
PRINT (cp, ndig);
|
PRINT (cp, ndig);
|
||||||
}
|
}
|
||||||
} else if (expt >= ndig) {
|
|
||||||
PRINT (cp, ndig);
|
|
||||||
PAD (expt - ndig, zeroes);
|
|
||||||
if (flags & ALT)
|
|
||||||
PRINT (decimal_point, decp_len);
|
|
||||||
} else {
|
} else {
|
||||||
PRINT (cp, expt);
|
char *convbuf = cp;
|
||||||
cp += expt;
|
PRINTANDPAD(cp, convbuf + ndig,
|
||||||
PRINT (decimal_point, decp_len);
|
lead, zeroes);
|
||||||
PRINT (cp, ndig - expt);
|
cp += lead;
|
||||||
|
#ifdef _WANT_IO_C99_FORMATS
|
||||||
|
if (flags & GROUPING) {
|
||||||
|
while (nseps > 0 || nrepeats > 0) {
|
||||||
|
if (nrepeats > 0)
|
||||||
|
nrepeats--;
|
||||||
|
else {
|
||||||
|
grouping--;
|
||||||
|
nseps--;
|
||||||
|
}
|
||||||
|
PRINT(thousands_sep, thsnd_len);
|
||||||
|
PRINTANDPAD (cp, convbuf + ndig,
|
||||||
|
*grouping, zeroes);
|
||||||
|
cp += *grouping;
|
||||||
|
}
|
||||||
|
if (cp > convbuf + ndig)
|
||||||
|
cp = convbuf + ndig;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (prec || flags & ALT)
|
||||||
|
PRINT (decimal_point, decp_len);
|
||||||
|
PRINTANDPAD (cp, convbuf + ndig,
|
||||||
|
ndig - expt, zeroes);
|
||||||
}
|
}
|
||||||
} else { /* 'a', 'A', 'e', or 'E' */
|
} else { /* 'a', 'A', 'e', or 'E' */
|
||||||
if (ndig > 1 || flags & ALT) {
|
if (ndig > 1 || flags & ALT) {
|
||||||
|
@ -201,8 +201,10 @@ _DEFUN(__sbwprintf, (rptr, fp, fmt, ap),
|
|||||||
#endif /* !STRING_ONLY */
|
#endif /* !STRING_ONLY */
|
||||||
|
|
||||||
|
|
||||||
#ifdef FLOATING_POINT
|
#if defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS)
|
||||||
# include <locale.h>
|
# include <locale.h>
|
||||||
|
#endif
|
||||||
|
#ifdef FLOATING_POINT
|
||||||
# include <math.h>
|
# include <math.h>
|
||||||
|
|
||||||
/* For %La, an exponent of 15 bits occupies the exponent character, a
|
/* For %La, an exponent of 15 bits occupies the exponent character, a
|
||||||
@ -249,8 +251,16 @@ static int wexponent(wchar_t *, int, int);
|
|||||||
reentrant storage shared with mprec. All other formats that use
|
reentrant storage shared with mprec. All other formats that use
|
||||||
buf get by with fewer characters. Making BUF slightly bigger
|
buf get by with fewer characters. Making BUF slightly bigger
|
||||||
reduces the need for malloc in %.*a and %ls/%S, when large precision or
|
reduces the need for malloc in %.*a and %ls/%S, when large precision or
|
||||||
long strings are processed. */
|
long strings are processed.
|
||||||
|
The bigger size of 100 bytes is used on systems which allow number
|
||||||
|
strings using the locale's grouping character. Since that's a multibyte
|
||||||
|
value, we should use a conservative value.
|
||||||
|
*/
|
||||||
|
#ifdef _WANT_IO_C99_FORMATS
|
||||||
|
#define BUF 100
|
||||||
|
#else
|
||||||
#define BUF 40
|
#define BUF 40
|
||||||
|
#endif
|
||||||
#if defined _MB_CAPABLE && MB_LEN_MAX > BUF
|
#if defined _MB_CAPABLE && MB_LEN_MAX > BUF
|
||||||
# undef BUF
|
# undef BUF
|
||||||
# define BUF MB_LEN_MAX
|
# define BUF MB_LEN_MAX
|
||||||
@ -336,6 +346,9 @@ _EXFUN(get_arg, (struct _reent *data, int n, wchar_t *fmt,
|
|||||||
#else /* define as 0, to make SARG and UARG occupy fewer instructions */
|
#else /* define as 0, to make SARG and UARG occupy fewer instructions */
|
||||||
# define CHARINT 0
|
# define CHARINT 0
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef _WANT_IO_C99_FORMATS
|
||||||
|
# define GROUPING 0x400 /* use grouping ("'" flag) */
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef STRING_ONLY
|
#ifndef STRING_ONLY
|
||||||
int
|
int
|
||||||
@ -378,19 +391,31 @@ _DEFUN(_VFWPRINTF_R, (data, fp, fmt0, ap),
|
|||||||
int width; /* width from format (%8d), or 0 */
|
int width; /* width from format (%8d), or 0 */
|
||||||
int prec; /* precision from format (%.3d), or -1 */
|
int prec; /* precision from format (%.3d), or -1 */
|
||||||
wchar_t sign; /* sign prefix (' ', '+', '-', or \0) */
|
wchar_t sign; /* sign prefix (' ', '+', '-', or \0) */
|
||||||
#ifdef FLOATING_POINT
|
#ifdef _WANT_IO_C99_FORMATS
|
||||||
wchar_t decimal_point;
|
/* locale specific numeric grouping */
|
||||||
|
wchar_t thousands_sep;
|
||||||
|
const char *grouping;
|
||||||
|
#endif
|
||||||
#ifdef _MB_CAPABLE
|
#ifdef _MB_CAPABLE
|
||||||
mbstate_t state; /* mbtowc calls from library must not change state */
|
mbstate_t state; /* mbtowc calls from library must not change state */
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef FLOATING_POINT
|
||||||
|
wchar_t decimal_point;
|
||||||
wchar_t softsign; /* temporary negative sign for floats */
|
wchar_t softsign; /* temporary negative sign for floats */
|
||||||
union { int i; _PRINTF_FLOAT_TYPE fp; } _double_ = {0};
|
union { int i; _PRINTF_FLOAT_TYPE fp; } _double_ = {0};
|
||||||
# define _fpvalue (_double_.fp)
|
# define _fpvalue (_double_.fp)
|
||||||
int expt; /* integer value of exponent */
|
int expt; /* integer value of exponent */
|
||||||
int expsize = 0; /* character count for expstr */
|
int expsize = 0; /* character count for expstr */
|
||||||
int ndig = 0; /* actual number of digits returned by wcvt */
|
|
||||||
wchar_t expstr[MAXEXPLEN]; /* buffer for exponent string */
|
wchar_t expstr[MAXEXPLEN]; /* buffer for exponent string */
|
||||||
|
int lead; /* sig figs before decimal or group sep */
|
||||||
#endif /* FLOATING_POINT */
|
#endif /* FLOATING_POINT */
|
||||||
|
#if defined (FLOATING_POINT) || defined (_WANT_IO_C99_FORMATS)
|
||||||
|
int ndig = 0; /* actual number of digits returned by cvt */
|
||||||
|
#endif
|
||||||
|
#ifdef _WANT_IO_C99_FORMATS
|
||||||
|
int nseps; /* number of group separators with ' */
|
||||||
|
int nrepeats; /* number of repeats of the last group */
|
||||||
|
#endif
|
||||||
u_quad_t _uquad; /* integer arguments %[diouxX] */
|
u_quad_t _uquad; /* integer arguments %[diouxX] */
|
||||||
enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
|
enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */
|
||||||
int dprec; /* a copy of prec if [diouxX], 0 otherwise */
|
int dprec; /* a copy of prec if [diouxX], 0 otherwise */
|
||||||
@ -419,9 +444,16 @@ _DEFUN(_VFWPRINTF_R, (data, fp, fmt0, ap),
|
|||||||
|
|
||||||
#ifdef FLOATING_POINT
|
#ifdef FLOATING_POINT
|
||||||
#ifdef _MB_CAPABLE
|
#ifdef _MB_CAPABLE
|
||||||
memset (&state, '\0', sizeof (state));
|
{
|
||||||
_mbrtowc_r (data, &decimal_point, _localeconv_r (data)->decimal_point,
|
size_t nconv;
|
||||||
MB_CUR_MAX, &state);
|
|
||||||
|
memset (&state, '\0', sizeof (state));
|
||||||
|
nconv = _mbrtowc_r (data, &decimal_point,
|
||||||
|
_localeconv_r (data)->decimal_point,
|
||||||
|
MB_CUR_MAX, &state);
|
||||||
|
if (nconv == (size_t) -1 || nconv == (size_t) -2)
|
||||||
|
decimal_point = L'.';
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
decimal_point = (wchar_t) *_localeconv_r (data)->decimal_point;
|
decimal_point = (wchar_t) *_localeconv_r (data)->decimal_point;
|
||||||
#endif
|
#endif
|
||||||
@ -449,6 +481,14 @@ _DEFUN(_VFWPRINTF_R, (data, fp, fmt0, ap),
|
|||||||
PRINT (with, n); \
|
PRINT (with, n); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
#define PRINTANDPAD(p, ep, len, with) { \
|
||||||
|
int n = (ep) - (p); \
|
||||||
|
if (n > (len)) \
|
||||||
|
n = (len); \
|
||||||
|
if (n > 0) \
|
||||||
|
PRINT((p), n); \
|
||||||
|
PAD((len) - (n > 0 ? n : 0), (with)); \
|
||||||
|
}
|
||||||
#define FLUSH() { \
|
#define FLUSH() { \
|
||||||
if (uio.uio_resid && __SPRINT(data, fp, &uio)) \
|
if (uio.uio_resid && __SPRINT(data, fp, &uio)) \
|
||||||
goto error; \
|
goto error; \
|
||||||
@ -570,6 +610,12 @@ _DEFUN(_VFWPRINTF_R, (data, fp, fmt0, ap),
|
|||||||
width = 0;
|
width = 0;
|
||||||
prec = -1;
|
prec = -1;
|
||||||
sign = L'\0';
|
sign = L'\0';
|
||||||
|
#ifdef FLOATING_POINT
|
||||||
|
lead = 0;
|
||||||
|
#endif
|
||||||
|
#ifdef _WANT_IO_C99_FORMATS
|
||||||
|
nseps = nrepeats = 0;
|
||||||
|
#endif
|
||||||
#ifndef _NO_POS_ARGS
|
#ifndef _NO_POS_ARGS
|
||||||
N = arg_index;
|
N = arg_index;
|
||||||
is_pos_arg = 0;
|
is_pos_arg = 0;
|
||||||
@ -579,8 +625,23 @@ rflag: ch = *fmt++;
|
|||||||
reswitch: switch (ch) {
|
reswitch: switch (ch) {
|
||||||
#ifdef _WANT_IO_C99_FORMATS
|
#ifdef _WANT_IO_C99_FORMATS
|
||||||
case L'\'':
|
case L'\'':
|
||||||
/* The ' flag is required by POSIX, but not C99.
|
#ifdef _MB_CAPABLE
|
||||||
FIXME: this flag is currently a no-op. */
|
{
|
||||||
|
size_t nconv;
|
||||||
|
|
||||||
|
memset (&state, '\0', sizeof (state));
|
||||||
|
nconv = _mbrtowc_r (data, &thousands_sep,
|
||||||
|
_localeconv_r (data)->thousands_sep,
|
||||||
|
MB_CUR_MAX, &state);
|
||||||
|
if (nconv == (size_t) -1 || nconv == (size_t) -2)
|
||||||
|
thousands_sep = L'\0';
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
thousands_sep = (wchar_t) *_localeconv_r(data)->thousands_sep;
|
||||||
|
#endif
|
||||||
|
grouping = _localeconv_r (data)->grouping;
|
||||||
|
if (thousands_sep && grouping && *grouping)
|
||||||
|
flags |= GROUPING;
|
||||||
goto rflag;
|
goto rflag;
|
||||||
#endif
|
#endif
|
||||||
case L' ':
|
case L' ':
|
||||||
@ -942,23 +1003,46 @@ reswitch: switch (ch) {
|
|||||||
size = expsize + ndig;
|
size = expsize + ndig;
|
||||||
if (ndig > 1 || flags & ALT)
|
if (ndig > 1 || flags & ALT)
|
||||||
++size;
|
++size;
|
||||||
} else if (ch == L'f') { /* f fmt */
|
# ifdef _WANT_IO_C99_FORMATS
|
||||||
if (expt > 0) {
|
flags &= ~GROUPING;
|
||||||
|
# endif
|
||||||
|
} else {
|
||||||
|
if (ch == L'f') { /* f fmt */
|
||||||
|
if (expt > 0) {
|
||||||
|
size = expt;
|
||||||
|
if (prec || flags & ALT)
|
||||||
|
size += prec + 1;
|
||||||
|
} else /* "0.X" */
|
||||||
|
size = (prec || flags & ALT)
|
||||||
|
? prec + 2
|
||||||
|
: 1;
|
||||||
|
} else if (expt >= ndig) { /* fixed g fmt */
|
||||||
size = expt;
|
size = expt;
|
||||||
if (prec || flags & ALT)
|
if (flags & ALT)
|
||||||
size += prec + 1;
|
++size;
|
||||||
} else /* "0.X" */
|
} else
|
||||||
size = (prec || flags & ALT)
|
size = ndig + (expt > 0 ?
|
||||||
? prec + 2
|
1 : 2 - expt);
|
||||||
: 1;
|
# ifdef _WANT_IO_C99_FORMATS
|
||||||
} else if (expt >= ndig) { /* fixed g fmt */
|
if ((flags & GROUPING) && expt > 0) {
|
||||||
size = expt;
|
/* space for thousands' grouping */
|
||||||
if (flags & ALT)
|
nseps = nrepeats = 0;
|
||||||
++size;
|
lead = expt;
|
||||||
} else
|
while (*grouping != CHAR_MAX) {
|
||||||
size = ndig + (expt > 0 ?
|
if (lead <= *grouping)
|
||||||
1 : 2 - expt);
|
break;
|
||||||
|
lead -= *grouping;
|
||||||
|
if (grouping[1]) {
|
||||||
|
nseps++;
|
||||||
|
grouping++;
|
||||||
|
} else
|
||||||
|
nrepeats++;
|
||||||
|
}
|
||||||
|
size += nseps + nrepeats;
|
||||||
|
} else
|
||||||
|
# endif
|
||||||
|
lead = expt;
|
||||||
|
}
|
||||||
if (softsign)
|
if (softsign)
|
||||||
sign = L'-';
|
sign = L'-';
|
||||||
break;
|
break;
|
||||||
@ -983,6 +1067,9 @@ reswitch: switch (ch) {
|
|||||||
case L'o':
|
case L'o':
|
||||||
_uquad = UARG ();
|
_uquad = UARG ();
|
||||||
base = OCT;
|
base = OCT;
|
||||||
|
#ifdef _WANT_IO_C99_FORMATS
|
||||||
|
flags &= ~GROUPING;
|
||||||
|
#endif
|
||||||
goto nosign;
|
goto nosign;
|
||||||
case L'p':
|
case L'p':
|
||||||
/*
|
/*
|
||||||
@ -1106,6 +1193,9 @@ hex: _uquad = UARG ();
|
|||||||
flags |= HEXPREFIX;
|
flags |= HEXPREFIX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WANT_IO_C99_FORMATS
|
||||||
|
flags &= ~GROUPING;
|
||||||
|
#endif
|
||||||
/* unsigned conversions */
|
/* unsigned conversions */
|
||||||
nosign: sign = L'\0';
|
nosign: sign = L'\0';
|
||||||
/*
|
/*
|
||||||
@ -1141,11 +1231,35 @@ number: if ((dprec = prec) >= 0)
|
|||||||
|
|
||||||
case DEC:
|
case DEC:
|
||||||
/* many numbers are 1 digit */
|
/* many numbers are 1 digit */
|
||||||
while (_uquad >= 10) {
|
if (_uquad < 10) {
|
||||||
*--cp = to_char (_uquad % 10);
|
*--cp = to_char(_uquad);
|
||||||
_uquad /= 10;
|
break;
|
||||||
}
|
}
|
||||||
*--cp = to_char (_uquad);
|
#ifdef _WANT_IO_C99_FORMATS
|
||||||
|
ndig = 0;
|
||||||
|
#endif
|
||||||
|
do {
|
||||||
|
*--cp = to_char (_uquad % 10);
|
||||||
|
#ifdef _WANT_IO_C99_FORMATS
|
||||||
|
ndig++;
|
||||||
|
/* If (*grouping == CHAR_MAX) then no
|
||||||
|
more grouping */
|
||||||
|
if ((flags & GROUPING)
|
||||||
|
&& ndig == *grouping
|
||||||
|
&& *grouping != CHAR_MAX
|
||||||
|
&& _uquad > 9) {
|
||||||
|
*--cp = thousands_sep;
|
||||||
|
ndig = 0;
|
||||||
|
/* If (grouping[1] == '\0') then we
|
||||||
|
have to use *grouping character
|
||||||
|
(last grouping rule) for all
|
||||||
|
next cases. */
|
||||||
|
if (grouping[1] != '\0')
|
||||||
|
grouping++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
_uquad /= 10;
|
||||||
|
} while (_uquad != 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HEX:
|
case HEX:
|
||||||
@ -1245,17 +1359,35 @@ number: if ((dprec = prec) >= 0)
|
|||||||
PAD (-expt, zeroes);
|
PAD (-expt, zeroes);
|
||||||
PRINT (cp, ndig);
|
PRINT (cp, ndig);
|
||||||
}
|
}
|
||||||
} else if (expt >= ndig) {
|
|
||||||
PRINT (cp, ndig);
|
|
||||||
PAD (expt - ndig, zeroes);
|
|
||||||
if (flags & ALT)
|
|
||||||
PRINT (&decimal_point, 1);
|
|
||||||
} else {
|
} else {
|
||||||
PRINT (cp, expt);
|
wchar_t *convbuf = cp;
|
||||||
cp += expt;
|
PRINTANDPAD(cp, convbuf + ndig,
|
||||||
PRINT (&decimal_point, 1);
|
lead, zeroes);
|
||||||
PRINT (cp, ndig - expt);
|
cp += lead;
|
||||||
|
#ifdef _WANT_IO_C99_FORMATS
|
||||||
|
if (flags & GROUPING) {
|
||||||
|
while (nseps > 0 || nrepeats > 0) {
|
||||||
|
if (nrepeats > 0)
|
||||||
|
nrepeats--;
|
||||||
|
else {
|
||||||
|
grouping--;
|
||||||
|
nseps--;
|
||||||
|
}
|
||||||
|
PRINT (&thousands_sep, 1);
|
||||||
|
PRINTANDPAD (cp, convbuf + ndig,
|
||||||
|
*grouping, zeroes);
|
||||||
|
cp += *grouping;
|
||||||
|
}
|
||||||
|
if (cp > convbuf + ndig)
|
||||||
|
cp = convbuf + ndig;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (prec || flags & ALT)
|
||||||
|
PRINT (&decimal_point, 1);
|
||||||
|
PRINTANDPAD (cp, convbuf + ndig,
|
||||||
|
ndig - expt, zeroes);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else { /* 'a', 'A', 'e', or 'E' */
|
} else { /* 'a', 'A', 'e', or 'E' */
|
||||||
if (ndig > 1 || flags & ALT) {
|
if (ndig > 1 || flags & ALT) {
|
||||||
PRINT (cp, 1);
|
PRINT (cp, 1);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user