1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-08-08 17:42:12 +03:00
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:
Ulrich Drepper
2000-01-29 02:54:27 +00:00
parent 8217ddf5c6
commit 4295702fe3
17 changed files with 1103 additions and 61 deletions

View File

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