diff options
Diffstat (limited to 'lib/printf/vfprintf.c')
-rw-r--r-- | lib/printf/vfprintf.c | 235 |
1 files changed, 20 insertions, 215 deletions
diff --git a/lib/printf/vfprintf.c b/lib/printf/vfprintf.c index 70f5074e2..69b9e2da9 100644 --- a/lib/printf/vfprintf.c +++ b/lib/printf/vfprintf.c @@ -37,11 +37,7 @@ * SUCH DAMAGE. */ -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)vfprintf.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); /* * Actual printf innards. @@ -49,163 +45,38 @@ __FBSDID("$FreeBSD$"); * This code is large and complicated... */ -#include "namespace.h" #include <sys/types.h> +#include <sys/uio.h> #include <ctype.h> #include <errno.h> #include <limits.h> -#include <locale.h> #include <stddef.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <wchar.h> -#include <printf.h> #include <stdarg.h> -#include "xlocale_private.h" -#include "un-namespace.h" -#include "libc_private.h" -#include "local.h" -#include "fvwrite.h" -#include "printflocal.h" +#define NO_FLOATING_POINT -static int __sprint(FILE *, struct __suio *, locale_t); -static int __sbprintf(FILE *, locale_t, const char *, va_list) __printflike(3, 0) - __noinline; -static char *__wcsconv(wchar_t *, int); +int __vfprintf(FILE *fp, const char *fmt0, va_list ap); -#define CHAR char -#include "printfcommon.h" +struct __suio { + size_t uio_resid; -struct grouping_state { - char *thousands_sep; /* locale-specific thousands separator */ - int thousep_len; /* length of thousands_sep */ - const char *grouping; /* locale-specific numeric grouping rules */ - int lead; /* sig figs before decimal or group sep */ - int nseps; /* number of group separators with ' */ - int nrepeats; /* number of repeats of the last group */ + struct iovec *uio_iov; + size_t uio_iovcnt; }; -/* - * Initialize the thousands' grouping state in preparation to print a - * number with ndigits digits. This routine returns the total number - * of bytes that will be needed. - */ -static int -grouping_init(struct grouping_state *gs, int ndigits, locale_t loc) -{ - struct lconv *locale; - - locale = localeconv_l(loc); - gs->grouping = locale->grouping; - gs->thousands_sep = locale->thousands_sep; - gs->thousep_len = strlen(gs->thousands_sep); - - gs->nseps = gs->nrepeats = 0; - gs->lead = ndigits; - while (*gs->grouping != CHAR_MAX) { - if (gs->lead <= *gs->grouping) - break; - gs->lead -= *gs->grouping; - if (*(gs->grouping+1)) { - gs->nseps++; - gs->grouping++; - } else - gs->nrepeats++; - } - return ((gs->nseps + gs->nrepeats) * gs->thousep_len); -} - -/* - * Print a number with thousands' separators. - */ -static int -grouping_print(struct grouping_state *gs, struct io_state *iop, - const CHAR *cp, const CHAR *ep, locale_t locale) -{ - const CHAR *cp0 = cp; - - if (io_printandpad(iop, cp, ep, gs->lead, zeroes, locale)) - return (-1); - cp += gs->lead; - while (gs->nseps > 0 || gs->nrepeats > 0) { - if (gs->nrepeats > 0) - gs->nrepeats--; - else { - gs->grouping--; - gs->nseps--; - } - if (io_print(iop, gs->thousands_sep, gs->thousep_len, locale)) - return (-1); - if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes, locale)) - return (-1); - cp += *gs->grouping; - } - if (cp > ep) - cp = ep; - return (cp - cp0); -} - -/* - * Flush out all the vectors defined by the given uio, - * then reset it so that it can be reused. - */ -static int -__sprint(FILE *fp, struct __suio *uio, locale_t locale) -{ - int err; - - if (uio->uio_resid == 0) { - uio->uio_iovcnt = 0; - return (0); - } - err = __sfvwrite(fp, uio); - uio->uio_resid = 0; - uio->uio_iovcnt = 0; - return (err); -} - -/* - * Helper function for `fprintf to unbuffered unix file': creates a - * temporary buffer. We only work on write-only files; this avoids - * worries about ungetc buffers and so forth. - */ -static int -__sbprintf(FILE *fp, locale_t locale, const char *fmt, va_list ap) -{ - int ret; - FILE fake = FAKE_FILE; - unsigned char buf[BUFSIZ]; - - /* XXX This is probably not needed. */ - if (prepwrite(fp) != 0) - return (EOF); - - /* copy the important variables */ - fake._flags = fp->_flags & ~__SNBF; - fake._file = fp->_file; - fake._cookie = fp->_cookie; - fake._write = fp->_write; - fake._orientation = fp->_orientation; - fake._mbstate = fp->_mbstate; +#include "printflocal.h" - /* set up the buffer */ - fake._bf._base = fake._p = buf; - fake._bf._size = fake._w = sizeof(buf); - fake._lbfsize = 0; /* not actually used, but Just In Case */ +static char *__wcsconv(wchar_t *, int); - /* do the work, then copy any error status */ - ret = __vfprintf(&fake, locale, fmt, ap); - if (ret >= 0 && __fflush(&fake)) - ret = EOF; - if (fake._flags & __SERR) - fp->_flags |= __SERR; - return (ret); -} +#define CHAR char +#include "printfcommon.h" /* * Convert a wide character string argument for the %ls format to a multibyte @@ -267,32 +138,6 @@ __wcsconv(wchar_t *wcsarg, int prec) } /* - * MT-safe version - */ -int -vfprintf_l(FILE * __restrict fp, locale_t locale, const char * __restrict fmt0, - va_list ap) -{ - int ret; - FIX_LOCALE(locale); - - FLOCKFILE_CANCELSAFE(fp); - /* optimise fprintf(stderr) (and other unbuffered Unix files) */ - if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && - fp->_file >= 0) - ret = __sbprintf(fp, locale, fmt0, ap); - else - ret = __vfprintf(fp, locale, fmt0, ap); - FUNLOCKFILE_CANCELSAFE(); - return (ret); -} -int -vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap) -{ - return vfprintf_l(fp, __get_locale(), fmt0, ap); -} - -/* * The size of the buffer we use as scratch space for integer * conversions, among other things. We need enough space to * write a uintmax_t in octal (plus one byte). @@ -307,7 +152,7 @@ vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap) * Non-MT-safe version */ int -__vfprintf(FILE *fp, locale_t locale, const char *fmt0, va_list ap) +__vfprintf(FILE *fp, const char *fmt0, va_list ap) { char *fmt; /* format string */ int ch; /* character from fmt */ @@ -319,7 +164,6 @@ __vfprintf(FILE *fp, locale_t locale, const char *fmt0, va_list ap) int prec; /* precision from format; <0 for N/A */ int saved_errno; char sign; /* sign prefix (' ', '+', '-', or \0) */ - struct grouping_state gs; /* thousands' grouping info */ #ifndef NO_FLOATING_POINT /* @@ -374,21 +218,18 @@ __vfprintf(FILE *fp, locale_t locale, const char *fmt0, va_list ap) /* BEWARE, these `goto error' on error. */ #define PRINT(ptr, len) { \ - if (io_print(&io, (ptr), (len), locale)) \ + if (io_print(&io, (ptr), (len))) \ goto error; \ } #define PAD(howmany, with) { \ - if (io_pad(&io, (howmany), (with), locale)) \ + if (io_pad(&io, (howmany), (with))) \ goto error; \ } #define PRINTANDPAD(p, ep, len, with) { \ - if (io_printandpad(&io, (p), (ep), (len), (with), locale)) \ - goto error; \ -} -#define FLUSH() { \ - if (io_flush(&io, locale)) \ + if (io_printandpad(&io, (p), (ep), (len), (with))) \ goto error; \ } +#define FLUSH() do { } while (0) /* * Get the argument indexed by nextarg. If the argument table is @@ -453,17 +294,6 @@ __vfprintf(FILE *fp, locale_t locale, const char *fmt0, va_list ap) val = GETARG (int); \ } - if (__use_xprintf == 0 && getenv("USE_XPRINTF")) - __use_xprintf = 1; - if (__use_xprintf > 0) - return (__xvprintf(fp, fmt0, ap)); - - /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */ - if (prepwrite(fp) != 0) { - errno = EBADF; - return (EOF); - } - savserr = fp->_flags & __SERR; fp->_flags &= ~__SERR; @@ -477,7 +307,7 @@ __vfprintf(FILE *fp, locale_t locale, const char *fmt0, va_list ap) ret = 0; #ifndef NO_FLOATING_POINT dtoaresult = NULL; - decimal_point = localeconv_l(locale)->decimal_point; + decimal_point = "."; /* The overwhelmingly common case is decpt_len == 1. */ decpt_len = (decimal_point[1] == '\0' ? 1 : strlen(decimal_point)); #endif @@ -505,7 +335,6 @@ __vfprintf(FILE *fp, locale_t locale, const char *fmt0, va_list ap) dprec = 0; width = 0; prec = -1; - gs.grouping = NULL; sign = '\0'; ox[1] = '\0'; @@ -628,7 +457,6 @@ reswitch: switch (ch) { mbseqlen = wcrtomb(cp = buf, (wchar_t)GETARG(wint_t), &mbs); if (mbseqlen == (size_t)-1) { - fp->_flags |= __SERR; goto error; } size = (int)mbseqlen; @@ -773,8 +601,6 @@ fp_common: /* space for decimal pt and following digits */ if (prec || flags & ALT) size += prec + decpt_len; - if ((flags & GROUPING) && expt > 0) - size += grouping_init(&gs, expt, locale); } break; #endif /* !NO_FLOATING_POINT */ @@ -844,7 +670,6 @@ fp_common: else { convbuf = __wcsconv(wcp, prec); if (convbuf == NULL) { - fp->_flags |= __SERR; goto error; } cp = convbuf; @@ -915,8 +740,6 @@ number: if ((dprec = prec) >= 0) size = buf + BUF - cp; if (size > BUF) /* should never happen */ abort(); - if ((flags & GROUPING) && size != 0) - size += grouping_init(&gs, size, locale); break; default: /* "%?" prints ?, unless ? is NUL */ if (ch == '\0') @@ -979,12 +802,7 @@ number: if ((dprec = prec) >= 0) #endif /* leading zeroes from decimal precision */ PAD(dprec - size, zeroes); - if (gs.grouping) { - if (grouping_print(&gs, &io, cp, buf+BUF, locale) < 0) - goto error; - } else { - PRINT(cp, size); - } + PRINT(cp, size); #ifndef NO_FLOATING_POINT } else { /* glue together f_p fragments */ if (!expchar) { /* %[fF] or sufficiently short %[gG] */ @@ -996,17 +814,8 @@ number: if ((dprec = prec) >= 0) /* already handled initial 0's */ prec += expt; } else { - if (gs.grouping) { - n = grouping_print(&gs, &io, - cp, dtoaend, locale); - if (n < 0) - goto error; - cp += n; - } else { - PRINTANDPAD(cp, dtoaend, - expt, zeroes); - cp += expt; - } + PRINTANDPAD(cp, dtoaend, expt, zeroes); + cp += expt; if (prec || flags & ALT) PRINT(decimal_point,decpt_len); } @@ -1042,10 +851,6 @@ error: #endif if (convbuf != NULL) free(convbuf); - if (__sferror(fp)) - ret = EOF; - else - fp->_flags |= savserr; if ((argtable != NULL) && (argtable != statargtable)) free (argtable); return (ret); |