diff --git a/newlib/ChangeLog b/newlib/ChangeLog index 2d09818c9..07fca262d 100644 --- a/newlib/ChangeLog +++ b/newlib/ChangeLog @@ -1,3 +1,11 @@ +2003-12-04 Artem B. Bityuckiy + + * libc/stdio/vfprintf.c (_VFPRINTF_R): Use _r versions + of mb routines for %lc and %ls support. + * libc/stdio/vfscanf.c (_svfscanf_r): Add %lc, %C, + %ls, and %S support. Remove CYGNUS_NEC markers and + code within. + 2003-12-04 Jeff Johnston * libc/include/wchar.h: Add prototypes for _mbrtowc_r, @@ -24,7 +32,7 @@ * libc/stdlib/atol.c (_atol_r): New reentrant function. * libc/stdlib/atoll.c (_atoll_r): Ditto. -2003-11-27 Artem B. Bityuckiy +2003-11-27 Artem B. Bityuckiy Jeff Johnston * libc/include/stdlib.h (lldiv_t): New type. @@ -42,12 +50,12 @@ * libc/include/unistd.h: Ditto. * libc/include/stat.h: Ditto. Also declare struct stat64. -2003-11-24 Artem B. Bityuckiy +2003-11-24 Artem B. Bityuckiy * libc/stdio/vfprintf.c (_VFPRINTF_R): Fix check for 'C' format specifier to use ch instead of *fmt. -2003-11-21 Artem B. Bityuckiy +2003-11-21 Artem B. Bityuckiy * libc/stdio/vfprintf.c (_VFPRINTF_R, get_arg): Move mb-specific code within checks for MB_CAPABLE. For non-mb-capable platforms, @@ -163,7 +171,7 @@ * libc/sys/linux/linuxthreads/td_thr_validate.c: Ditto. 2003-11-05 Jeff Johnston - Artem B. Bityuckiy + Artem B. Bityuckiy * libc/stdio/vfprintf.c (_VFPRINTF_R): Add support for %ls, %S, %lc, and %C format specifiers. @@ -182,7 +190,7 @@ CC_FOR_NEWLIB include options. * configure: Regenerated. -2003-10-23 Artem B. Bityuckiy +2003-10-23 Artem B. Bityuckiy * libc/string/wcsnlen.c: New file. * libc/include/wchar.h: Add wcsnlen prototype. diff --git a/newlib/libc/stdio/vfprintf.c b/newlib/libc/stdio/vfprintf.c index 743d307a8..7015740e0 100644 --- a/newlib/libc/stdio/vfprintf.c +++ b/newlib/libc/stdio/vfprintf.c @@ -750,7 +750,7 @@ reswitch: switch (ch) { mbstate_t ps; memset((void *)&ps, '\0', sizeof(mbstate_t)); - if ((size = (int)wcrtomb(cp, + if ((size = (int)_wcrtomb_r(data, cp, (wchar_t)GET_ARG(N, ap, wint_t), &ps)) == -1) goto error; @@ -931,8 +931,8 @@ reswitch: switch (ch) { while (1) { if (wcp[m] == L'\0') break; - if ((n = (int)wcrtomb(buf, - wcp[m], &ps)) == -1) + if ((n = (int)_wcrtomb_r(data, + buf, wcp[m], &ps)) == -1) goto error; if (n + size > prec) break; @@ -943,8 +943,8 @@ reswitch: switch (ch) { } } else { - if ((size = (int)wcsrtombs(NULL, &wcp, - 0, &ps)) == -1) + if ((size = (int)_wcsrtombs_r(data, + NULL, &wcp, 0, &ps)) == -1) goto error; wcp = (_CONST wchar_t *)cp; } @@ -953,13 +953,13 @@ reswitch: switch (ch) { break; if ((malloc_buf = - (char *)malloc(size + 1)) == NULL) + (char *)_malloc_r(data, size + 1)) == NULL) goto error; /* Convert widechar string to multibyte string. */ memset((void *)&ps, '\0', sizeof(mbstate_t)); - if (wcsrtombs(malloc_buf, &wcp, size, &ps) - != size) + if (_wcsrtombs_r(data, malloc_buf, + &wcp, size, &ps) != size) goto error; cp = malloc_buf; cp[size] = '\0'; diff --git a/newlib/libc/stdio/vfscanf.c b/newlib/libc/stdio/vfscanf.c index fab2fbf3c..eef38b9e8 100644 --- a/newlib/libc/stdio/vfscanf.c +++ b/newlib/libc/stdio/vfscanf.c @@ -104,6 +104,7 @@ Supporting OS subroutines required: #include <_ansi.h> #include +#include #include #include #include @@ -138,7 +139,13 @@ extern _LONG_DOUBLE _strtold _PARAMS((char *s, char **sptr)); #endif #include "floatio.h" -#define BUF (MAXEXP+MAXFRACT+3) /* 3 = sign + decimal point + NUL */ + +#if ((MAXEXP+MAXFRACT+3) > MB_LEN_MAX) +# define BUF (MAXEXP+MAXFRACT+3) /* 3 = sign + decimal point + NUL */ +#else +# define BUF MB_LEN_MAX +#endif + /* An upper bound for how long a long prints in decimal. 4 / 13 approximates log (2). Add one char for roundoff compensation and one for the sign. */ #define MAX_LONG_LEN ((CHAR_BIT * sizeof (long) - 1) * 4 / 13 + 2) @@ -254,14 +261,14 @@ __svfscanf_r (rptr, fp, fmt0, ap) int base = 0; /* base argument to strtol/strtoul */ int nbytes = 1; /* number of bytes read from fmt string */ wchar_t wc; /* wchar to use to read format string */ + wchar_t *wcp; /* handy wide character pointer */ + size_t mbslen; /* length of converted multibyte sequence */ + mbstate_t state; /* value to keep track of multibyte state */ u_long (*ccfn) () = 0; /* conversion function (strtol/strtoul) */ char ccltab[256]; /* character class table for %[...] */ char buf[BUF]; /* buffer for numeric conversions */ char *lptr; /* literal pointer */ -#ifdef MB_CAPABLE - mbstate_t state; /* value to keep track of multibyte state */ -#endif char *cp; short *sp; @@ -272,8 +279,6 @@ __svfscanf_r (rptr, fp, fmt0, ap) long *lp; #ifndef _NO_LONGLONG long long *llp; -#else - u_long _uquad; #endif /* `basefix' is used to avoid `if' tests in the integer scanner */ @@ -428,6 +433,9 @@ __svfscanf_r (rptr, fp, fmt0, ap) c = CT_FLOAT; break; #endif + case 'S': + flags |= LONG; + /* FALLTHROUGH */ case 's': c = CT_STRING; @@ -439,6 +447,10 @@ __svfscanf_r (rptr, fp, fmt0, ap) c = CT_CCL; break; + case 'C': + flags |= LONG; + /* FALLTHROUGH */ + case 'c': flags |= NOSKIP; c = CT_CHAR; @@ -516,9 +528,7 @@ __svfscanf_r (rptr, fp, fmt0, ap) if (--fp->_r > 0) fp->_p++; else -#ifndef CYGNUS_NEC if (__srefill (fp)) -#endif goto input_failure; } /* @@ -538,10 +548,47 @@ __svfscanf_r (rptr, fp, fmt0, ap) /* scan arbitrary characters (sets NOSKIP) */ if (width == 0) width = 1; - if (flags & SUPPRESS) + if (flags & LONG) + { + if ((flags & SUPPRESS) == 0) + wcp = va_arg(ap, wchar_t *); + else + wcp = NULL; + n = 0; + while (width != 0) + { + if (n == MB_CUR_MAX) + goto input_failure; + buf[n++] = *fp->_p; + fp->_r -= 1; + fp->_p += 1; + memset((void *)&state, '\0', sizeof(mbstate_t)); + if ((mbslen = _mbrtowc_r(rptr, wcp, buf, n, &state)) + == (size_t)-1) + goto input_failure; /* Invalid sequence */ + if (mbslen == 0 && !(flags & SUPPRESS)) + *wcp = L'\0'; + if (mbslen != (size_t)-2) /* Incomplete sequence */ + { + nread += n; + width -= 1; + if (!(flags & SUPPRESS)) + wcp += 1; + n = 0; + } + if (BufferEmpty) + { + if (n != 0) + goto input_failure; + break; + } + } + if (!(flags & SUPPRESS)) + nassigned++; + } + else if (flags & SUPPRESS) { size_t sum = 0; - for (;;) { if ((n = fp->_r) < (int)width) @@ -549,16 +596,12 @@ __svfscanf_r (rptr, fp, fmt0, ap) sum += n; width -= n; fp->_p += n; -#ifndef CYGNUS_NEC if (__srefill (fp)) { -#endif if (sum == 0) goto input_failure; break; -#ifndef CYGNUS_NEC } -#endif } else { @@ -572,27 +615,11 @@ __svfscanf_r (rptr, fp, fmt0, ap) } else { -#ifdef CYGNUS_NEC - /* Kludge city for the moment */ - char *dest = va_arg (ap, char *); - int n = width; - if (fp->_r == 0) - goto input_failure; - - while (n && fp->_r) - { - *dest++ = *(fp->_p++); - n--; - fp->_r--; - nread++; - } -#else size_t r = fread ((_PTR) va_arg (ap, char *), 1, width, fp); if (r == 0) goto input_failure; nread += r; -#endif nassigned++; } break; @@ -648,8 +675,56 @@ __svfscanf_r (rptr, fp, fmt0, ap) case CT_STRING: /* like CCL, but zero-length string OK, & no NOSKIP */ if (width == 0) - width = ~0; - if (flags & SUPPRESS) + width = (size_t)~0; + if (flags & LONG) + { + /* Process %S and %ls placeholders */ + if ((flags & SUPPRESS) == 0) + wcp = va_arg(ap, wchar_t *); + else + wcp = &wc; + n = 0; + while (!isspace(*fp->_p) && width != 0) + { + if (n == MB_CUR_MAX) + goto input_failure; + buf[n++] = *fp->_p; + fp->_r -= 1; + fp->_p += 1; + memset((void *)&state, '\0', sizeof(mbstate_t)); + if ((mbslen = _mbrtowc_r(rptr, wcp, buf, n, &state)) + == (size_t)-1) + goto input_failure; + if (mbslen == 0) + *wcp = L'\0'; + if (mbslen != (size_t)-2) /* Incomplete sequence */ + { + if (iswspace(*wcp)) + { + while (n != 0) + ungetc(buf[--n], fp); + break; + } + nread += n; + width -= 1; + if ((flags & SUPPRESS) == 0) + wcp += 1; + n = 0; + } + if (BufferEmpty) + { + if (n != 0) + goto input_failure; + break; + } + } + if (!(flags & SUPPRESS)) + { + *wcp = L'\0'; + nassigned++; + } + } + else if (flags & SUPPRESS) { n = 0; while (!isspace (*fp->_p)) @@ -797,9 +872,7 @@ __svfscanf_r (rptr, fp, fmt0, ap) if (--fp->_r > 0) fp->_p++; else -#ifndef CYGNUS_NEC if (__srefill (fp)) -#endif break; /* EOF */ } /* @@ -961,9 +1034,7 @@ __svfscanf_r (rptr, fp, fmt0, ap) if (--fp->_r > 0) fp->_p++; else -#ifndef CYGNUS_NEC if (__srefill (fp)) -#endif break; /* EOF */ } if (zeroes) @@ -998,11 +1069,11 @@ __svfscanf_r (rptr, fp, fmt0, ap) } if ((flags & SUPPRESS) == 0) { - double res; + double res = 0; #ifdef _NO_LONGDBL #define QUAD_RES res; #else /* !_NO_LONG_DBL */ - long double qres; + long double qres = 0; #define QUAD_RES qres; #endif /* !_NO_LONG_DBL */ long new_exp = 0;