diff options
Diffstat (limited to 'stdio-common')
-rw-r--r-- | stdio-common/vfscanf.c | 275 |
1 files changed, 105 insertions, 170 deletions
diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c index 75e187b765..603940da4c 100644 --- a/stdio-common/vfscanf.c +++ b/stdio-common/vfscanf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1991-2002, 2003, 2004 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 @@ -65,97 +65,91 @@ #define I18N 0x400 /* I: use locale's digits */ -#ifdef USE_IN_LIBIO -# include <libioP.h> -# include <libio.h> +#include <locale/localeinfo.h> +#include <libioP.h> +#include <libio.h> -# undef va_list -# define va_list _IO_va_list +#undef va_list +#define va_list _IO_va_list -# ifdef COMPILE_WSCANF -# define ungetc(c, s) ((void) (c == WEOF \ +#ifdef COMPILE_WSCANF +# define ungetc(c, s) ((void) (c == WEOF \ || (--read_in, \ INTUSE(_IO_sputbackwc) (s, c)))) -# define ungetc_not_eof(c, s) ((void) (--read_in, \ +# define ungetc_not_eof(c, s) ((void) (--read_in, \ INTUSE(_IO_sputbackwc) (s, c))) -# define inchar() (c == WEOF ? ((errno = inchar_errno), WEOF) \ +# define inchar() (c == WEOF ? ((errno = inchar_errno), WEOF) \ : ((c = _IO_getwc_unlocked (s)), \ (void) (c != WEOF \ ? ++read_in \ : (size_t) (inchar_errno = errno)), c)) -# define MEMCPY(d, s, n) __wmemcpy (d, s, n) -# define ISSPACE(Ch) iswspace (Ch) -# define ISDIGIT(Ch) iswdigit (Ch) -# define ISXDIGIT(Ch) iswxdigit (Ch) -# define TOLOWER(Ch) towlower (Ch) -# define ORIENT if (_IO_fwide (s, 1) != 1) return WEOF -# define __strtoll_internal __wcstoll_internal -# define __strtoull_internal __wcstoull_internal -# define __strtol_internal __wcstol_internal -# define __strtoul_internal __wcstoul_internal -# define __strtold_internal __wcstold_internal -# define __strtod_internal __wcstod_internal -# define __strtof_internal __wcstof_internal - -# define L_(Str) L##Str -# define CHAR_T wchar_t -# define UCHAR_T unsigned int -# define WINT_T wint_t -# undef EOF -# define EOF WEOF -# else -# define ungetc(c, s) ((void) ((int) c == EOF \ +# define MEMCPY(d, s, n) __wmemcpy (d, s, n) +# define ISSPACE(Ch) iswspace (Ch) +# define ISDIGIT(Ch) iswdigit (Ch) +# define ISXDIGIT(Ch) iswxdigit (Ch) +# define TOLOWER(Ch) towlower (Ch) +# define ORIENT if (_IO_fwide (s, 1) != 1) return WEOF +# define __strtoll_internal __wcstoll_internal +# define __strtoull_internal __wcstoull_internal +# define __strtol_internal __wcstol_internal +# define __strtoul_internal __wcstoul_internal +# define __strtold_internal __wcstold_internal +# define __strtod_internal __wcstod_internal +# define __strtof_internal __wcstof_internal + +# define L_(Str) L##Str +# define CHAR_T wchar_t +# define UCHAR_T unsigned int +# define WINT_T wint_t +# undef EOF +# define EOF WEOF +#else +# define ungetc(c, s) ((void) ((int) c == EOF \ || (--read_in, \ INTUSE(_IO_sputbackc) (s, (unsigned char) c)))) -# define ungetc_not_eof(c, s) ((void) (--read_in, \ +# define ungetc_not_eof(c, s) ((void) (--read_in, \ INTUSE(_IO_sputbackc) (s, (unsigned char) c))) -# define inchar() (c == EOF ? ((errno = inchar_errno), EOF) \ +# define inchar() (c == EOF ? ((errno = inchar_errno), EOF) \ : ((c = _IO_getc_unlocked (s)), \ (void) (c != EOF \ ? ++read_in \ : (size_t) (inchar_errno = errno)), c)) -# define MEMCPY(d, s, n) memcpy (d, s, n) -# define ISSPACE(Ch) isspace (Ch) -# define ISDIGIT(Ch) isdigit (Ch) -# define ISXDIGIT(Ch) isxdigit (Ch) -# define TOLOWER(Ch) tolower (Ch) -# define ORIENT if (_IO_vtable_offset (s) == 0 \ +# define MEMCPY(d, s, n) memcpy (d, s, n) +# define ISSPACE(Ch) __isspace_l (Ch, loc) +# define ISDIGIT(Ch) __isdigit_l (Ch, loc) +# define ISXDIGIT(Ch) __isxdigit_l (Ch, loc) +# define TOLOWER(Ch) __tolower_l (Ch, loc) +# define ORIENT if (_IO_vtable_offset (s) == 0 \ && _IO_fwide (s, -1) != -1) \ return EOF -# define L_(Str) Str -# define CHAR_T char -# define UCHAR_T unsigned char -# define WINT_T int -# endif +# define L_(Str) Str +# define CHAR_T char +# define UCHAR_T unsigned char +# define WINT_T int +#endif -# define encode_error() do { \ - if (errp != NULL) *errp |= 4; \ - _IO_funlockfile (s); \ - __libc_cleanup_end (0); \ +#define encode_error() do { \ + errval = 4; \ __set_errno (EILSEQ); \ - return done; \ + goto errout; \ } while (0) -# define conv_error() do { \ - if (errp != NULL) *errp |= 2; \ - _IO_funlockfile (s); \ - __libc_cleanup_end (0); \ - return done; \ +#define conv_error() do { \ + errval = 2; \ + goto errout; \ } while (0) -# define input_error() do { \ - _IO_funlockfile (s); \ - if (errp != NULL) *errp |= 1; \ - __libc_cleanup_end (0); \ - return done ?: EOF; \ +#define input_error() do { \ + errval = 1; \ + if (done == 0) done = EOF; \ + goto errout; \ } while (0) -# define memory_error() do { \ - _IO_funlockfile (s); \ +#define memory_error() do { \ __set_errno (ENOMEM); \ - __libc_cleanup_end (0); \ - return EOF; \ + done = EOF; \ + goto errout; \ } while (0) -# define ARGCHECK(s, format) \ +#define ARGCHECK(s, format) \ do \ { \ /* Check file argument for consistence. */ \ @@ -171,100 +165,31 @@ return EOF; \ } \ } while (0) -# define LOCK_STREAM(S) \ +#define LOCK_STREAM(S) \ __libc_cleanup_region_start (1, (void (*) (void *)) &_IO_funlockfile, (S)); \ _IO_flockfile (S) -# define UNLOCK_STREAM(S) \ +#define UNLOCK_STREAM(S) \ _IO_funlockfile (S); \ __libc_cleanup_region_end (0) -#else -# define ungetc(c, s) ((void) (c != EOF && --read_in), ungetc (c, s)) -# define ungetc_not_eof(c, s) (--read_in, (ungetc) (c, s)) -# define inchar() (c == EOF ? EOF \ - : ((c = getc (s)), (void) (c != EOF && ++read_in), c)) -# define MEMCPY(d, s, n) memcpy (d, s, n) -# define ISSPACE(Ch) isspace (Ch) -# define ISDIGIT(Ch) isdigit (Ch) -# define ISXDIGIT(Ch) isxdigit (Ch) -# define TOLOWER(Ch) tolower (Ch) - -# define L_(Str) Str -# define CHAR_T char -# define UCHAR_T unsigned char -# define WINT_T int - -# define encode_error() do { \ - funlockfile (s); \ - __set_errno (EILSEQ); \ - return done; \ - } while (0) -# define conv_error() do { \ - funlockfile (s); \ - return done; \ - } while (0) -# define input_error() do { \ - funlockfile (s); \ - return done ?: EOF; \ - } while (0) -# define memory_error() do { \ - funlockfile (s); \ - __set_errno (ENOMEM); \ - return EOF; \ - } while (0) -# define ARGCHECK(s, format) \ - do \ - { \ - /* Check file argument for consistence. */ \ - if (!__validfp (s) || !s->__mode.__read) \ - { \ - __set_errno (EBADF); \ - return EOF; \ - } \ - else if (format == NULL) \ - { \ - __set_errno (EINVAL); \ - return EOF; \ - } \ - } while (0) -#if 1 - /* XXX For now !!! */ -# define flockfile(S) /* nothing */ -# define funlockfile(S) /* nothing */ -# define LOCK_STREAM(S) -# define UNLOCK_STREAM(S) -#else -# define LOCK_STREAM(S) \ - __libc_cleanup_region_start (&__funlockfile, (S)); \ - __flockfile (S) -# define UNLOCK_STREAM(S) \ - __funlockfile (S); \ - __libc_cleanup_region_end (0) -#endif -#endif /* Read formatted input from S according to the format string FORMAT, using the argument list in ARG. Return the number of assignments made, or -1 for an input error. */ -#ifdef USE_IN_LIBIO -# ifdef COMPILE_WSCANF +#ifdef COMPILE_WSCANF int _IO_vfwscanf (s, format, argptr, errp) _IO_FILE *s; const wchar_t *format; _IO_va_list argptr; int *errp; -# else +#else int _IO_vfscanf (s, format, argptr, errp) _IO_FILE *s; const char *format; _IO_va_list argptr; int *errp; -# endif -#else -int -__vfscanf (FILE *s, const char *format, va_list argptr) #endif { va_list arg; @@ -275,6 +200,11 @@ __vfscanf (FILE *s, const char *format, va_list argptr) register WINT_T c = 0; /* Last char read. */ register int width; /* Maximum field width. */ register int flags; /* Modifiers for current format element. */ + int errval = 0; +#ifndef COMPILE_WSCANF + __locale_t loc = _NL_CURRENT_LOCALE; + struct locale_data *const curctype = loc->__locales[LC_CTYPE]; +#endif /* Errno of last failed inchar call. */ int inchar_errno = 0; @@ -353,20 +283,26 @@ __vfscanf (FILE *s, const char *format, va_list argptr) ARGCHECK (s, format); - /* Figure out the decimal point character. */ + { +#ifndef COMPILE_WSCANF + struct locale_data *const curnumeric = loc->__locales[LC_NUMERIC]; +#endif + + /* Figure out the decimal point character. */ #ifdef COMPILE_WSCANF - decimal = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC); + decimal = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC); #else - decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT); + decimal = curnumeric->values[_NL_ITEM_INDEX (DECIMAL_POINT)].string; #endif - /* Figure out the thousands separator character. */ + /* Figure out the thousands separator character. */ #ifdef COMPILE_WSCANF - thousands = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_THOUSANDS_SEP_WC); + thousands = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_THOUSANDS_SEP_WC); #else - thousands = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP); - if (*thousands == '\0') - thousands = NULL; + thousands = curnumeric->values[_NL_ITEM_INDEX (THOUSANDS_SEP)].string; + if (*thousands == '\0') + thousands = NULL; #endif + } /* Lock the stream. */ LOCK_STREAM (s); @@ -1237,8 +1173,7 @@ __vfscanf (FILE *s, const char *format, va_list argptr) 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; + to_level = (uint32_t) curctype->values[_NL_ITEM_INDEX (_NL_CTYPE_INDIGITS_MB_LEN)].word - 1; #endif /* Read the number into workspace. */ @@ -1266,8 +1201,8 @@ __vfscanf (FILE *s, const char *format, va_list argptr) const char *cmpp; int avail = width > 0 ? width : INT_MAX; - mbdigits[n] = _NL_CURRENT (LC_CTYPE, - _NL_CTYPE_INDIGITS0_MB + n); + mbdigits[n] + = curctype->values[_NL_CTYPE_INDIGITS0_MB + n].string; for (level = 0; level < from_level; level++) mbdigits[n] = strchr (mbdigits[n], '\0') + 1; @@ -2316,33 +2251,31 @@ __vfscanf (FILE *s, const char *format, va_list argptr) && (char *) str == *strptr + strsize) { /* Enlarge the buffer. */ - str = (char *) realloc (*strptr, 2 * strsize); + size_t newsize = 2 * strsize; + + allocagain: + str = (char *) realloc (*strptr, newsize); if (str == NULL) { /* Can't allocate that much. Last-ditch effort. */ - str = (char *) realloc (*strptr, strsize + 1); - if (str == NULL) + if (newsize > strsize + 1) { - /* We lose. Oh well. Terminate the - string and stop converting, - so at least we don't skip any input. */ - ((char *) (*strptr))[strsize - 1] = '\0'; - ++done; - conv_error (); - } - else - { - *strptr = (char *) str; - str += strsize; - ++strsize; + newsize = strsize + 1; + goto allocagain; } + /* We lose. Oh well. Terminate the + string and stop converting, + so at least we don't skip any input. */ + ((char *) (*strptr))[strsize - 1] = '\0'; + ++done; + conv_error (); } else { *strptr = (char *) str; str += strsize; - strsize *= 2; + strsize = newsize; } } } @@ -2428,27 +2361,29 @@ __vfscanf (FILE *s, const char *format, va_list argptr) ungetc (c, s); } + errout: /* Unlock stream. */ UNLOCK_STREAM (s); + if (errp != NULL) + *errp |= errval; + return done; } -#ifdef USE_IN_LIBIO -# ifdef COMPILE_WSCANF +#ifdef COMPILE_WSCANF int __vfwscanf (FILE *s, const wchar_t *format, va_list argptr) { return _IO_vfwscanf (s, format, argptr, NULL); } -# else +#else int __vfscanf (FILE *s, const char *format, va_list argptr) { return INTUSE(_IO_vfscanf) (s, format, argptr, NULL); } libc_hidden_def (__vfscanf) -# endif #endif #ifdef COMPILE_WSCANF |