mirror of https://gitee.com/Nocallback/glibc.git
Browse Source
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.cvs/glibc-2-2-branch
17 changed files with 1105 additions and 63 deletions
@ -0,0 +1,98 @@ |
|||
/* Copyright (C) 2000 Free Software Foundation, Inc.
|
|||
This file is part of the GNU C Library. |
|||
Contributed by Ulrich Drepper <drepper@gnu.org>, 2000. |
|||
|
|||
The GNU C Library is free software; you can redistribute it and/or |
|||
modify it under the terms of the GNU Library General Public License as |
|||
published by the Free Software Foundation; either version 2 of the |
|||
License, or (at your option) any later version. |
|||
|
|||
The GNU C Library is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
Library General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Library General Public |
|||
License along with the GNU C Library; see the file COPYING.LIB. If not, |
|||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
|||
Boston, MA 02111-1307, USA. */ |
|||
|
|||
#include <assert.h> |
|||
#include <langinfo.h> |
|||
#include <string.h> |
|||
|
|||
/* Look up the value of the next multibyte character and return its numerical
|
|||
value if it is one of the digits known in the locale. If *DECIDED is |
|||
-1 this means it is not yet decided which form it is and we have to |
|||
search through all available digits. Otherwise we know which script |
|||
the digits are from. */ |
|||
static inline int |
|||
indigit_value (const char **s, size_t *len, int *decided) |
|||
{ |
|||
int from_level; |
|||
int to_level; |
|||
const char *mbdigits[10]; |
|||
int n; |
|||
|
|||
if (*decided != -1) |
|||
from_level = to_level = *decided; |
|||
else |
|||
{ |
|||
from_level = 0; |
|||
to_level = _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_INDIGITS_MB_LEN) - 1; |
|||
assert (from_level <= to_level); |
|||
} |
|||
|
|||
/* In this round we get the pointer to the digit strings and also perform
|
|||
the first round of comparisons. */ |
|||
for (n = 0; n < 10; ++n) |
|||
{ |
|||
size_t dlen; |
|||
|
|||
/* Get the string for the digits with value N. */ |
|||
mbdigits[n] = _NL_CURRENT (LC_CTYPE, _NL_CTYPE_INDIGITS0_MB + n); |
|||
dlen = strlen (mbdigits[n]); |
|||
|
|||
if (dlen <= len && memcmp (*s, mbdigits[n], dlen) == 0) |
|||
{ |
|||
/* Found it. */ |
|||
*s += dlen; |
|||
len -= dlen; |
|||
if (*decided == -1) |
|||
*decided = 0; |
|||
return n; |
|||
} |
|||
|
|||
/* Advance the pointer to the next string. */ |
|||
mbdigits[n] += dlen + 1; |
|||
} |
|||
|
|||
/* Now perform the remaining tests. */ |
|||
while (++from_level <= to_level) |
|||
{ |
|||
/* Search all ten digits of this level. */ |
|||
for (n = 0; n < 10; ++n) |
|||
{ |
|||
size_t dlen = strlen (mbdigits[n]); |
|||
|
|||
if (dlen <= len && memcmp (*s, mbdigits[n], dlen) == 0) |
|||
{ |
|||
/* Found it. */ |
|||
*s += dlen; |
|||
len -= dlen; |
|||
if (*decided == -1) |
|||
*decided = from_level; |
|||
return n; |
|||
} |
|||
|
|||
/* Advance the pointer to the next string. */ |
|||
mbdigits[n] += dlen + 1; |
|||
} |
|||
|
|||
/* Next level. */ |
|||
++from_level; |
|||
} |
|||
|
|||
/* If we reach this point no matching digit was found. */ |
|||
return -1; |
|||
} |
|||
@ -0,0 +1,88 @@ |
|||
/* Copyright (C) 2000 Free Software Foundation, Inc.
|
|||
This file is part of the GNU C Library. |
|||
Contributed by Ulrich Drepper <drepper@gnu.org>, 2000. |
|||
|
|||
The GNU C Library is free software; you can redistribute it and/or |
|||
modify it under the terms of the GNU Library General Public License as |
|||
published by the Free Software Foundation; either version 2 of the |
|||
License, or (at your option) any later version. |
|||
|
|||
The GNU C Library is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
Library General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Library General Public |
|||
License along with the GNU C Library; see the file COPYING.LIB. If not, |
|||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
|||
Boston, MA 02111-1307, USA. */ |
|||
|
|||
#include <assert.h> |
|||
#include <langinfo.h> |
|||
|
|||
/* Look up the value of the next multibyte character and return its numerical
|
|||
value if it is one of the digits known in the locale. If *DECIDED is |
|||
-1 this means it is not yet decided which form it is and we have to |
|||
search through all available digits. Otherwise we know which script |
|||
the digits are from. */ |
|||
static inline int |
|||
indigitwc_value (wchar_t wc, int *decided) |
|||
{ |
|||
int from_level; |
|||
int to_level; |
|||
const wchar_t *wcdigits[10]; |
|||
int n; |
|||
|
|||
if (*decided != -1) |
|||
from_level = to_level = *decided; |
|||
else |
|||
{ |
|||
from_level = 0; |
|||
to_level = _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_INDIGITS_WC_LEN) - 1; |
|||
assert (from_level <= to_level); |
|||
} |
|||
|
|||
/* In this round we get the pointer to the digit strings and also perform
|
|||
the first round of comparisons. */ |
|||
for (n = 0; n < 10; ++n) |
|||
{ |
|||
/* Get the string for the digits with value N. */ |
|||
wcdigits[n] = _NL_CURRENT (LC_CTYPE, _NL_CTYPE_INDIGITS0_WC + n); |
|||
|
|||
if (wc == wcdigits[n]) |
|||
{ |
|||
/* Found it. */ |
|||
if (*decided == -1) |
|||
*decided = 0; |
|||
return n; |
|||
} |
|||
|
|||
/* Advance the pointer to the next string. */ |
|||
++wcdigits[n]; |
|||
} |
|||
|
|||
/* Now perform the remaining tests. */ |
|||
while (++from_level <= to_level) |
|||
{ |
|||
/* Search all ten digits of this level. */ |
|||
for (n = 0; n < 10; ++n) |
|||
{ |
|||
if (wc == wcdigits[n]) |
|||
{ |
|||
/* Found it. */ |
|||
if (*decided == -1) |
|||
*decided = from_level; |
|||
return n; |
|||
} |
|||
|
|||
/* Advance the pointer to the next string. */ |
|||
++wcdigits[n]; |
|||
} |
|||
|
|||
/* Next level. */ |
|||
++from_level; |
|||
} |
|||
|
|||
/* If we reach this point no matching digit was found. */ |
|||
return -1; |
|||
} |
|||
@ -0,0 +1,45 @@ |
|||
/* Copyright (C) 2000 Free Software Foundation, Inc.
|
|||
This file is part of the GNU C Library. |
|||
Contributed by Ulrich Drepper <drepper@gnu.org>, 2000. |
|||
|
|||
The GNU C Library is free software; you can redistribute it and/or |
|||
modify it under the terms of the GNU Library General Public License as |
|||
published by the Free Software Foundation; either version 2 of the |
|||
License, or (at your option) any later version. |
|||
|
|||
The GNU C Library is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
Library General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Library General Public |
|||
License along with the GNU C Library; see the file COPYING.LIB. If not, |
|||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
|||
Boston, MA 02111-1307, USA. */ |
|||
|
|||
#include <assert.h> |
|||
#include <langinfo.h> |
|||
#include <string.h> |
|||
#include "../locale/localeinfo.h" |
|||
|
|||
/* Look up the value of the next multibyte character and return its numerical
|
|||
value if it is one of the digits known in the locale. If *DECIDED is |
|||
-1 this means it is not yet decided which form it is and we have to |
|||
search through all available digits. Otherwise we know which script |
|||
the digits are from. */ |
|||
static inline char * |
|||
outdigit_value (char *s, int n) |
|||
{ |
|||
const char *outdigit; |
|||
size_t dlen; |
|||
|
|||
assert (0 <= n && n <= 9); |
|||
outdigit = _NL_CURRENT (LC_CTYPE, _NL_CTYPE_OUTDIGIT0_MB + n); |
|||
dlen = strlen (outdigit); |
|||
|
|||
s -= dlen; |
|||
while (dlen-- > 0) |
|||
s[dlen] = outdigit[dlen]; |
|||
|
|||
return s; |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
/* Copyright (C) 2000 Free Software Foundation, Inc.
|
|||
This file is part of the GNU C Library. |
|||
Contributed by Ulrich Drepper <drepper@gnu.org>, 2000. |
|||
|
|||
The GNU C Library is free software; you can redistribute it and/or |
|||
modify it under the terms of the GNU Library General Public License as |
|||
published by the Free Software Foundation; either version 2 of the |
|||
License, or (at your option) any later version. |
|||
|
|||
The GNU C Library is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
Library General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Library General Public |
|||
License along with the GNU C Library; see the file COPYING.LIB. If not, |
|||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
|||
Boston, MA 02111-1307, USA. */ |
|||
|
|||
#include <assert.h> |
|||
#include <langinfo.h> |
|||
#include "../locale/localeinfo.h" |
|||
|
|||
/* Look up the value of the next multibyte character and return its numerical
|
|||
value if it is one of the digits known in the locale. If *DECIDED is |
|||
-1 this means it is not yet decided which form it is and we have to |
|||
search through all available digits. Otherwise we know which script |
|||
the digits are from. */ |
|||
static inline wchar_t |
|||
outdigitwc_value (int n) |
|||
{ |
|||
assert (0 <= n && n <= 9); |
|||
|
|||
return _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_OUTDIGIT0_WC + n); |
|||
} |
|||
@ -0,0 +1,266 @@ |
|||
/* Internal function for converting integers to string using locale
|
|||
specific digits. |
|||
Copyright (C) 2000 Free Software Foundation, Inc. |
|||
This file is part of the GNU C Library. |
|||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000. |
|||
|
|||
The GNU C Library is free software; you can redistribute it and/or |
|||
modify it under the terms of the GNU Library General Public License as |
|||
published by the Free Software Foundation; either version 2 of the |
|||
License, or (at your option) any later version. |
|||
|
|||
The GNU C Library is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
Library General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Library General Public |
|||
License along with the GNU C Library; see the file COPYING.LIB. If not, |
|||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
|||
Boston, MA 02111-1307, USA. */ |
|||
|
|||
#include <gmp-mparam.h> |
|||
#include <stdlib/gmp.h> |
|||
#include <stdlib/gmp-impl.h> |
|||
#include <stdlib/longlong.h> |
|||
|
|||
#include "_i18n_itoa.h" |
|||
|
|||
|
|||
/* Canonize environment. For some architectures not all values might
|
|||
be defined in the GMP header files. */ |
|||
#ifndef UMUL_TIME |
|||
# define UMUL_TIME 1 |
|||
#endif |
|||
#ifndef UDIV_TIME |
|||
# define UDIV_TIME 3 |
|||
#endif |
|||
|
|||
/* Control memory layout. */ |
|||
#ifdef PACK |
|||
# undef PACK |
|||
# define PACK __attribute__ ((packed)) |
|||
#else |
|||
# define PACK |
|||
#endif |
|||
|
|||
|
|||
/* Declare local types. */ |
|||
struct base_table_t |
|||
{ |
|||
#if (UDIV_TIME > 2 * UMUL_TIME) |
|||
mp_limb_t base_multiplier; |
|||
#endif |
|||
char flag; |
|||
char post_shift; |
|||
#if BITS_PER_MP_LIMB == 32 |
|||
struct |
|||
{ |
|||
char normalization_steps; |
|||
char ndigits; |
|||
mp_limb_t base PACK; |
|||
#if UDIV_TIME > 2 * UMUL_TIME |
|||
mp_limb_t base_ninv PACK; |
|||
#endif |
|||
} big; |
|||
#endif |
|||
}; |
|||
|
|||
|
|||
/* Variable in other file. */ |
|||
extern const struct base_table_t _itoa_base_table[]; |
|||
|
|||
|
|||
char * |
|||
_i18n_itoa (value, buflim) |
|||
unsigned long long int value; |
|||
char *buflim; |
|||
{ |
|||
const struct base_table_t *brec = &_itoa_base_table[8]; |
|||
|
|||
#if BITS_PER_MP_LIMB == 64 |
|||
mp_limb_t base_multiplier = brec->base_multiplier; |
|||
if (brec->flag) while (value != 0) |
|||
{ |
|||
mp_limb_t quo, rem, x, dummy; |
|||
|
|||
umul_ppmm (x, dummy, value, base_multiplier); |
|||
quo = (x + ((value - x) >> 1)) >> (brec->post_shift - 1); |
|||
rem = value - quo * 10; |
|||
buflim = outdigit_value (buflim, rem); |
|||
value = quo; |
|||
} |
|||
else |
|||
while (value != 0) |
|||
{ |
|||
mp_limb_t quo, rem, x, dummy; |
|||
|
|||
umul_ppmm (x, dummy, value, base_multiplier); |
|||
quo = x >> brec->post_shift; |
|||
rem = value - quo * 10; |
|||
buflim = outdigit_value (buflim, rem); |
|||
value = quo; |
|||
} |
|||
#endif |
|||
#if BITS_PER_MP_LIMB == 32 |
|||
mp_limb_t t[3]; |
|||
int n; |
|||
|
|||
/* First convert x0 to 1-3 words in base s->big.base.
|
|||
Optimize for frequent cases of 32 bit numbers. */ |
|||
if ((mp_limb_t) (value >> 32) >= 1) |
|||
{ |
|||
#if UDIV_TIME > 2 * UMUL_TIME || UDIV_NEEDS_NORMALIZATION |
|||
int big_normalization_steps = brec->big.normalization_steps; |
|||
mp_limb_t big_base_norm |
|||
= brec->big.base << big_normalization_steps; |
|||
#endif |
|||
if ((mp_limb_t) (value >> 32) >= brec->big.base) |
|||
{ |
|||
mp_limb_t x1hi, x1lo, r; |
|||
/* If you want to optimize this, take advantage of
|
|||
that the quotient in the first udiv_qrnnd will |
|||
always be very small. It might be faster just to |
|||
subtract in a tight loop. */ |
|||
|
|||
#if UDIV_TIME > 2 * UMUL_TIME |
|||
mp_limb_t x, xh, xl; |
|||
|
|||
if (big_normalization_steps == 0) |
|||
xh = 0; |
|||
else |
|||
xh = (mp_limb_t) (value >> (64 - big_normalization_steps)); |
|||
xl = (mp_limb_t) (value >> (32 - big_normalization_steps)); |
|||
udiv_qrnnd_preinv (x1hi, r, xh, xl, big_base_norm, |
|||
brec->big.base_ninv); |
|||
|
|||
xl = ((mp_limb_t) value) << big_normalization_steps; |
|||
udiv_qrnnd_preinv (x1lo, x, r, xl, big_base_norm, |
|||
brec->big.base_ninv); |
|||
t[2] = x >> big_normalization_steps; |
|||
|
|||
if (big_normalization_steps == 0) |
|||
xh = x1hi; |
|||
else |
|||
xh = ((x1hi << big_normalization_steps) |
|||
| (x1lo >> (32 - big_normalization_steps))); |
|||
xl = x1lo << big_normalization_steps; |
|||
udiv_qrnnd_preinv (t[0], x, xh, xl, big_base_norm, |
|||
brec->big.base_ninv); |
|||
t[1] = x >> big_normalization_steps; |
|||
#elif UDIV_NEEDS_NORMALIZATION |
|||
mp_limb_t x, xh, xl; |
|||
|
|||
if (big_normalization_steps == 0) |
|||
xh = 0; |
|||
else |
|||
xh = (mp_limb_t) (value >> 64 - big_normalization_steps); |
|||
xl = (mp_limb_t) (value >> 32 - big_normalization_steps); |
|||
udiv_qrnnd (x1hi, r, xh, xl, big_base_norm); |
|||
|
|||
xl = ((mp_limb_t) value) << big_normalization_steps; |
|||
udiv_qrnnd (x1lo, x, r, xl, big_base_norm); |
|||
t[2] = x >> big_normalization_steps; |
|||
|
|||
if (big_normalization_steps == 0) |
|||
xh = x1hi; |
|||
else |
|||
xh = ((x1hi << big_normalization_steps) |
|||
| (x1lo >> 32 - big_normalization_steps)); |
|||
xl = x1lo << big_normalization_steps; |
|||
udiv_qrnnd (t[0], x, xh, xl, big_base_norm); |
|||
t[1] = x >> big_normalization_steps; |
|||
#else |
|||
udiv_qrnnd (x1hi, r, 0, (mp_limb_t) (value >> 32), |
|||
brec->big.base); |
|||
udiv_qrnnd (x1lo, t[2], r, (mp_limb_t) value, brec->big.base); |
|||
udiv_qrnnd (t[0], t[1], x1hi, x1lo, brec->big.base); |
|||
#endif |
|||
n = 3; |
|||
} |
|||
else |
|||
{ |
|||
#if (UDIV_TIME > 2 * UMUL_TIME) |
|||
mp_limb_t x; |
|||
|
|||
value <<= brec->big.normalization_steps; |
|||
udiv_qrnnd_preinv (t[0], x, (mp_limb_t) (value >> 32), |
|||
(mp_limb_t) value, big_base_norm, |
|||
brec->big.base_ninv); |
|||
t[1] = x >> brec->big.normalization_steps; |
|||
#elif UDIV_NEEDS_NORMALIZATION |
|||
mp_limb_t x; |
|||
|
|||
value <<= big_normalization_steps; |
|||
udiv_qrnnd (t[0], x, (mp_limb_t) (value >> 32), |
|||
(mp_limb_t) value, big_base_norm); |
|||
t[1] = x >> big_normalization_steps; |
|||
#else |
|||
udiv_qrnnd (t[0], t[1], (mp_limb_t) (value >> 32), |
|||
(mp_limb_t) value, brec->big.base); |
|||
#endif |
|||
n = 2; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
t[0] = value; |
|||
n = 1; |
|||
} |
|||
|
|||
/* Convert the 1-3 words in t[], word by word, to ASCII. */ |
|||
do |
|||
{ |
|||
mp_limb_t ti = t[--n]; |
|||
int ndig_for_this_limb = 0; |
|||
|
|||
#if UDIV_TIME > 2 * UMUL_TIME |
|||
mp_limb_t base_multiplier = brec->base_multiplier; |
|||
if (brec->flag) |
|||
while (ti != 0) |
|||
{ |
|||
mp_limb_t quo, rem, x, dummy; |
|||
|
|||
umul_ppmm (x, dummy, ti, base_multiplier); |
|||
quo = (x + ((ti - x) >> 1)) >> (brec->post_shift - 1); |
|||
rem = ti - quo * 10; |
|||
buflim = outdigit_value (buflim, rem); |
|||
ti = quo; |
|||
++ndig_for_this_limb; |
|||
} else |
|||
while (ti != 0) |
|||
{ |
|||
mp_limb_t quo, rem, x, dummy; |
|||
|
|||
umul_ppmm (x, dummy, ti, base_multiplier); |
|||
quo = x >> brec->post_shift; |
|||
rem = ti - quo * 10; |
|||
buflim = outdigit_value (buflim, rem); |
|||
ti = quo; |
|||
++ndig_for_this_limb; |
|||
} |
|||
#else |
|||
while (ti != 0) |
|||
{ |
|||
mp_limb_t quo, rem; |
|||
|
|||
quo = ti / 10; |
|||
rem = ti % 10; |
|||
buflim = outdigit_value (buflim, rem); |
|||
ti = quo; |
|||
++ndig_for_this_limb; |
|||
} |
|||
#endif |
|||
/* If this wasn't the most significant word, pad with zeros. */ |
|||
if (n != 0) |
|||
while (ndig_for_this_limb < brec->big.ndigits) |
|||
{ |
|||
*--buflim = '0'; |
|||
++ndig_for_this_limb; |
|||
} |
|||
} |
|||
while (n != 0); |
|||
#endif |
|||
|
|||
return buflim; |
|||
} |
|||
@ -0,0 +1,41 @@ |
|||
/* Internal function for converting integers to string using locale
|
|||
specific digits. |
|||
Copyright (C) 2000 Free Software Foundation, Inc. |
|||
This file is part of the GNU C Library. |
|||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000. |
|||
|
|||
The GNU C Library is free software; you can redistribute it and/or |
|||
modify it under the terms of the GNU Library General Public License as |
|||
published by the Free Software Foundation; either version 2 of the |
|||
License, or (at your option) any later version. |
|||
|
|||
The GNU C Library is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
Library General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Library General Public |
|||
License along with the GNU C Library; see the file COPYING.LIB. If not, |
|||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
|||
Boston, MA 02111-1307, USA. */ |
|||
|
|||
#ifndef _I18N_ITOA_H |
|||
#define _I18N_ITOA_H |
|||
#include <sys/cdefs.h> |
|||
|
|||
#include "../locale/outdigits.h" |
|||
|
|||
|
|||
extern char *_i18n_itoa (unsigned long long int value, char *buflim); |
|||
|
|||
static inline char * |
|||
_i18n_itoa_word (unsigned long int value, char *buflim) |
|||
{ |
|||
do |
|||
buflim = outdigit_value (buflim, value % 10); |
|||
while ((value /= 10) != 0); \ |
|||
|
|||
return buflim; |
|||
} |
|||
|
|||
#endif /* _i18n_itoa.h */ |
|||
@ -0,0 +1,267 @@ |
|||
/* Internal function for converting integers to string using locale
|
|||
specific digits. |
|||
Copyright (C) 2000 Free Software Foundation, Inc. |
|||
This file is part of the GNU C Library. |
|||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000. |
|||
|
|||
The GNU C Library is free software; you can redistribute it and/or |
|||
modify it under the terms of the GNU Library General Public License as |
|||
published by the Free Software Foundation; either version 2 of the |
|||
License, or (at your option) any later version. |
|||
|
|||
The GNU C Library is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
Library General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Library General Public |
|||
License along with the GNU C Library; see the file COPYING.LIB. If not, |
|||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
|||
Boston, MA 02111-1307, USA. */ |
|||
|
|||
#include <gmp-mparam.h> |
|||
#include <stdlib/gmp.h> |
|||
#include <stdlib/gmp-impl.h> |
|||
#include <stdlib/longlong.h> |
|||
|
|||
#include "_i18n_itowa.h" |
|||
|
|||
|
|||
/* Canonize environment. For some architectures not all values might
|
|||
be defined in the GMP header files. */ |
|||
#ifndef UMUL_TIME |
|||
# define UMUL_TIME 1 |
|||
#endif |
|||
#ifndef UDIV_TIME |
|||
# define UDIV_TIME 3 |
|||
#endif |
|||
|
|||
/* Control memory layout. */ |
|||
#ifdef PACK |
|||
# undef PACK |
|||
# define PACK __attribute__ ((packed)) |
|||
#else |
|||
# define PACK |
|||
#endif |
|||
|
|||
|
|||
/* Declare local types. */ |
|||
struct base_table_t |
|||
{ |
|||
#if (UDIV_TIME > 2 * UMUL_TIME) |
|||
mp_limb_t base_multiplier; |
|||
#endif |
|||
char flag; |
|||
char post_shift; |
|||
#if BITS_PER_MP_LIMB == 32 |
|||
struct |
|||
{ |
|||
char normalization_steps; |
|||
char ndigits; |
|||
mp_limb_t base PACK; |
|||
#if UDIV_TIME > 2 * UMUL_TIME |
|||
mp_limb_t base_ninv PACK; |
|||
#endif |
|||
} big; |
|||
#endif |
|||
}; |
|||
|
|||
|
|||
/* Variable in other file. */ |
|||
extern const struct base_table_t _itoa_base_table[]; |
|||
|
|||
|
|||
wchar_t * |
|||
_i18n_itowa (value, buflim) |
|||
unsigned long long int value; |
|||
wchar_t *buflim; |
|||
{ |
|||
const struct base_table_t *brec = &_itoa_base_table[8]; |
|||
|
|||
#if BITS_PER_MP_LIMB == 64 |
|||
mp_limb_t base_multiplier = brec->base_multiplier; |
|||
if (brec->flag) while (value != 0) |
|||
{ |
|||
mp_limb_t quo, rem, x, dummy; |
|||
|
|||
umul_ppmm (x, dummy, value, base_multiplier); |
|||
quo = (x + ((value - x) >> 1)) >> (brec->post_shift - 1); |
|||
rem = value - quo * 10; |
|||
*--buflim = outdigitwc_value (rem); |
|||
value = quo; |
|||
} |
|||
else |
|||
while (value != 0) |
|||
{ |
|||
mp_limb_t quo, rem, x, dummy; |
|||
|
|||
umul_ppmm (x, dummy, value, base_multiplier); |
|||
quo = x >> brec->post_shift; |
|||
rem = value - quo * 10; |
|||
*--buflim = outdigitwc_value (rem); |
|||
value = quo; |
|||
} |
|||
#endif |
|||
#if BITS_PER_MP_LIMB == 32 |
|||
mp_limb_t t[3]; |
|||
int n; |
|||
|
|||
/* First convert x0 to 1-3 words in base s->big.base.
|
|||
Optimize for frequent cases of 32 bit numbers. */ |
|||
if ((mp_limb_t) (value >> 32) >= 1) |
|||
{ |
|||
#if UDIV_TIME > 2 * UMUL_TIME || UDIV_NEEDS_NORMALIZATION |
|||
int big_normalization_steps = brec->big.normalization_steps; |
|||
mp_limb_t big_base_norm |
|||
= brec->big.base << big_normalization_steps; |
|||
#endif |
|||
if ((mp_limb_t) (value >> 32) >= brec->big.base) |
|||
{ |
|||
mp_limb_t x1hi, x1lo, r; |
|||
/* If you want to optimize this, take advantage of
|
|||
that the quotient in the first udiv_qrnnd will |
|||
always be very small. It might be faster just to |
|||
subtract in a tight loop. */ |
|||
|
|||
#if UDIV_TIME > 2 * UMUL_TIME |
|||
mp_limb_t x, xh, xl; |
|||
|
|||
if (big_normalization_steps == 0) |
|||
xh = 0; |
|||
else |
|||
xh = (mp_limb_t) (value >> (64 - big_normalization_steps)); |
|||
xl = (mp_limb_t) (value >> (32 - big_normalization_steps)); |
|||
udiv_qrnnd_preinv (x1hi, r, xh, xl, big_base_norm, |
|||
brec->big.base_ninv); |
|||
|
|||
xl = ((mp_limb_t) value) << big_normalization_steps; |
|||
udiv_qrnnd_preinv (x1lo, x, r, xl, big_base_norm, |
|||
brec->big.base_ninv); |
|||
t[2] = x >> big_normalization_steps; |
|||
|
|||
if (big_normalization_steps == 0) |
|||
xh = x1hi; |
|||
else |
|||
xh = ((x1hi << big_normalization_steps) |
|||
| (x1lo >> (32 - big_normalization_steps))); |
|||
xl = x1lo << big_normalization_steps; |
|||
udiv_qrnnd_preinv (t[0], x, xh, xl, big_base_norm, |
|||
brec->big.base_ninv); |
|||
t[1] = x >> big_normalization_steps; |
|||
#elif UDIV_NEEDS_NORMALIZATION |
|||
mp_limb_t x, xh, xl; |
|||
|
|||
if (big_normalization_steps == 0) |
|||
xh = 0; |
|||
else |
|||
xh = (mp_limb_t) (value >> 64 - big_normalization_steps); |
|||
xl = (mp_limb_t) (value >> 32 - big_normalization_steps); |
|||
udiv_qrnnd (x1hi, r, xh, xl, big_base_norm); |
|||
|
|||
xl = ((mp_limb_t) value) << big_normalization_steps; |
|||
udiv_qrnnd (x1lo, x, r, xl, big_base_norm); |
|||
t[2] = x >> big_normalization_steps; |
|||
|
|||
if (big_normalization_steps == 0) |
|||
xh = x1hi; |
|||
else |
|||
xh = ((x1hi << big_normalization_steps) |
|||
| (x1lo >> 32 - big_normalization_steps)); |
|||
xl = x1lo << big_normalization_steps; |
|||
udiv_qrnnd (t[0], x, xh, xl, big_base_norm); |
|||
t[1] = x >> big_normalization_steps; |
|||
#else |
|||
udiv_qrnnd (x1hi, r, 0, (mp_limb_t) (value >> 32), |
|||
brec->big.base); |
|||
udiv_qrnnd (x1lo, t[2], r, (mp_limb_t) value, brec->big.base); |
|||
udiv_qrnnd (t[0], t[1], x1hi, x1lo, brec->big.base); |
|||
#endif |
|||
n = 3; |
|||
} |
|||
else |
|||
{ |
|||
#if (UDIV_TIME > 2 * UMUL_TIME) |
|||
mp_limb_t x; |
|||
|
|||
value <<= brec->big.normalization_steps; |
|||
udiv_qrnnd_preinv (t[0], x, (mp_limb_t) (value >> 32), |
|||
(mp_limb_t) value, big_base_norm, |
|||
brec->big.base_ninv); |
|||
t[1] = x >> brec->big.normalization_steps; |
|||
#elif UDIV_NEEDS_NORMALIZATION |
|||
mp_limb_t x; |
|||
|
|||
value <<= big_normalization_steps; |
|||
udiv_qrnnd (t[0], x, (mp_limb_t) (value >> 32), |
|||
(mp_limb_t) value, big_base_norm); |
|||
t[1] = x >> big_normalization_steps; |
|||
#else |
|||
udiv_qrnnd (t[0], t[1], (mp_limb_t) (value >> 32), |
|||
(mp_limb_t) value, brec->big.base); |
|||
#endif |
|||
n = 2; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
t[0] = value; |
|||
n = 1; |
|||
} |
|||
|
|||
/* Convert the 1-3 words in t[], word by word, to ASCII. */ |
|||
do |
|||
{ |
|||
mp_limb_t ti = t[--n]; |
|||
int ndig_for_this_limb = 0; |
|||
|
|||
#if UDIV_TIME > 2 * UMUL_TIME |
|||
mp_limb_t base_multiplier = brec->base_multiplier; |
|||
if (brec->flag) |
|||
while (ti != 0) |
|||
{ |
|||
mp_limb_t quo, rem, x, dummy; |
|||
|
|||
umul_ppmm (x, dummy, ti, base_multiplier); |
|||
quo = (x + ((ti - x) >> 1)) >> (brec->post_shift - 1); |
|||
rem = ti - quo * 10; |
|||
*--buflim = outdigitwc_value (rem); |
|||
ti = quo; |
|||
++ndig_for_this_limb; |
|||
} |
|||
else |
|||
while (ti != 0) |
|||
{ |
|||
mp_limb_t quo, rem, x, dummy; |
|||
|
|||
umul_ppmm (x, dummy, ti, base_multiplier); |
|||
quo = x >> brec->post_shift; |
|||
rem = ti - quo * 10; |
|||
*--buflim = outdigitwc_value (rem); |
|||
ti = quo; |
|||
++ndig_for_this_limb; |
|||
} |
|||
#else |
|||
while (ti != 0) |
|||
{ |
|||
mp_limb_t quo, rem; |
|||
|
|||
quo = ti / 10; |
|||
rem = ti % 10; |
|||
*--buflim = outdigitwc_value (rem); |
|||
ti = quo; |
|||
++ndig_for_this_limb; |
|||
} |
|||
#endif |
|||
/* If this wasn't the most significant word, pad with zeros. */ |
|||
if (n != 0) |
|||
while (ndig_for_this_limb < brec->big.ndigits) |
|||
{ |
|||
*--buflim = '0'; |
|||
++ndig_for_this_limb; |
|||
} |
|||
} |
|||
while (n != 0); |
|||
#endif |
|||
|
|||
return buflim; |
|||
} |
|||
@ -0,0 +1,41 @@ |
|||
/* Internal function for converting integers to string using locale
|
|||
specific digits. |
|||
Copyright (C) 2000 Free Software Foundation, Inc. |
|||
This file is part of the GNU C Library. |
|||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000. |
|||
|
|||
The GNU C Library is free software; you can redistribute it and/or |
|||
modify it under the terms of the GNU Library General Public License as |
|||
published by the Free Software Foundation; either version 2 of the |
|||
License, or (at your option) any later version. |
|||
|
|||
The GNU C Library is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|||
Library General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Library General Public |
|||
License along with the GNU C Library; see the file COPYING.LIB. If not, |
|||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
|||
Boston, MA 02111-1307, USA. */ |
|||
|
|||
#ifndef _I18N_ITOWA_H |
|||
#define _I18N_ITOWA_H |
|||
#include <sys/cdefs.h> |
|||
|
|||
#include "../locale/outdigitswc.h" |
|||
|
|||
|
|||
extern wchar_t *_i18n_itowa (unsigned long long int value, wchar_t *buflim); |
|||
|
|||
static inline wchar_t * |
|||
_i18n_itowa_word (unsigned long int value, wchar_t *buflim) |
|||
{ |
|||
do |
|||
*--buflim = outdigitwc_value (value % 10); |
|||
while ((value /= 10) != 0); \ |
|||
|
|||
return buflim; |
|||
} |
|||
|
|||
#endif /* _i18n_itoa.h */ |
|||
Loading…
Reference in new issue