diff options
Diffstat (limited to 'lib/libc/stdio/xprintf.c')
-rw-r--r-- | lib/libc/stdio/xprintf.c | 690 |
1 files changed, 0 insertions, 690 deletions
diff --git a/lib/libc/stdio/xprintf.c b/lib/libc/stdio/xprintf.c deleted file mode 100644 index 0cc8571..0000000 --- a/lib/libc/stdio/xprintf.c +++ /dev/null @@ -1,690 +0,0 @@ -/*- - * Copyright (c) 2005 Poul-Henning Kamp - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Chris Torek. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include "namespace.h" -#include <err.h> -#include <sys/types.h> -#include <stdio.h> -#include <stddef.h> -#include <stdlib.h> -#include <locale.h> -#include <stdint.h> -#include <assert.h> -#include <stdarg.h> -#include <namespace.h> -#include <string.h> -#include <wchar.h> -#include "un-namespace.h" - -#include "local.h" -#include "printf.h" -#include "fvwrite.h" - -int __use_xprintf = -1; - -/* private stuff -----------------------------------------------------*/ - -union arg { - int intarg; - long longarg; - intmax_t intmaxarg; -#ifndef NO_FLOATING_POINT - double doublearg; - long double longdoublearg; -#endif - wint_t wintarg; - char *pchararg; - wchar_t *pwchararg; - void *pvoidarg; -}; - -/* - * Macros for converting digits to letters and vice versa - */ -#define to_digit(c) ((c) - '0') -#define is_digit(c) (((unsigned)to_digit(c)) <= 9) - -/* various globals ---------------------------------------------------*/ - -const char __lowercase_hex[17] = "0123456789abcdef?"; /*lint !e784 */ -const char __uppercase_hex[17] = "0123456789ABCDEF?"; /*lint !e784 */ - -#define PADSIZE 16 -static char blanks[PADSIZE] = - {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}; -static char zeroes[PADSIZE] = - {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}; - -/* printing and padding functions ------------------------------------*/ - -#define NIOV 8 - -struct __printf_io { - FILE *fp; - struct __suio uio; - struct __siov iov[NIOV]; - struct __siov *iovp; -}; - -static void -__printf_init(struct __printf_io *io) -{ - - io->uio.uio_iov = io->iovp = &io->iov[0]; - io->uio.uio_resid = 0; - io->uio.uio_iovcnt = 0; -} - -void -__printf_flush(struct __printf_io *io) -{ - - __sfvwrite(io->fp, &io->uio); - __printf_init(io); -} - -int -__printf_puts(struct __printf_io *io, const void *ptr, int len) -{ - - - if (io->fp->_flags & __SERR) - return (0); - if (len == 0) - return (0); - io->iovp->iov_base = __DECONST(void *, ptr); - io->iovp->iov_len = len; - io->uio.uio_resid += len; - io->iovp++; - io->uio.uio_iovcnt++; - if (io->uio.uio_iovcnt >= NIOV) - __printf_flush(io); - return (len); -} - -int -__printf_pad(struct __printf_io *io, int howmany, int zero) -{ - int n; - const char *with; - int ret = 0; - - if (zero) - with = zeroes; - else - with = blanks; - - if ((n = (howmany)) > 0) { - while (n > PADSIZE) { - ret += __printf_puts(io, with, PADSIZE); - n -= PADSIZE; - } - ret += __printf_puts(io, with, n); - } - return (ret); -} - -int -__printf_out(struct __printf_io *io, const struct printf_info *pi, const void *ptr, int len) -{ - int ret = 0; - - if ((!pi->left) && pi->width > len) - ret += __printf_pad(io, pi->width - len, pi->pad == '0'); - ret += __printf_puts(io, ptr, len); - if (pi->left && pi->width > len) - ret += __printf_pad(io, pi->width - len, pi->pad == '0'); - return (ret); -} - - -/* percent handling -------------------------------------------------*/ - -static int -__printf_arginfo_pct(const struct printf_info *pi __unused, size_t n __unused, int *argt __unused) -{ - - return (0); -} - -static int -__printf_render_pct(struct __printf_io *io, const struct printf_info *pi __unused, const void *const *arg __unused) -{ - - return (__printf_puts(io, "%", 1)); -} - -/* 'n' ---------------------------------------------------------------*/ - -static int -__printf_arginfo_n(const struct printf_info *pi, size_t n, int *argt) -{ - - assert(n >= 1); - argt[0] = PA_POINTER; - return (1); -} - -/* - * This is a printf_render so that all output has been flushed before it - * gets called. - */ - -static int -__printf_render_n(FILE *io __unused, const struct printf_info *pi, const void *const *arg) -{ - - if (pi->is_char) - **((signed char **)arg[0]) = (signed char)pi->sofar; - else if (pi->is_short) - **((short **)arg[0]) = (short)pi->sofar; - else if (pi->is_long) - **((long **)arg[0]) = pi->sofar; - else if (pi->is_long_double) - **((long long **)arg[0]) = pi->sofar; - else if (pi->is_intmax) - **((intmax_t **)arg[0]) = pi->sofar; - else if (pi->is_ptrdiff) - **((ptrdiff_t **)arg[0]) = pi->sofar; - else if (pi->is_quad) - **((quad_t **)arg[0]) = pi->sofar; - else if (pi->is_size) - **((size_t **)arg[0]) = pi->sofar; - else - **((int **)arg[0]) = pi->sofar; - - return (0); -} - -/* table -------------------------------------------------------------*/ - -/*lint -esym(785, printf_tbl) */ -static struct { - printf_arginfo_function *arginfo; - printf_function *gnurender; - printf_render *render; -} printf_tbl[256] = { - ['%'] = { __printf_arginfo_pct, NULL, __printf_render_pct }, - ['A'] = { __printf_arginfo_float, NULL, __printf_render_float }, - ['C'] = { __printf_arginfo_chr, NULL, __printf_render_chr }, - ['E'] = { __printf_arginfo_float, NULL, __printf_render_float }, - ['F'] = { __printf_arginfo_float, NULL, __printf_render_float }, - ['G'] = { __printf_arginfo_float, NULL, __printf_render_float }, - ['S'] = { __printf_arginfo_str, NULL, __printf_render_str }, - ['X'] = { __printf_arginfo_int, NULL, __printf_render_int }, - ['a'] = { __printf_arginfo_float, NULL, __printf_render_float }, - ['c'] = { __printf_arginfo_chr, NULL, __printf_render_chr }, - ['d'] = { __printf_arginfo_int, NULL, __printf_render_int }, - ['e'] = { __printf_arginfo_float, NULL, __printf_render_float }, - ['f'] = { __printf_arginfo_float, NULL, __printf_render_float }, - ['g'] = { __printf_arginfo_float, NULL, __printf_render_float }, - ['i'] = { __printf_arginfo_int, NULL, __printf_render_int }, - ['n'] = { __printf_arginfo_n, __printf_render_n, NULL }, - ['o'] = { __printf_arginfo_int, NULL, __printf_render_int }, - ['p'] = { __printf_arginfo_ptr, NULL, __printf_render_ptr }, - ['q'] = { __printf_arginfo_int, NULL, __printf_render_int }, - ['s'] = { __printf_arginfo_str, NULL, __printf_render_str }, - ['u'] = { __printf_arginfo_int, NULL, __printf_render_int }, - ['x'] = { __printf_arginfo_int, NULL, __printf_render_int }, -}; - - -static int -__v2printf(FILE *fp, const char *fmt0, unsigned pct, va_list ap) -{ - struct printf_info *pi, *pil; - const char *fmt; - int ch; - struct printf_info pia[pct + 10]; - int argt[pct + 10]; - union arg args[pct + 10]; - int nextarg; - int maxarg; - int ret = 0; - int n; - struct __printf_io io; - - __printf_init(&io); - io.fp = fp; - - fmt = fmt0; - maxarg = 0; - nextarg = 1; - memset(argt, 0, sizeof argt); - for (pi = pia; ; pi++) { - memset(pi, 0, sizeof *pi); - pil = pi; - if (*fmt == '\0') - break; - pil = pi + 1; - pi->prec = -1; - pi->pad = ' '; - pi->begin = pi->end = fmt; - while (*fmt != '\0' && *fmt != '%') - pi->end = ++fmt; - if (*fmt == '\0') - break; - fmt++; - for (;;) { - pi->spec = *fmt; - switch (pi->spec) { - case ' ': - /*- - * ``If the space and + flags both appear, the space - * flag will be ignored.'' - * -- ANSI X3J11 - */ - if (pi->showsign == 0) - pi->showsign = ' '; - fmt++; - continue; - case '#': - pi->alt = 1; - fmt++; - continue; - case '.': - pi->prec = 0; - fmt++; - if (*fmt == '*') { - fmt++; - pi->get_prec = nextarg; - argt[nextarg++] = PA_INT; - continue; - } - while (*fmt != '\0' && is_digit(*fmt)) { - pi->prec *= 10; - pi->prec += to_digit(*fmt); - fmt++; - } - continue; - case '-': - pi->left = 1; - fmt++; - continue; - case '+': - pi->showsign = '+'; - fmt++; - continue; - case '*': - fmt++; - pi->get_width = nextarg; - argt[nextarg++] = PA_INT; - continue; - case '%': - fmt++; - break; - case '\'': - pi->group = 1; - fmt++; - continue; - case '0': - /*- - * ``Note that 0 is taken as a flag, not as the - * beginning of a field width.'' - * -- ANSI X3J11 - */ - pi->pad = '0'; - fmt++; - continue; - case '1': case '2': case '3': - case '4': case '5': case '6': - case '7': case '8': case '9': - n = 0; - while (*fmt != '\0' && is_digit(*fmt)) { - n *= 10; - n += to_digit(*fmt); - fmt++; - } - if (*fmt == '$') { - if (nextarg > maxarg) - maxarg = nextarg; - nextarg = n; - fmt++; - } else - pi->width = n; - continue; - case 'D': - case 'O': - case 'U': - pi->spec += ('a' - 'A'); - pi->is_intmax = 0; - if (pi->is_long_double || pi->is_quad) { - pi->is_long = 0; - pi->is_long_double = 1; - } else { - pi->is_long = 1; - pi->is_long_double = 0; - } - fmt++; - break; - case 'j': - pi->is_intmax = 1; - fmt++; - continue; - case 'q': - pi->is_long = 0; - pi->is_quad = 1; - fmt++; - continue; - case 'L': - pi->is_long_double = 1; - fmt++; - continue; - case 'h': - fmt++; - if (*fmt == 'h') { - fmt++; - pi->is_char = 1; - } else { - pi->is_short = 1; - } - continue; - case 'l': - fmt++; - if (*fmt == 'l') { - fmt++; - pi->is_long_double = 1; - pi->is_quad = 0; - } else { - pi->is_quad = 0; - pi->is_long = 1; - } - continue; - case 't': - pi->is_ptrdiff = 1; - fmt++; - continue; - case 'z': - pi->is_size = 1; - fmt++; - continue; - default: - fmt++; - break; - } - if (printf_tbl[pi->spec].arginfo == NULL) - errx(1, "arginfo[%c] = NULL", pi->spec); - ch = printf_tbl[pi->spec].arginfo( - pi, __PRINTFMAXARG, &argt[nextarg]); - if (ch > 0) - pi->arg[0] = &args[nextarg]; - if (ch > 1) - pi->arg[1] = &args[nextarg + 1]; - nextarg += ch; - break; - } - } - if (nextarg > maxarg) - maxarg = nextarg; -#if 0 - fprintf(stderr, "fmt0 <%s>\n", fmt0); - fprintf(stderr, "pil %p\n", pil); -#endif - for (ch = 1; ch < maxarg; ch++) { -#if 0 - fprintf(stderr, "arg %d %x\n", ch, argt[ch]); -#endif - switch(argt[ch]) { - case PA_CHAR: - args[ch].intarg = (char)va_arg (ap, int); - break; - case PA_INT: - args[ch].intarg = va_arg (ap, int); - break; - case PA_INT | PA_FLAG_SHORT: - args[ch].intarg = (short)va_arg (ap, int); - break; - case PA_INT | PA_FLAG_LONG: - args[ch].longarg = va_arg (ap, long); - break; - case PA_INT | PA_FLAG_INTMAX: - args[ch].intmaxarg = va_arg (ap, intmax_t); - break; - case PA_INT | PA_FLAG_QUAD: - args[ch].intmaxarg = va_arg (ap, quad_t); - break; - case PA_INT | PA_FLAG_LONG_LONG: - args[ch].intmaxarg = va_arg (ap, long long); - break; - case PA_INT | PA_FLAG_SIZE: - args[ch].intmaxarg = va_arg (ap, size_t); - break; - case PA_INT | PA_FLAG_PTRDIFF: - args[ch].intmaxarg = va_arg (ap, ptrdiff_t); - break; - case PA_WCHAR: - args[ch].wintarg = va_arg (ap, wint_t); - break; - case PA_POINTER: - args[ch].pvoidarg = va_arg (ap, void *); - break; - case PA_STRING: - args[ch].pchararg = va_arg (ap, char *); - break; - case PA_WSTRING: - args[ch].pwchararg = va_arg (ap, wchar_t *); - break; - case PA_DOUBLE: -#ifndef NO_FLOATING_POINT - args[ch].doublearg = va_arg (ap, double); -#endif - break; - case PA_DOUBLE | PA_FLAG_LONG_DOUBLE: -#ifndef NO_FLOATING_POINT - args[ch].longdoublearg = va_arg (ap, long double); -#endif - break; - default: - errx(1, "argtype = %x (fmt = \"%s\")\n", - argt[ch], fmt0); - } - } - for (pi = pia; pi < pil; pi++) { -#if 0 - fprintf(stderr, "pi %p", pi); - fprintf(stderr, " spec '%c'", pi->spec); - fprintf(stderr, " args %d", - ((uintptr_t)pi->arg[0] - (uintptr_t)args) / sizeof args[0]); - if (pi->width) fprintf(stderr, " width %d", pi->width); - if (pi->pad) fprintf(stderr, " pad 0x%x", pi->pad); - if (pi->left) fprintf(stderr, " left"); - if (pi->showsign) fprintf(stderr, " showsign"); - if (pi->prec != -1) fprintf(stderr, " prec %d", pi->prec); - if (pi->is_char) fprintf(stderr, " char"); - if (pi->is_short) fprintf(stderr, " short"); - if (pi->is_long) fprintf(stderr, " long"); - if (pi->is_long_double) fprintf(stderr, " long_double"); - fprintf(stderr, "\n"); - fprintf(stderr, "\t\"%.*s\"\n", pi->end - pi->begin, pi->begin); -#endif - if (pi->get_width) { - pi->width = args[pi->get_width].intarg; - /*- - * ``A negative field width argument is taken as a - * - flag followed by a positive field width.'' - * -- ANSI X3J11 - * They don't exclude field widths read from args. - */ - if (pi->width < 0) { - pi->left = 1; - pi->width = -pi->width; - } - } - if (pi->get_prec) - pi->prec = args[pi->get_prec].intarg; - ret += __printf_puts(&io, pi->begin, pi->end - pi->begin); - if (printf_tbl[pi->spec].gnurender != NULL) { - __printf_flush(&io); - pi->sofar = ret; - ret += printf_tbl[pi->spec].gnurender( - fp, pi, (const void *)pi->arg); - } else if (printf_tbl[pi->spec].render != NULL) { - pi->sofar = ret; - n = printf_tbl[pi->spec].render( - &io, pi, (const void *)pi->arg); - if (n < 0) - io.fp->_flags |= __SERR; - else - ret += n; - } else if (pi->begin == pi->end) - errx(1, "render[%c] = NULL", *fmt); - } - __printf_flush(&io); - return (ret); -} - -extern int __fflush(FILE *fp); - -/* - * 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 -__v3printf(FILE *fp, const char *fmt, int pct, va_list ap) -{ - int ret; - FILE fake = FAKE_FILE; - unsigned char buf[BUFSIZ]; - - /* 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; - - /* 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 */ - - /* do the work, then copy any error status */ - ret = __v2printf(&fake, fmt, pct, ap); - if (ret >= 0 && __fflush(&fake)) - ret = EOF; - if (fake._flags & __SERR) - fp->_flags |= __SERR; - return (ret); -} - -int -__xvprintf(FILE *fp, const char *fmt0, va_list ap) -{ - unsigned u; - const char *p; - - /* Count number of '%' signs handling double '%' signs */ - for (p = fmt0, u = 0; *p; p++) { - if (*p != '%') - continue; - u++; - if (p[1] == '%') - p++; - } - - /* optimise fprintf(stderr) (and other unbuffered Unix files) */ - if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && - fp->_file >= 0) - return (__v3printf(fp, fmt0, u, ap)); - else - return (__v2printf(fp, fmt0, u, ap)); -} - -/* extending ---------------------------------------------------------*/ - -int -register_printf_function(int spec, printf_function *render, printf_arginfo_function *arginfo) -{ - - if (spec > 255 || spec < 0) - return (-1); - printf_tbl[spec].gnurender = render; - printf_tbl[spec].arginfo = arginfo; - __use_xprintf = 1; - return (0); -} - -int -register_printf_render(int spec, printf_render *render, printf_arginfo_function *arginfo) -{ - - if (spec > 255 || spec < 0) - return (-1); - printf_tbl[spec].render = render; - printf_tbl[spec].arginfo = arginfo; - __use_xprintf = 1; - return (0); -} - -int -register_printf_render_std(const unsigned char *specs) -{ - - for (; *specs != '\0'; specs++) { - switch (*specs) { - case 'H': - register_printf_render(*specs, - __printf_render_hexdump, - __printf_arginfo_hexdump); - break; - case 'M': - register_printf_render(*specs, - __printf_render_errno, - __printf_arginfo_errno); - break; - case 'Q': - register_printf_render(*specs, - __printf_render_quote, - __printf_arginfo_quote); - break; - case 'T': - register_printf_render(*specs, - __printf_render_time, - __printf_arginfo_time); - break; - case 'V': - register_printf_render(*specs, - __printf_render_vis, - __printf_arginfo_vis); - break; - default: - return (-1); - } - } - return (0); -} - |