vfprintf: Reuse work_buffer in group_number

This commit is contained in:
Florian Weimer 2017-06-29 09:37:13 +02:00
parent 12d5853e22
commit edc1686af0
2 changed files with 44 additions and 29 deletions

View File

@ -1,3 +1,9 @@
2017-06-29 Florian Weimer <fweimer@redhat.com>
* stdio-common/vfprintf.c (group_number): Add front_ptr argument.
Use it to make the temporary copy at the start of the work buffer.
(process_arg): Adjust call to group_number.
2017-06-29 Florian Weimer <fweimer@redhat.com> 2017-06-29 Florian Weimer <fweimer@redhat.com>
* stdio-common/vfprintf.c (printf_positional): Use struct * stdio-common/vfprintf.c (printf_positional): Use struct

View File

@ -595,9 +595,8 @@ static const uint8_t jump_table[] =
string = _itoa (number.longlong, workend, base, \ string = _itoa (number.longlong, workend, base, \
spec == L_('X')); \ spec == L_('X')); \
if (group && grouping) \ if (group && grouping) \
string = group_number (string, workend, grouping, \ string = group_number (work_buffer, string, workend, \
thousands_sep); \ grouping, thousands_sep); \
\
if (use_outdigits && base == 10) \ if (use_outdigits && base == 10) \
string = _i18n_number_rewrite (string, workend, workend); \ string = _i18n_number_rewrite (string, workend, workend); \
} \ } \
@ -653,9 +652,8 @@ static const uint8_t jump_table[] =
string = _itoa_word (number.word, workend, base, \ string = _itoa_word (number.word, workend, base, \
spec == L_('X')); \ spec == L_('X')); \
if (group && grouping) \ if (group && grouping) \
string = group_number (string, workend, grouping, \ string = group_number (work_buffer, string, workend, \
thousands_sep); \ grouping, thousands_sep); \
\
if (use_outdigits && base == 10) \ if (use_outdigits && base == 10) \
string = _i18n_number_rewrite (string, workend, workend); \ string = _i18n_number_rewrite (string, workend, workend); \
} \ } \
@ -1237,8 +1235,8 @@ static int printf_unknown (FILE *, const struct printf_info *,
const void *const *) __THROW; const void *const *) __THROW;
/* Group digits of number string. */ /* Group digits of number string. */
static CHAR_T *group_number (CHAR_T *, CHAR_T *, const char *, THOUSANDS_SEP_T) static CHAR_T *group_number (CHAR_T *, CHAR_T *, CHAR_T *, const char *,
__THROW internal_function; THOUSANDS_SEP_T);
/* The function itself. */ /* The function itself. */
int int
@ -2123,16 +2121,20 @@ printf_unknown (FILE *s, const struct printf_info *info,
return done; return done;
} }
/* Group the digits according to the grouping rules of the current locale. /* Group the digits from W to REAR_PTR according to the grouping rules
The interpretation of GROUPING is as in `struct lconv' from <locale.h>. */ of the current locale. The interpretation of GROUPING is as in
`struct lconv' from <locale.h>. The grouped number extends from
the returned pointer until REAR_PTR. FRONT_PTR to W is used as a
scratch area. */
static CHAR_T * static CHAR_T *
internal_function group_number (CHAR_T *front_ptr, CHAR_T *w, CHAR_T *rear_ptr,
group_number (CHAR_T *w, CHAR_T *rear_ptr, const char *grouping, const char *grouping, THOUSANDS_SEP_T thousands_sep)
THOUSANDS_SEP_T thousands_sep)
{ {
/* Length of the current group. */
int len; int len;
CHAR_T *src, *s;
#ifndef COMPILE_WPRINTF #ifndef COMPILE_WPRINTF
/* Length of the separator (in wide mode, the separator is always a
single wide character). */
int tlen = strlen (thousands_sep); int tlen = strlen (thousands_sep);
#endif #endif
@ -2145,26 +2147,34 @@ group_number (CHAR_T *w, CHAR_T *rear_ptr, const char *grouping,
len = *grouping++; len = *grouping++;
/* Copy existing string so that nothing gets overwritten. */ /* Copy existing string so that nothing gets overwritten. */
src = (CHAR_T *) alloca ((rear_ptr - w) * sizeof (CHAR_T)); memmove (front_ptr, w, (rear_ptr - w) * sizeof (CHAR_T));
s = (CHAR_T *) __mempcpy (src, w, CHAR_T *s = front_ptr + (rear_ptr - w);
(rear_ptr - w) * sizeof (CHAR_T));
w = rear_ptr; w = rear_ptr;
/* Process all characters in the string. */ /* Process all characters in the string. */
while (s > src) while (s > front_ptr)
{ {
*--w = *--s; *--w = *--s;
if (--len == 0 && s > src) if (--len == 0 && s > front_ptr)
{ {
/* A new group begins. */ /* A new group begins. */
#ifdef COMPILE_WPRINTF #ifdef COMPILE_WPRINTF
*--w = thousands_sep; if (w != s)
*--w = thousands_sep;
else
/* Not enough room for the separator. */
goto copy_rest;
#else #else
int cnt = tlen; int cnt = tlen;
do if (tlen < w - s)
*--w = thousands_sep[--cnt]; do
while (cnt > 0); *--w = thousands_sep[--cnt];
while (cnt > 0);
else
/* Not enough room for the separator. */
goto copy_rest;
#endif #endif
if (*grouping == CHAR_MAX if (*grouping == CHAR_MAX
@ -2173,17 +2183,16 @@ group_number (CHAR_T *w, CHAR_T *rear_ptr, const char *grouping,
#endif #endif
) )
{ {
/* No further grouping to be done. copy_rest:
Copy the rest of the number. */ /* No further grouping to be done. Copy the rest of the
do number. */
*--w = *--s; memmove (w, s, (front_ptr -s) * sizeof (CHAR_T));
while (s > src);
break; break;
} }
else if (*grouping != '\0') else if (*grouping != '\0')
/* The previous grouping repeats ad infinitum. */
len = *grouping++; len = *grouping++;
else else
/* The previous grouping repeats ad infinitum. */
len = grouping[-1]; len = grouping[-1];
} }
} }