diff options
author | tjr <tjr@FreeBSD.org> | 2002-09-23 11:35:50 +0000 |
---|---|---|
committer | tjr <tjr@FreeBSD.org> | 2002-09-23 11:35:50 +0000 |
commit | 456a491da7892351012637eda2691f270124c7e9 (patch) | |
tree | 1697747a3d06969079977f9a6d255bb6ad5ed00a /lib/libc/stdio/vfscanf.c | |
parent | 043dfd402f23f3170df53cfd02593ab72c377eff (diff) | |
download | FreeBSD-src-456a491da7892351012637eda2691f270124c7e9.zip FreeBSD-src-456a491da7892351012637eda2691f270124c7e9.tar.gz |
Implement the %lc, %ls and %[ conversions, which read sequences of wide
characters, non-whitespace wide character strings and wide character
strings in a scanset.
Diffstat (limited to 'lib/libc/stdio/vfscanf.c')
-rw-r--r-- | lib/libc/stdio/vfscanf.c | 106 |
1 files changed, 105 insertions, 1 deletions
diff --git a/lib/libc/stdio/vfscanf.c b/lib/libc/stdio/vfscanf.c index 47334d5..358c562 100644 --- a/lib/libc/stdio/vfscanf.c +++ b/lib/libc/stdio/vfscanf.c @@ -48,6 +48,8 @@ __FBSDID("$FreeBSD$"); #include <stddef.h> #include <stdarg.h> #include <string.h> +#include <wchar.h> +#include <wctype.h> #include "un-namespace.h" #include "collate.h" @@ -136,7 +138,11 @@ __svfscanf(FILE *fp, const char *fmt0, va_list ap) int nread; /* number of characters consumed from fp */ int base; /* base argument to conversion function */ char ccltab[256]; /* character class table for %[...] */ - char buf[BUF]; /* buffer for numeric conversions */ + char buf[BUF]; /* buffer for numeric and mb conversions */ + wchar_t *wcp; /* handy wide character pointer */ + wchar_t *wcp0; /* saves original value of wcp */ + mbstate_t mbs; /* multibyte conversion state */ + size_t nconv; /* length of multibyte sequence converted */ /* `basefix' is used to avoid `if' tests in the integer scanner */ static short basefix[17] = @@ -371,6 +377,32 @@ literal: } } nread += sum; + } else if (flags & LONG) { + wcp = va_arg(ap, wchar_t *); + n = 0; + while (width != 0) { + if (n == MB_CUR_MAX) + goto input_failure; + buf[n++] = *fp->_p; + fp->_p++; + fp->_r--; + memset(&mbs, 0, sizeof(mbs)); + nconv = mbrtowc(wcp, buf, n, &mbs); + if (nconv == 0 || nconv == (size_t)-1) + goto input_failure; + if (nconv != (size_t)-2) { + nread += n; + width--; + wcp++; + n = 0; + } + if (fp->_r <= 0 && __srefill(fp)) { + if (n != 0) + goto input_failure; + break; + } + } + nassigned++; } else { size_t r = fread((void *)va_arg(ap, char *), 1, width, fp); @@ -402,6 +434,45 @@ literal: } if (n == 0) goto match_failure; + } else if (flags & LONG) { + wcp = wcp0 = va_arg(ap, wchar_t *); + n = 0; + while (width != 0) { + if (n == MB_CUR_MAX) + goto input_failure; + buf[n++] = *fp->_p; + fp->_p++; + fp->_r--; + memset(&mbs, 0, sizeof(mbs)); + nconv = mbrtowc(wcp, buf, n, &mbs); + if (nconv == 0 || nconv == (size_t)-1) + goto input_failure; + if (nconv != (size_t)-2) { + if (wctob(*wcp) != EOF && + !ccltab[wctob(*wcp)]) { + while (--n > 0) + __ungetc(buf[n], + fp); + break; + } + nread += n; + width--; + wcp++; + n = 0; + } + if (fp->_r <= 0 && __srefill(fp)) { + if (n != 0) + goto input_failure; + break; + } + } + if (n != 0) + goto input_failure; + n = wcp - wcp0; + if (n == 0) + goto match_failure; + *wcp = L'\0'; + nassigned++; } else { p0 = p = va_arg(ap, char *); while (ccltab[*fp->_p]) { @@ -439,6 +510,39 @@ literal: break; } nread += n; + } else if (flags & LONG) { + wcp = va_arg(ap, wchar_t *); + n = 0; + while (!isspace(*fp->_p) && width != 0) { + if (n == MB_CUR_MAX) + goto input_failure; + buf[n++] = *fp->_p; + fp->_p++; + fp->_r--; + memset(&mbs, 0, sizeof(mbs)); + nconv = mbrtowc(wcp, buf, n, &mbs); + if (nconv == 0 || nconv == (size_t)-1) + goto input_failure; + if (nconv != (size_t)-2) { + if (iswspace(*wcp)) { + while (--n > 0) + __ungetc(buf[n], + fp); + break; + } + nread += n; + width--; + wcp++; + n = 0; + } + if (fp->_r <= 0 && __srefill(fp)) { + if (n != 0) + goto input_failure; + break; + } + } + *wcp = L'\0'; + nassigned++; } else { p0 = p = va_arg(ap, char *); while (!isspace(*fp->_p)) { |