diff options
Diffstat (limited to 'libc/stdio/scanf.c')
-rw-r--r-- | libc/stdio/scanf.c | 30 |
1 files changed, 22 insertions, 8 deletions
diff --git a/libc/stdio/scanf.c b/libc/stdio/scanf.c index 48e9344c0..11deea38c 100644 --- a/libc/stdio/scanf.c +++ b/libc/stdio/scanf.c @@ -20,6 +20,11 @@ * Also now optionally supports hexadecimal float notation, positional * args, and glibc locale-specific digit grouping. Should now be * standards compliant. + * + * Aug 18, 2003 + * Bug fix: scanf %lc,%ls,%l[ would always set mb_fail on eof or error, + * even when just starting a new mb char. + * Bug fix: wscanf would incorrectly unget in certain situations. */ @@ -829,7 +834,9 @@ static int scan_getwc(register struct scan_cookie *sc) width = sc->width; /* Preserve width. */ sc->width = INT_MAX; /* MB_CUR_MAX can invoke a function. */ - r = (size_t)(-1); + assert(!sc->mb_fail); + + r = (size_t)(-3); while (__scan_getc(sc) >= 0) { *b = sc->cc; @@ -844,12 +851,17 @@ static int scan_getwc(register struct scan_cookie *sc) break; } - /* If we reach here, either r == ((size_t)-1) and - * mbrtowc set errno to EILSEQ, or r == ((size_t)-2) - * and stream is in an error state or at EOF with a - * partially complete wchar. */ - __set_errno(EILSEQ); /* In case of incomplete conversion. */ - sc->mb_fail = 1; + if (r == ((size_t)(-3))) { /* EOF or ERROR on first read */ + sc->wc = WEOF; + r = (size_t)(-1); + } else { + /* If we reach here, either r == ((size_t)-1) and + * mbrtowc set errno to EILSEQ, or r == ((size_t)-2) + * and stream is in an error state or at EOF with a + * partially complete wchar. */ + __set_errno(EILSEQ); /* In case of incomplete conversion. */ + sc->mb_fail = 1; + } SUCCESS: sc->width = width; /* Restore width. */ @@ -961,7 +973,9 @@ static __inline void kill_scan_cookie(register struct scan_cookie *sc) #else - if ((sc->ungot_wflag & 1) && (sc->fp->filedes != -3) && (sc->fp->state.mask == 0)) { + if ((sc->ungot_flag & 1) && (sc->ungot_wflag & 1) + && (sc->fp->filedes != -3) && (sc->fp->state.mask == 0) + ) { ungetwc(sc->ungot_char, sc->fp); /* Deal with distiction between user and scanf ungots. */ if (sc->nread == 0) { /* Only one char was read... app ungot? */ |