diff options
author | Ulrich Drepper <drepper@redhat.com> | 2000-02-11 18:50:36 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2000-02-11 18:50:36 +0000 |
commit | a1d84548c8aa7023cd039c85f81b831eef6d4a4c (patch) | |
tree | d4f80547dd8c427aebbf0b43051d01206ea972ae /stdio-common/vfscanf.c | |
parent | f296f567c3f69fd2a61983f464d5c52174e3bab8 (diff) | |
download | glibc-a1d84548c8aa7023cd039c85f81b831eef6d4a4c.tar.gz glibc-a1d84548c8aa7023cd039c85f81b831eef6d4a4c.tar.xz glibc-a1d84548c8aa7023cd039c85f81b831eef6d4a4c.zip |
Update.
2000-02-11 Ulrich Drepper <drepper@redhat.com> * stdio-common/printf-parse.h (parse_one_spec): Set wide elements. * stdio-common/printf_fp.c: Truely support wide characater output. Finally handle decimal points and thousands separator characters correctly for multibyte output. * stdio-common/printf_size.c: Likewise. * sysdeps/generic/printf_fphex.c: Likewise. * sysdeps/ieee754/ldbl-96/printf_fphex.c: Likewise. * stdio-common/vfscanf.c: Implement I modifier for numbers to read locale dependent digits. * locale/C-monetary.c (_nl_C_LC_MONETARY): Change wide character decimal point and thousands separator values to wide characters from wide character strings. * locale/C-numeric.c (_nl_C_LC_NUMERIC): Likewise. * locale/indigitswc.h: Dereference wcdigits array elements. 2000-02-03 Jakub Jelinek <jakub@redhat.com> * stdlib/canonicalize.c (canonicalize): Zero terminate path to copy on error. 2000-02-01 Cristian Gafton <gafton@redhat.com> * misc/syslog.c (closelog): Reset LogType to SOCK_DGRAM. 2000-01-31 Philip Blundell <philb@gnu.org> * sysdeps/arm/fpu/fpu_control.h (_FPU_DEFAULT): Set the AC bit. 2000-01-31 Andreas Jaeger <aj@suse.de> * intl/Makefile (generated): msgs.h is generated. * localedata/Makefile (generated-dirs): Add de_DE.437. 2000-01-31 Jakub Jelinek <jakub@redhat.com> * config.make.in: Allow default localedir to come from configure. * configure.in: Export libc_cv_localedir. * sysdeps/unix/sysv/linux/configure.in: For sparc64, put locale stuff into $exec_prefix/lib/locale because it can be shared between 32bit and 64bit libraries. * configure: Rebuilt. * sysdeps/unix/sysv/linux/configure: Rebuilt. 2000-01-31 Andreas Jaeger <aj@suse.de> * inet/tst-network.c: New file. * inet/Makefile (tests): Add tst-network. * inet/inet_net.c (inet_network): Don't overwrite memory or allow to great last digits.
Diffstat (limited to 'stdio-common/vfscanf.c')
-rw-r--r-- | stdio-common/vfscanf.c | 150 |
1 files changed, 135 insertions, 15 deletions
diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c index b50e7b8323..6b95352971 100644 --- a/stdio-common/vfscanf.c +++ b/stdio-common/vfscanf.c @@ -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 @@ -62,6 +62,7 @@ #define GROUP 0x080 /* ': group numbers */ #define MALLOC 0x100 /* a: malloc strings */ #define CHAR 0x200 /* hh: char */ +#define I18N 0x400 /* I: use locale's digits */ #ifdef USE_IN_LIBIO @@ -479,8 +480,9 @@ __vfscanf (FILE *s, const char *format, va_list argptr) } } - /* Check for the assignment-suppressing and the number grouping flag. */ - while (*f == L_('*') || *f == L_('\'')) + /* Check for the assignment-suppressing, the number grouping flag, + and the signal to use the locale's digit representation. */ + while (*f == L_('*') || *f == L_('\'') || *f == L_('I')) switch (*f++) { case L_('*'): @@ -489,6 +491,9 @@ __vfscanf (FILE *s, const char *format, va_list argptr) case L_('\''): flags |= GROUP; break; + case L_('I'): + flags |= I18N; + break; } /* We have seen width. */ @@ -1192,22 +1197,137 @@ __vfscanf (FILE *s, const char *format, va_list argptr) if (base == 0) base = 10; - /* Read the number into workspace. */ - while (c != EOF && width != 0) + if (base == 10 && (flags & I18N) != 0) { - if (base == 16 ? !ISXDIGIT (c) : - ((!ISDIGIT (c) || c - L_('0') >= base) && - !((flags & GROUP) && base == 10 && c == thousands))) - break; - ADDW (c); - if (width > 0) - --width; + int from_level; + int to_level; +#ifdef COMPILE_WPRINTF + const wchar_t *wcdigits; +#else + const char *mbdigits[10]; +#endif + int n; - c = inchar (); + from_level = 0; +#ifdef COMPILE_WPRINTF + to_level = _NL_CURRENT_WORD (LC_CTYPE, + _NL_CTYPE_INDIGITS_WC_LEN) - 1; +#else + to_level = _NL_CURRENT_WORD (LC_CTYPE, + _NL_CTYPE_INDIGITS_MB_LEN) - 1; +#endif + + /* 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; + size_t dcnt; + + /* Get the string for the digits with value N. */ +#ifdef COMPILE_WPRINTF + wcdigits[n] = _NL_CURRENT (LC_CTYPE, + _NL_CTYPE_INDIGITS0_WC + n); + if (c == *wcdigit[n]) + break; + + /* Advance the pointer to the next string. */ + ++wcdigits[n]; +#else + mbdigits[n] = _NL_CURRENT (LC_CTYPE, + _NL_CTYPE_INDIGITS0_MB + n); + dlen = strlen (mbdigits[n]); + + dcnt = 0; + do + { + if (c != mbdigits[n][dcnt]) + break; + c = inchar (); + } + while (--dcnt > 0); + + if (dcnt == 0) + /* We found it. */ + break; + + /* Advance the pointer to the next string. */ + mbdigits[n] += dlen + 1; + } +#endif + + if (n == 10) + { + /*Have not yet found the digit. */ + while (++from_level <= to_level) + { + /* Search all ten digits of this level. */ + for (n = 0; n < 10; ++n) + { +#ifdef COMPILE_WPRINTF + if (c == *wcdigit[n]) + break; + + /* Advance the pointer to the next string. */ + ++wcdigits[n]; +#else + size_t dlen = strlen (mbdigits[n]); + size_t dcnt; + + dcnt = 0; + do + { + if (c != mbdigits[n][dcnt]) + break; + c = inchar (); + } + while (--dcnt > 0); + + if (dcnt == 0) + /* We found it. */ + break; + + /* Advance the pointer to the next string. */ + mbdigits[n] += dlen + 1; +#endif + } + + if (n < 10) + /* Found it. */ + break; + + /* Next level. */ + ++from_level; + } + } + + if (n == 10) + { + /* Haven't found anything. Push the last character back + and return an error. */ + ungetc (c, s); + input_error (); + } + + ADDW (L_('0') + n); } + else + /* Read the number into workspace. */ + while (c != EOF && width != 0) + { + if (base == 16 ? !ISXDIGIT (c) : + ((!ISDIGIT (c) || c - L_('0') >= base) && + !((flags & GROUP) && base == 10 && c == thousands))) + break; + ADDW (c); + if (width > 0) + --width; + + c = inchar (); + } - if (wpsize == 0 || - (wpsize == 1 && (wp[0] == L_('+') || wp[0] == L_('-')))) + if (wpsize == 0 + || (wpsize == 1 && (wp[0] == L_('+') || wp[0] == L_('-')))) { /* There was no number. If we are supposed to read a pointer we must recognize "(nil)" as well. */ |