mirror of
https://sourceware.org/git/glibc.git
synced 2025-08-08 17:42:12 +03:00
Update.
2000-01-28 Ulrich Drepper <drepper@cygnus.com> * locale/C-monetary.c: Add initializers for new fields. * locale/C-numeric.c: Likewise. * locale/Makefile (distribute): Add indigits.h, indigitswc.h, outdigits.h, and outdigitswc.h. * locale/langinfo.h: Add _NL_MONETARY_DECIMAL_POINT_WC, _NL_MONETARY_THOUSANDS_SEP_WC, _NL_NUMERIC_DECIMAL_POINT_WC, and _NL_NUMERIC_THOUSANDS_SEP_WC. * locale/indigits.h: New file. * locale/indigitswc.h: New file. * locale/outdigits.h: New file. * locale/outdigitswc.h: New file. * locale/programs/ld-monetary.c: Write out decimal point and thousands separator info in wide character form. * locale/programs/ld-numeric.c: Likewise. * stdio-common/Makefile (routines): Add _i18n_itoa and _i18n_itowa. (distribute): Add _i18n_itoa.h and _i18n_itowa.h. * stdio-common/_i18n_itoa.c: New file. * stdio-common/_i18n_itoa.h: New file. * stdio-common/_i18n_itowa.c: New file. * stdio-common/_i18n_itowa.h: New file. * stdio-common/printf-parse.h: Parse 'I' flag. * stdio-common/printf.h (struct printf_info): Add i18n field. * stdio-common/vfprintf.c: Implement 'I' flag to print using locales' outdigits.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1991-1999, 2000 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <bits/libc-lock.h>
|
||||
#include <sys/param.h>
|
||||
#include "_itoa.h"
|
||||
#include "_i18n_itoa.h"
|
||||
#include <locale/localeinfo.h>
|
||||
|
||||
/* This code is shared between the standard stdio implementation found
|
||||
@@ -80,6 +81,7 @@
|
||||
return -1
|
||||
# else
|
||||
# include "_itowa.h"
|
||||
# include "_i18n_itowa.h"
|
||||
|
||||
# define vfprintf _IO_vfwprintf
|
||||
# define CHAR_T wchar_t
|
||||
@@ -98,6 +100,9 @@
|
||||
|
||||
# define _itoa(Val, Buf, Base, Case) _itowa (Val, Buf, Base, Case)
|
||||
# define _itoa_word(Val, Buf, Base, Case) _itowa_word (Val, Buf, Base, Case)
|
||||
# define _i18n_itoa(Val, Buf, Base, Case) _i18n_itowa (Val, Buf, Base, Case)
|
||||
# define _i18n_itoa_word(Val, Buf, Base, Case) \
|
||||
_i18n_itowa_word (Val, Buf, Base, Case)
|
||||
# undef EOF
|
||||
# define EOF WEOF
|
||||
# endif
|
||||
@@ -213,8 +218,13 @@ static int printf_unknown __P ((FILE *, const struct printf_info *,
|
||||
const void *const *));
|
||||
|
||||
/* Group digits of number string. */
|
||||
#ifdef COMPILE_WPRINTF
|
||||
static CHAR_T *group_number __P ((CHAR_T *, CHAR_T *, const char *, wchar_t))
|
||||
internal_function;
|
||||
#else
|
||||
static CHAR_T *group_number __P ((CHAR_T *, CHAR_T *, const char *,
|
||||
const char *)) internal_function;
|
||||
#endif
|
||||
|
||||
|
||||
/* The function itself. */
|
||||
@@ -222,7 +232,11 @@ int
|
||||
vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
{
|
||||
/* The character used as thousands separator. */
|
||||
#ifdef COMPILE_WPRINTF
|
||||
wchar_t thousands_sep;
|
||||
#else
|
||||
const char *thousands_sep;
|
||||
#endif
|
||||
|
||||
/* The string describing the size of groups of digits. */
|
||||
const char *grouping;
|
||||
@@ -254,6 +268,10 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
/* Count number of specifiers we already processed. */
|
||||
int nspecs_done;
|
||||
|
||||
/* This flag is set by the 'I' modifier and selects the use of the
|
||||
`outdigits' as determined by the current locale. */
|
||||
int use_outdigits;
|
||||
|
||||
/* For the %m format we may need the current `errno' value. */
|
||||
int save_errno = errno;
|
||||
|
||||
@@ -273,7 +291,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
0, 0, 0, 0,
|
||||
0, /* 'A' */ 26, 0, /* 'C' */ 25,
|
||||
0, /* 'E' */ 19, 0, /* 'G' */ 19,
|
||||
0, 0, 0, 0,
|
||||
0, /* 'I' */ 29, 0, 0,
|
||||
/* 'L' */ 12, 0, 0, 0,
|
||||
0, 0, 0, /* 'S' */ 21,
|
||||
0, 0, 0, 0,
|
||||
@@ -321,7 +339,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
|
||||
#define STEP0_3_TABLE \
|
||||
/* Step 0: at the beginning. */ \
|
||||
static JUMP_TABLE_TYPE step0_jumps[29] = \
|
||||
static JUMP_TABLE_TYPE step0_jumps[30] = \
|
||||
{ \
|
||||
REF (form_unknown), \
|
||||
REF (flag_space), /* for ' ' */ \
|
||||
@@ -352,9 +370,10 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
REF (form_floathex), /* for 'A', 'a' */ \
|
||||
REF (mod_ptrdiff_t), /* for 't' */ \
|
||||
REF (mod_intmax_t), /* for 'j' */ \
|
||||
REF (flag_i18n), /* for 'I' */ \
|
||||
}; \
|
||||
/* Step 1: after processing width. */ \
|
||||
static JUMP_TABLE_TYPE step1_jumps[29] = \
|
||||
static JUMP_TABLE_TYPE step1_jumps[30] = \
|
||||
{ \
|
||||
REF (form_unknown), \
|
||||
REF (form_unknown), /* for ' ' */ \
|
||||
@@ -384,10 +403,11 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
REF (form_wcharacter), /* for 'C' */ \
|
||||
REF (form_floathex), /* for 'A', 'a' */ \
|
||||
REF (mod_ptrdiff_t), /* for 't' */ \
|
||||
REF (mod_intmax_t) /* for 'j' */ \
|
||||
REF (mod_intmax_t), /* for 'j' */ \
|
||||
REF (flag_i18n) /* for 'I' */ \
|
||||
}; \
|
||||
/* Step 2: after processing precision. */ \
|
||||
static JUMP_TABLE_TYPE step2_jumps[29] = \
|
||||
static JUMP_TABLE_TYPE step2_jumps[30] = \
|
||||
{ \
|
||||
REF (form_unknown), \
|
||||
REF (form_unknown), /* for ' ' */ \
|
||||
@@ -417,10 +437,11 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
REF (form_wcharacter), /* for 'C' */ \
|
||||
REF (form_floathex), /* for 'A', 'a' */ \
|
||||
REF (mod_ptrdiff_t), /* for 't' */ \
|
||||
REF (mod_intmax_t) /* for 'j' */ \
|
||||
REF (mod_intmax_t), /* for 'j' */ \
|
||||
REF (flag_i18n) /* for 'I' */ \
|
||||
}; \
|
||||
/* Step 3a: after processing first 'h' modifier. */ \
|
||||
static JUMP_TABLE_TYPE step3a_jumps[29] = \
|
||||
static JUMP_TABLE_TYPE step3a_jumps[30] = \
|
||||
{ \
|
||||
REF (form_unknown), \
|
||||
REF (form_unknown), /* for ' ' */ \
|
||||
@@ -450,10 +471,11 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
REF (form_unknown), /* for 'C' */ \
|
||||
REF (form_unknown), /* for 'A', 'a' */ \
|
||||
REF (form_unknown), /* for 't' */ \
|
||||
REF (form_unknown) /* for 'j' */ \
|
||||
REF (form_unknown), /* for 'j' */ \
|
||||
REF (form_unknown) /* for 'I' */ \
|
||||
}; \
|
||||
/* Step 3b: after processing first 'l' modifier. */ \
|
||||
static JUMP_TABLE_TYPE step3b_jumps[29] = \
|
||||
static JUMP_TABLE_TYPE step3b_jumps[30] = \
|
||||
{ \
|
||||
REF (form_unknown), \
|
||||
REF (form_unknown), /* for ' ' */ \
|
||||
@@ -483,12 +505,13 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
REF (form_wcharacter), /* for 'C' */ \
|
||||
REF (form_floathex), /* for 'A', 'a' */ \
|
||||
REF (form_unknown), /* for 't' */ \
|
||||
REF (form_unknown) /* for 'j' */ \
|
||||
REF (form_unknown), /* for 'j' */ \
|
||||
REF (form_unknown) /* for 'I' */ \
|
||||
}
|
||||
|
||||
#define STEP4_TABLE \
|
||||
/* Step 4: processing format specifier. */ \
|
||||
static JUMP_TABLE_TYPE step4_jumps[29] = \
|
||||
static JUMP_TABLE_TYPE step4_jumps[30] = \
|
||||
{ \
|
||||
REF (form_unknown), \
|
||||
REF (form_unknown), /* for ' ' */ \
|
||||
@@ -518,7 +541,8 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
REF (form_wcharacter), /* for 'C' */ \
|
||||
REF (form_floathex), /* for 'A', 'a' */ \
|
||||
REF (form_unknown), /* for 't' */ \
|
||||
REF (form_unknown) /* for 'j' */ \
|
||||
REF (form_unknown), /* for 'j' */ \
|
||||
REF (form_unknown) /* for 'I' */ \
|
||||
}
|
||||
|
||||
|
||||
@@ -624,8 +648,11 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
else \
|
||||
{ \
|
||||
/* Put the number in WORK. */ \
|
||||
string = _itoa (number.longlong, workend + 1, base, \
|
||||
spec == L_('X')); \
|
||||
if (use_outdigits && base == 10) \
|
||||
string = _i18n_itoa (number.longlong, workend + 1); \
|
||||
else \
|
||||
string = _itoa (number.longlong, workend + 1, base, \
|
||||
spec == L_('X')); \
|
||||
string -= 1; \
|
||||
if (group && grouping) \
|
||||
string = group_number (string, workend, grouping, \
|
||||
@@ -678,8 +705,11 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
else \
|
||||
{ \
|
||||
/* Put the number in WORK. */ \
|
||||
string = _itoa_word (number.word, workend + 1, base, \
|
||||
spec == L_('X')); \
|
||||
if (use_outdigits && base == 10) \
|
||||
string = _i18n_itoa_word (number.word, workend + 1); \
|
||||
else \
|
||||
string = _itoa_word (number.word, workend + 1, base, \
|
||||
spec == L_('X')); \
|
||||
string -= 1; \
|
||||
if (group && grouping) \
|
||||
string = group_number (string, workend, grouping, \
|
||||
@@ -1302,26 +1332,31 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
|
||||
LABEL (flag_quote):
|
||||
group = 1;
|
||||
|
||||
/* XXX Completely wrong. Use wctob. */
|
||||
if (grouping == (const char *) -1)
|
||||
{
|
||||
mbstate_t mbstate;
|
||||
#ifdef COMPILE_WPRINTF
|
||||
thousands_sep = _NL_CURRENT_WORD (LC_NUMERIC,
|
||||
_NL_NUMERIC_THOUSANDS_SEP_WC);
|
||||
#else
|
||||
thousands_sep = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
|
||||
#endif
|
||||
|
||||
/* Figure out the thousands separator character. */
|
||||
memset (&mbstate, '\0', sizeof (mbstate));
|
||||
if (__mbrtowc (&thousands_sep,
|
||||
_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP),
|
||||
strlen (_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP)),
|
||||
&mbstate) <= 0)
|
||||
thousands_sep = (wchar_t)
|
||||
*_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
|
||||
grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
|
||||
if (*grouping == '\0' || *grouping == CHAR_MAX
|
||||
|| thousands_sep == L'\0')
|
||||
#ifdef COMPILE_WPRINTF
|
||||
|| thousands_sep == L'\0'
|
||||
#else
|
||||
|| *thousands_sep == '\0'
|
||||
#endif
|
||||
)
|
||||
grouping = NULL;
|
||||
}
|
||||
JUMP (*++f, step0_jumps);
|
||||
|
||||
LABEL (flag_i18n):
|
||||
use_outdigits = 1;
|
||||
break;
|
||||
|
||||
/* Get width from argument. */
|
||||
LABEL (width_asterics):
|
||||
{
|
||||
@@ -1492,18 +1527,15 @@ do_positional:
|
||||
|
||||
if (grouping == (const char *) -1)
|
||||
{
|
||||
mbstate_t mbstate;
|
||||
#ifdef COMPILE_WPRINTF
|
||||
thousands_sep = _NL_CURRENT_WORD (LC_NUMERIC,
|
||||
_NL_NUMERIC_THOUSANDS_SEP_WC);
|
||||
#else
|
||||
thousands_sep = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
|
||||
#endif
|
||||
|
||||
/* Figure out the thousands separator character. */
|
||||
memset (&mbstate, '\0', sizeof (mbstate));
|
||||
if (__mbrtowc (&thousands_sep,
|
||||
_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP),
|
||||
strlen (_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP)),
|
||||
&mbstate) <= 0)
|
||||
thousands_sep = (wchar_t) *_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
|
||||
grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
|
||||
if (*grouping == '\0' || *grouping == CHAR_MAX
|
||||
|| thousands_sep == L'\0')
|
||||
if (*grouping == '\0' || *grouping == CHAR_MAX)
|
||||
grouping = NULL;
|
||||
}
|
||||
|
||||
@@ -1781,6 +1813,8 @@ printf_unknown (FILE *s, const struct printf_info *info,
|
||||
outchar (L_('-'));
|
||||
if (info->pad == L_('0'))
|
||||
outchar (L_('0'));
|
||||
if (info->i18n)
|
||||
outchar (L_('I'));
|
||||
|
||||
if (info->width != 0)
|
||||
{
|
||||
@@ -1809,10 +1843,18 @@ printf_unknown (FILE *s, const struct printf_info *info,
|
||||
static CHAR_T *
|
||||
internal_function
|
||||
group_number (CHAR_T *w, CHAR_T *rear_ptr, const char *grouping,
|
||||
wchar_t thousands_sep)
|
||||
#ifdef COMPILE_WPRINTF
|
||||
wchar_t thousands_sep
|
||||
#else
|
||||
const char *thousands_sep
|
||||
#endif
|
||||
)
|
||||
{
|
||||
int len;
|
||||
CHAR_T *src, *s;
|
||||
#ifndef COMPILE_WPRINTF
|
||||
int tlen = strlen (thousands_sep);
|
||||
#endif
|
||||
|
||||
/* We treat all negative values like CHAR_MAX. */
|
||||
|
||||
@@ -1836,7 +1878,14 @@ group_number (CHAR_T *w, CHAR_T *rear_ptr, const char *grouping,
|
||||
if (--len == 0 && s >= src)
|
||||
{
|
||||
/* A new group begins. */
|
||||
#ifdef COMPILE_WPRINTF
|
||||
*w-- = thousands_sep;
|
||||
#else
|
||||
int cnt = tlen;
|
||||
do
|
||||
*w-- = thousands_sep[--cnt];
|
||||
while (cnt > 0);
|
||||
#endif
|
||||
|
||||
len = *grouping++;
|
||||
if (*grouping == '\0')
|
||||
|
Reference in New Issue
Block a user