Index: lib/libc/stdio/Makefile.inc =================================================================== RCS file: /home/cvs/NetBSD/src/lib/libc/stdio/Makefile.inc,v retrieving revision 1.28 diff -u -r1.28 Makefile.inc --- lib/libc/stdio/Makefile.inc 10 May 2004 17:02:21 -0000 1.28 +++ lib/libc/stdio/Makefile.inc 23 Nov 2004 05:55:20 -0000 @@ -4,7 +4,7 @@ # stdio sources .PATH: ${.CURDIR}/stdio -CPPFLAGS+=-DFLOATING_POINT +CPPFLAGS+=-DFLOATING_POINT -DWCHAR_T_SUPPORT SRCS+= asprintf.c clrerr.c fclose.c fdopen.c feof.c ferror.c fflush.c \ fgetc.c fgetln.c fgetpos.c fgets.c fileno.c findfp.c flags.c \ Index: lib/libc/stdio/vfprintf.c =================================================================== RCS file: /home/cvs/NetBSD/src/lib/libc/stdio/vfprintf.c,v retrieving revision 1.47 diff -u -r1.47 vfprintf.c --- lib/libc/stdio/vfprintf.c 2 Jul 2004 03:00:01 -0000 1.47 +++ lib/libc/stdio/vfprintf.c 23 Nov 2004 07:44:09 -0000 @@ -60,6 +60,11 @@ #include #include +#ifdef WCHAR_T_SUPPORT +#include +#include +#endif + #include "reentrant.h" #include "local.h" #include "fvwrite.h" @@ -241,6 +246,13 @@ char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */ char ox[2]; /* space for 0x hex-prefix */ +#ifdef WCHAR_T_SUPPORT + /* for wchar_t support, %lc(%C), %ls(%S) */ + char *mbs = NULL; + size_t nr; + char mbbuf[(MB_LEN_MAX * 2) + 1]; +#endif + /* * Choose PADSIZE to trade efficiency vs. size. If larger printf * fields occur frequently, increase PADSIZE and make the initialisers @@ -444,10 +456,30 @@ case 'z': flags |= SIZEINT; goto rflag; +#ifdef WCHAR_T_SUPPORT + case 'C': + flags |= LONGINT; + /*FALLTHROUGH*/ +#endif case 'c': +#ifdef WCHAR_T_SUPPORT + if (flags & LONGINT) { + wchar_t wcs[2]; + wcs[0] = (wchar_t)va_arg(ap, wint_t); + wcs[1] = 0; + nr = wcstombs(mbbuf, wcs, sizeof(mbbuf)); + if (nr == (size_t)-1) + goto ilseq; + cp = mbbuf; + size = nr; + } else { +#endif *buf = va_arg(ap, int); cp = buf; size = 1; +#ifdef WCHAR_T_SUPPORT + } +#endif sign = '\0'; break; case 'D': @@ -573,7 +605,54 @@ flags |= HEXPREFIX; ch = 'x'; goto nosign; +#ifdef WCHAR_T_SUPPORT + case 'S': + flags |= LONGINT; + /*FALLTHROUGH*/ +#endif case 's': +#ifdef WCHAR_T_SUPPORT + if (flags & LONGINT) { + wchar_t *wcs = va_arg(ap, wchar_t*); + if (wcs == NULL) + wcs = L"(null)"; + if (prec >= 0) { + size_t i = (size_t)prec; + mbs = (void *)malloc(i + MB_LEN_MAX); + if (mbs == NULL) + goto ilseq; + do { + wchar_t *pwcs = wcs; + char *pmbs= mbs; + mbstate_t st; + memset(&st, 0, sizeof(st)); + nr = wcsrtombs(pmbs, (const + wchar_t **)&pwcs, i--, &st); + if (nr == (size_t)-1) + goto ilseq; + size = nr; + if (mbsinit(&st) == 0) { + pmbs += nr; + nr = wcrtomb(pmbs, 0, + &st); + if (nr == (size_t)-1) + goto ilseq; + size += strlen(pmbs); + } + } while (prec < size); + } else { + nr = wcstombs(NULL, wcs, 0); + if (nr == (size_t)-1) + goto ilseq; + mbs = (void *)malloc(nr + 1); + if (mbs == NULL) + goto ilseq; + (void)wcstombs(mbs, wcs, nr + 1); + size = nr; + } + cp = mbs; + } else { +#endif if ((cp = va_arg(ap, char *)) == NULL) cp = "(null)"; if (prec >= 0) { @@ -592,6 +671,9 @@ size = prec; } else size = strlen(cp); +#ifdef WCHAR_T_SUPPORT + } +#endif sign = '\0'; break; case 'U': @@ -770,6 +852,12 @@ #else PRINT(cp, size); #endif +#ifdef WCHAR_T_SUPPORT + if (mbs != NULL) { + free(mbs); + mbs = NULL; + } +#endif /* left-adjusting padding (always blank) */ if (flags & LADJUST) PAD(width - realsz, blanks); @@ -783,7 +871,14 @@ FLUSH(); error: if (__sferror(fp)) +#ifdef WCHAR_T_SUPPORT +ilseq: +#endif ret = -1; +#ifdef WCHAR_T_SUPPORT + if (mbs != NULL) + free(mbs); +#endif return (ret); } Index: lib/libc/stdio/vfscanf.c =================================================================== RCS file: /home/cvs/NetBSD/src/lib/libc/stdio/vfscanf.c,v retrieving revision 1.36 diff -u -r1.36 vfscanf.c --- lib/libc/stdio/vfscanf.c 30 Dec 2003 22:10:20 -0000 1.36 +++ lib/libc/stdio/vfscanf.c 23 Nov 2004 08:03:01 -0000 @@ -51,6 +51,8 @@ #include #include #include +#include +#include #include "reentrant.h" #include "local.h" @@ -158,6 +160,13 @@ static const short basefix[17] = { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }; + mbstate_t stfmt, stfp; + wchar_t wcfmt, wcfp; + size_t len; +#ifdef WCHAR_T_SUPPORT + wchar_t *wcs; +#endif + _DIAGASSERT(fp != NULL); _DIAGASSERT(fmt0 != NULL); @@ -165,13 +174,24 @@ nassigned = 0; nread = 0; +#ifdef __GNUC__ base = 0; /* XXX just to keep gcc happy */ ccfn = NULL; /* XXX just to keep gcc happy */ +#endif + memset(&stfmt, 0, sizeof(stfmt)); + memset(&stfp, 0, sizeof(stfp)); for (;;) { - c = *fmt++; - if (c == 0) { - return (nassigned); + len = mbrtowc(&wcfmt, (const char *)fmt, 1, &stfmt); + if (len == (size_t)-1) + goto match_failure; + else if (len == (size_t)-2) { + fmt++; + continue; } + fmt += len; + c = wctob((wint_t)wcfmt); + if (c == 0) + return (nassigned); if (isspace(c)) { while ((fp->_r > 0 || __srefill(fp) == 0) && isspace(*fp->_p)) @@ -189,13 +209,20 @@ again: c = *fmt++; switch (c) { case '%': + wcfmt = (wchar_t)c; literal: if (fp->_r <= 0 && __srefill(fp)) goto input_failure; - if (*fp->_p != c) + len = mbrtowc(&wcfp, (const char *)fp->_p, 1, &stfp); + if (len == (size_t)-1) + goto input_failure; + else if (len == (size_t)-2) { + nread++, fp->_r--, fp->_p++; + goto literal; + } + if (wcfmt != wcfp) goto match_failure; - fp->_r--, fp->_p++; - nread++; + nread += len, fp->_r -= len, fp->_p += len; continue; case '*': @@ -294,6 +321,12 @@ break; #endif +#ifdef WCHAR_T_SUPPORT + case 'S': + flags |= LONG; + /*FALLTHROUGH*/ +#endif + case 's': c = CT_STRING; break; @@ -304,6 +337,12 @@ c = CT_CCL; break; +#ifdef WCHAR_T_SUPPORT + case 'C': + flags |= LONG; + /*FALLTHROUGH*/ +#endif + case 'c': flags |= NOSKIP; c = CT_CHAR; @@ -355,6 +394,23 @@ break; } + for (;;) { + mbstate_t saved = stfp; + if (fp->_r <= 0 && __srefill(fp)) + goto input_failure; + len = mbrtowc(&wcfp, (const char *)fp->_p, 1, &stfp); + if (len == (size_t)-1) + goto input_failure; + else if (len == (size_t)-2) { + nread++, fp->_r--, fp->_p++; + if (mbsinit(&stfp) == 0) + break; + } else { + stfp = saved; + break; + } + } + /* * We have a conversion that requires input. */ @@ -389,6 +445,33 @@ /* scan arbitrary characters (sets NOSKIP) */ if (width == 0) width = 1; +#ifdef WCHAR_T_SUPPORT + if (flags & LONG) { + if (flags & SUPPRESS) + wcs = NULL; + else { + wcs = va_arg(ap, wchar_t *); + nassigned++; + } + do { + if (fp->_r <= 0 && __srefill(fp)) + goto input_failure; + len = mbrtowc(&wcfp, (const char *) + fp->_p, 1, &stfp); + if (len == (size_t)-1) + goto input_failure; + else if (len == (size_t)-2) { + nread++, fp->_r--, fp->_p++; + continue; + } + nread += len, + fp->_r -= len, fp->_p += len; + if (wcs != NULL) + *wcs++ = wcfp; + width--; + } while (width > 0); + } else { +#endif if (flags & SUPPRESS) { size_t sum = 0; for (;;) { @@ -418,6 +501,9 @@ nread += r; nassigned++; } +#ifdef WCHAR_T_SUPPORT + } +#endif break; case CT_CCL: @@ -425,6 +511,51 @@ if (width == 0) width = ~0U; /* `infinity' */ /* take only those things in the class */ +#ifdef WCHAR_T_SUPPORT + if (flags & LONG) { + n = 0; + if (flags & SUPPRESS) + wcs = NULL; + else { + wcs = va_arg(ap, wchar_t *); + nassigned++; + } + for (;;) { + if (fp->_r <= 0 && __srefill(fp)) + goto input_failure; + if (ccltab[*fp->_p]) { + len = mbrtowc(&wcfp, (const + char *)fp->_p, 1, &stfp); + if (len == (size_t)-1) + goto input_failure; + else if (len == (size_t)-2) { + n++, fp->_r--, fp->_p++; + continue; + } + n += len, + fp->_r -= len, fp->_p += len; + width--; + } else { + if (mbsinit(&stfp) == 0) { + errno = EILSEQ; + goto input_failure; + } + wcfp = L'\0'; + } + if (wcs != NULL) + *wcs++ = wcfp; + if (wcfp == L'\0') + break; + if (width == 0) { + if (wcs != NULL) + *wcs++ = L'\0'; + break; + } + } + if (n == 0) + goto match_failure; + } else { +#endif if (flags & SUPPRESS) { n = 0; while (ccltab[*fp->_p]) { @@ -437,7 +568,7 @@ break; } } - if (n == 0) + if (n == (size_t)0) goto match_failure; } else { p0 = p = va_arg(ap, char *); @@ -458,6 +589,9 @@ *p = 0; nassigned++; } +#ifdef WCHAR_T_SUPPORT + } +#endif nread += n; break; @@ -465,6 +599,49 @@ /* like CCL, but zero-length string OK, & no NOSKIP */ if (width == 0) width = ~0U; +#ifdef WCHAR_T_SUPPORT + if (flags & LONG) { + if (flags & SUPPRESS) + wcs = NULL; + else { + wcs = va_arg(ap, wchar_t *); + nassigned++; + } + for (;;) { + if (fp->_r <= 0 && __srefill(fp)) + goto input_failure; + if (!isspace((int)*fp->_p)) { + len = mbrtowc(&wcfp, (const + char *)fp->_p, 1, &stfp); + if (len == (size_t)-1) + goto input_failure; + else if (len == (size_t)-2) { + nread++, + fp->_r--, fp->_p++; + continue; + } + nread += len, + fp->_r -= len, fp->_p += len; + width--; + } else { + if (mbsinit(&stfp) == 0) { + errno = EILSEQ; + goto input_failure; + } + wcfp = L'\0'; + } + if (wcs != NULL) + *wcs++ = wcfp; + if (wcfp == L'\0') + break; + if (width == 0) { + if (wcs != NULL) + *wcs++ = L'\0'; + break; + } + } + } else { +#endif if (flags & SUPPRESS) { n = 0; while (!isspace(*fp->_p)) { @@ -489,6 +666,9 @@ nread += p - p0; nassigned++; } +#ifdef WCHAR_T_SUPPORT + } +#endif continue; case CT_INT: