diff options
Diffstat (limited to 'lib/libc/stdio/vfwprintf.c')
-rw-r--r-- | lib/libc/stdio/vfwprintf.c | 96 |
1 files changed, 58 insertions, 38 deletions
diff --git a/lib/libc/stdio/vfwprintf.c b/lib/libc/stdio/vfwprintf.c index 9f06f1b..aa2fdc8 100644 --- a/lib/libc/stdio/vfwprintf.c +++ b/lib/libc/stdio/vfwprintf.c @@ -66,6 +66,7 @@ __FBSDID("$FreeBSD$"); #include "fvwrite.h" #include "printflocal.h" +static int __sprint(FILE *, struct __suio *); static int __sbprintf(FILE *, const wchar_t *, va_list); static wint_t __xfputwc(wchar_t, FILE *); static wchar_t *__ujtoa(uintmax_t, wchar_t *, int, int, const char *, int, @@ -74,6 +75,37 @@ static wchar_t *__ultoa(u_long, wchar_t *, int, int, const char *, int, char, const char *); static wchar_t *__mbsconv(char *, int); +#define CHAR wchar_t +#include "printfcommon.h" + +/* + * Flush out all the vectors defined by the given uio, + * then reset it so that it can be reused. + * + * XXX The fact that we do this a character at a time and convert to a + * multibyte character sequence even if the destination is a wide + * string eclipses the benefits of buffering. + */ +static int +__sprint(FILE *fp, struct __suio *uio) +{ + struct __siov *iov; + wchar_t *p; + int i, len; + + iov = uio->uio_iov; + for (; uio->uio_resid != 0; uio->uio_resid -= len, iov++) { + p = (wchar_t *)iov->iov_base; + len = iov->iov_len; + for (i = 0; i < len; i++) { + if (__xfputwc(p[i], fp) == WEOF) + return (-1); + } + } + uio->uio_iovcnt = 0; + return (0); +} + /* * Helper function for `fprintf to unbuffered unix file': creates a * temporary buffer. We only work on write-only files; this avoids @@ -414,14 +446,14 @@ __vfwprintf(FILE *fp, const wchar_t *fmt0, va_list ap) { wchar_t *fmt; /* format string */ wchar_t ch; /* character from fmt */ - int n, n2, n3; /* handy integer (short term usage) */ + int n, n2; /* handy integer (short term usage) */ wchar_t *cp; /* handy char pointer (short term usage) */ int flags; /* flags as above */ int ret; /* return value accumulator */ int width; /* width from format (%8d), or 0 */ int prec; /* precision from format; <0 for N/A */ wchar_t sign; /* sign prefix (' ', '+', '-', or \0) */ - char thousands_sep; /* locale specific thousands separator */ + wchar_t thousands_sep; /* locale specific thousands separator */ const char *grouping; /* locale specific numeric grouping rules */ #ifndef NO_FLOATING_POINT /* @@ -463,6 +495,7 @@ __vfwprintf(FILE *fp, const wchar_t *fmt0, va_list ap) int size; /* size of converted field or string */ int prsize; /* max size of printed field */ const char *xdigs; /* digits for [xX] conversion */ + struct io_state io; /* I/O buffering state */ wchar_t buf[BUF]; /* buffer with space for digits of uintmax_t */ wchar_t ox[2]; /* space for 0x hex-prefix */ union arg *argtable; /* args, built due to positional arg */ @@ -471,45 +504,26 @@ __vfwprintf(FILE *fp, const wchar_t *fmt0, va_list ap) va_list orgap; /* original argument pointer */ wchar_t *convbuf; /* multibyte to wide conversion result */ - /* - * Choose PADSIZE to trade efficiency vs. size. If larger printf - * fields occur frequently, increase PADSIZE and make the initialisers - * below longer. - */ -#define PADSIZE 16 /* pad chunk size */ - static wchar_t blanks[PADSIZE] = - {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}; - static wchar_t zeroes[PADSIZE] = - {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}; - static const char xdigs_lower[16] = "0123456789abcdef"; static const char xdigs_upper[16] = "0123456789ABCDEF"; - /* - * BEWARE, these `goto error' on error, PRINT uses `n2' and - * PAD uses `n'. - */ + /* BEWARE, these `goto error' on error. */ #define PRINT(ptr, len) do { \ - for (n3 = 0; n3 < (len); n3++) \ - __xfputwc((ptr)[n3], fp); \ + if (io_print(&io, (ptr), (len))) \ + goto error; \ } while (0) -#define PAD(howmany, with) do { \ - if ((n = (howmany)) > 0) { \ - while (n > PADSIZE) { \ - PRINT(with, PADSIZE); \ - n -= PADSIZE; \ - } \ - PRINT(with, n); \ - } \ -} while (0) -#define PRINTANDPAD(p, ep, len, with) do { \ - n2 = (ep) - (p); \ - if (n2 > (len)) \ - n2 = (len); \ - if (n2 > 0) \ - PRINT((p), n2); \ - PAD((len) - (n2 > 0 ? n2 : 0), (with)); \ -} while(0) +#define PAD(howmany, with) { \ + if (io_pad(&io, (howmany), (with))) \ + goto error; \ +} +#define PRINTANDPAD(p, ep, len, with) { \ + if (io_printandpad(&io, (p), (ep), (len), (with))) \ + goto error; \ +} +#define FLUSH() { \ + if (io_flush(&io)) \ + goto error; \ +} /* * Get the argument indexed by nextarg. If the argument table is @@ -591,6 +605,7 @@ __vfwprintf(FILE *fp, const wchar_t *fmt0, va_list ap) argtable = NULL; nextarg = 1; va_copy(orgap, ap); + io_init(&io, fp); ret = 0; #ifndef NO_FLOATING_POINT decimal_point = localeconv()->decimal_point; @@ -1120,8 +1135,10 @@ number: if ((dprec = prec) >= 0) if (!expchar) { /* %[fF] or sufficiently short %[gG] */ if (expt <= 0) { PRINT(zeroes, 1); - if (prec || flags & ALT) - PRINT(decimal_point, 1); + if (prec || flags & ALT) { + buf[0] = *decimal_point; + PRINT(buf, 1); + } PAD(-expt, zeroes); /* already handled initial 0's */ prec += expt; @@ -1173,8 +1190,11 @@ number: if ((dprec = prec) >= 0) /* finally, adjust ret */ ret += prsize; + + FLUSH(); /* copy out the I/O vectors */ } done: + FLUSH(); error: va_end(orgap); if (convbuf != NULL) |