xref: /freebsd/lib/libc/stdio/xprintf.c (revision b3e76948)
175067f4fSPoul-Henning Kamp /*-
28a16b7a1SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
38a16b7a1SPedro F. Giffuni  *
475067f4fSPoul-Henning Kamp  * Copyright (c) 2005 Poul-Henning Kamp
575067f4fSPoul-Henning Kamp  * Copyright (c) 1990, 1993
675067f4fSPoul-Henning Kamp  *	The Regents of the University of California.  All rights reserved.
775067f4fSPoul-Henning Kamp  *
875067f4fSPoul-Henning Kamp  * This code is derived from software contributed to Berkeley by
975067f4fSPoul-Henning Kamp  * Chris Torek.
1075067f4fSPoul-Henning Kamp  *
1175067f4fSPoul-Henning Kamp  * Redistribution and use in source and binary forms, with or without
1275067f4fSPoul-Henning Kamp  * modification, are permitted provided that the following conditions
1375067f4fSPoul-Henning Kamp  * are met:
1475067f4fSPoul-Henning Kamp  * 1. Redistributions of source code must retain the above copyright
1575067f4fSPoul-Henning Kamp  *    notice, this list of conditions and the following disclaimer.
1675067f4fSPoul-Henning Kamp  * 2. Redistributions in binary form must reproduce the above copyright
1775067f4fSPoul-Henning Kamp  *    notice, this list of conditions and the following disclaimer in the
1875067f4fSPoul-Henning Kamp  *    documentation and/or other materials provided with the distribution.
1975067f4fSPoul-Henning Kamp  * 3. Neither the name of the University nor the names of its contributors
2075067f4fSPoul-Henning Kamp  *    may be used to endorse or promote products derived from this software
2175067f4fSPoul-Henning Kamp  *    without specific prior written permission.
2275067f4fSPoul-Henning Kamp  *
2375067f4fSPoul-Henning Kamp  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2475067f4fSPoul-Henning Kamp  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2575067f4fSPoul-Henning Kamp  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2675067f4fSPoul-Henning Kamp  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2775067f4fSPoul-Henning Kamp  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2875067f4fSPoul-Henning Kamp  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2975067f4fSPoul-Henning Kamp  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3075067f4fSPoul-Henning Kamp  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3175067f4fSPoul-Henning Kamp  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3275067f4fSPoul-Henning Kamp  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3375067f4fSPoul-Henning Kamp  * SUCH DAMAGE.
3475067f4fSPoul-Henning Kamp  */
3575067f4fSPoul-Henning Kamp 
36c17bf9a9SJohn Baldwin #include "namespace.h"
3775067f4fSPoul-Henning Kamp #include <err.h>
3875067f4fSPoul-Henning Kamp #include <sys/types.h>
3975067f4fSPoul-Henning Kamp #include <stdio.h>
4075067f4fSPoul-Henning Kamp #include <stddef.h>
4175067f4fSPoul-Henning Kamp #include <stdlib.h>
4275067f4fSPoul-Henning Kamp #include <locale.h>
4375067f4fSPoul-Henning Kamp #include <stdint.h>
4475067f4fSPoul-Henning Kamp #include <assert.h>
4575067f4fSPoul-Henning Kamp #include <stdarg.h>
4675067f4fSPoul-Henning Kamp #include <namespace.h>
4775067f4fSPoul-Henning Kamp #include <string.h>
4875067f4fSPoul-Henning Kamp #include <wchar.h>
49c17bf9a9SJohn Baldwin #include "un-namespace.h"
5075067f4fSPoul-Henning Kamp 
511b0181dfSJohn Baldwin #include "local.h"
5275067f4fSPoul-Henning Kamp #include "printf.h"
5375067f4fSPoul-Henning Kamp #include "fvwrite.h"
5475067f4fSPoul-Henning Kamp 
5575067f4fSPoul-Henning Kamp int __use_xprintf = -1;
5675067f4fSPoul-Henning Kamp 
5775067f4fSPoul-Henning Kamp /* private stuff -----------------------------------------------------*/
5875067f4fSPoul-Henning Kamp 
5975067f4fSPoul-Henning Kamp union arg {
6075067f4fSPoul-Henning Kamp 	int			intarg;
6175067f4fSPoul-Henning Kamp 	long			longarg;
6275067f4fSPoul-Henning Kamp 	intmax_t 		intmaxarg;
6375067f4fSPoul-Henning Kamp #ifndef NO_FLOATING_POINT
6475067f4fSPoul-Henning Kamp 	double			doublearg;
6575067f4fSPoul-Henning Kamp 	long double 		longdoublearg;
6675067f4fSPoul-Henning Kamp #endif
6775067f4fSPoul-Henning Kamp 	wint_t			wintarg;
6875067f4fSPoul-Henning Kamp 	char			*pchararg;
6975067f4fSPoul-Henning Kamp 	wchar_t			*pwchararg;
7075067f4fSPoul-Henning Kamp 	void			*pvoidarg;
7175067f4fSPoul-Henning Kamp };
7275067f4fSPoul-Henning Kamp 
7375067f4fSPoul-Henning Kamp /*
7475067f4fSPoul-Henning Kamp  * Macros for converting digits to letters and vice versa
7575067f4fSPoul-Henning Kamp  */
7675067f4fSPoul-Henning Kamp #define	to_digit(c)	((c) - '0')
7775067f4fSPoul-Henning Kamp #define is_digit(c)	(((unsigned)to_digit(c)) <= 9)
7875067f4fSPoul-Henning Kamp 
7975067f4fSPoul-Henning Kamp /* various globals ---------------------------------------------------*/
8075067f4fSPoul-Henning Kamp 
8175067f4fSPoul-Henning Kamp const char __lowercase_hex[17] = "0123456789abcdef?";	/*lint !e784 */
8275067f4fSPoul-Henning Kamp const char __uppercase_hex[17] = "0123456789ABCDEF?";	/*lint !e784 */
8375067f4fSPoul-Henning Kamp 
8475067f4fSPoul-Henning Kamp #define PADSIZE 16
8575067f4fSPoul-Henning Kamp static char blanks[PADSIZE] =
8675067f4fSPoul-Henning Kamp 	 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
8775067f4fSPoul-Henning Kamp static char zeroes[PADSIZE] =
8875067f4fSPoul-Henning Kamp 	 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
8975067f4fSPoul-Henning Kamp 
9075067f4fSPoul-Henning Kamp /* printing and padding functions ------------------------------------*/
9175067f4fSPoul-Henning Kamp 
9275067f4fSPoul-Henning Kamp #define NIOV 8
9375067f4fSPoul-Henning Kamp 
9475067f4fSPoul-Henning Kamp struct __printf_io {
9575067f4fSPoul-Henning Kamp 	FILE		*fp;
9675067f4fSPoul-Henning Kamp 	struct __suio	uio;
9775067f4fSPoul-Henning Kamp 	struct __siov	iov[NIOV];
9875067f4fSPoul-Henning Kamp 	struct __siov	*iovp;
9975067f4fSPoul-Henning Kamp };
10075067f4fSPoul-Henning Kamp 
10175067f4fSPoul-Henning Kamp static void
__printf_init(struct __printf_io * io)10275067f4fSPoul-Henning Kamp __printf_init(struct __printf_io *io)
10375067f4fSPoul-Henning Kamp {
10475067f4fSPoul-Henning Kamp 
10575067f4fSPoul-Henning Kamp 	io->uio.uio_iov = io->iovp = &io->iov[0];
10675067f4fSPoul-Henning Kamp 	io->uio.uio_resid = 0;
10775067f4fSPoul-Henning Kamp 	io->uio.uio_iovcnt = 0;
10875067f4fSPoul-Henning Kamp }
10975067f4fSPoul-Henning Kamp 
11075067f4fSPoul-Henning Kamp void
__printf_flush(struct __printf_io * io)11175067f4fSPoul-Henning Kamp __printf_flush(struct __printf_io *io)
11275067f4fSPoul-Henning Kamp {
11375067f4fSPoul-Henning Kamp 
11475067f4fSPoul-Henning Kamp 	__sfvwrite(io->fp, &io->uio);
11575067f4fSPoul-Henning Kamp 	__printf_init(io);
11675067f4fSPoul-Henning Kamp }
11775067f4fSPoul-Henning Kamp 
11875067f4fSPoul-Henning Kamp int
__printf_puts(struct __printf_io * io,const void * ptr,int len)11975067f4fSPoul-Henning Kamp __printf_puts(struct __printf_io *io, const void *ptr, int len)
12075067f4fSPoul-Henning Kamp {
12175067f4fSPoul-Henning Kamp 
12275067f4fSPoul-Henning Kamp 
12375067f4fSPoul-Henning Kamp 	if (io->fp->_flags & __SERR)
12475067f4fSPoul-Henning Kamp 		return (0);
12575067f4fSPoul-Henning Kamp 	if (len == 0)
12675067f4fSPoul-Henning Kamp 		return (0);
12775067f4fSPoul-Henning Kamp 	io->iovp->iov_base = __DECONST(void *, ptr);
12875067f4fSPoul-Henning Kamp 	io->iovp->iov_len = len;
12975067f4fSPoul-Henning Kamp 	io->uio.uio_resid += len;
13075067f4fSPoul-Henning Kamp 	io->iovp++;
13175067f4fSPoul-Henning Kamp 	io->uio.uio_iovcnt++;
13275067f4fSPoul-Henning Kamp 	if (io->uio.uio_iovcnt >= NIOV)
13375067f4fSPoul-Henning Kamp 		__printf_flush(io);
13475067f4fSPoul-Henning Kamp 	return (len);
13575067f4fSPoul-Henning Kamp }
13675067f4fSPoul-Henning Kamp 
13775067f4fSPoul-Henning Kamp int
__printf_pad(struct __printf_io * io,int howmany,int zero)13875067f4fSPoul-Henning Kamp __printf_pad(struct __printf_io *io, int howmany, int zero)
13975067f4fSPoul-Henning Kamp {
14075067f4fSPoul-Henning Kamp 	int n;
14175067f4fSPoul-Henning Kamp 	const char *with;
14275067f4fSPoul-Henning Kamp 	int ret = 0;
14375067f4fSPoul-Henning Kamp 
14475067f4fSPoul-Henning Kamp 	if (zero)
14575067f4fSPoul-Henning Kamp 		with = zeroes;
14675067f4fSPoul-Henning Kamp 	else
14775067f4fSPoul-Henning Kamp 		with = blanks;
14875067f4fSPoul-Henning Kamp 
14975067f4fSPoul-Henning Kamp 	if ((n = (howmany)) > 0) {
15075067f4fSPoul-Henning Kamp 		while (n > PADSIZE) {
15175067f4fSPoul-Henning Kamp 			ret += __printf_puts(io, with, PADSIZE);
15275067f4fSPoul-Henning Kamp 			n -= PADSIZE;
15375067f4fSPoul-Henning Kamp 		}
15475067f4fSPoul-Henning Kamp 		ret += __printf_puts(io, with, n);
15575067f4fSPoul-Henning Kamp 	}
15675067f4fSPoul-Henning Kamp 	return (ret);
15775067f4fSPoul-Henning Kamp }
15875067f4fSPoul-Henning Kamp 
15975067f4fSPoul-Henning Kamp int
__printf_out(struct __printf_io * io,const struct printf_info * pi,const void * ptr,int len)16075067f4fSPoul-Henning Kamp __printf_out(struct __printf_io *io, const struct printf_info *pi, const void *ptr, int len)
16175067f4fSPoul-Henning Kamp {
16275067f4fSPoul-Henning Kamp 	int ret = 0;
16375067f4fSPoul-Henning Kamp 
16475067f4fSPoul-Henning Kamp 	if ((!pi->left) && pi->width > len)
16575067f4fSPoul-Henning Kamp 		ret += __printf_pad(io, pi->width - len, pi->pad == '0');
16675067f4fSPoul-Henning Kamp 	ret += __printf_puts(io, ptr, len);
16775067f4fSPoul-Henning Kamp 	if (pi->left && pi->width > len)
16875067f4fSPoul-Henning Kamp 		ret += __printf_pad(io, pi->width - len, pi->pad == '0');
16975067f4fSPoul-Henning Kamp 	return (ret);
17075067f4fSPoul-Henning Kamp }
17175067f4fSPoul-Henning Kamp 
17275067f4fSPoul-Henning Kamp 
17375067f4fSPoul-Henning Kamp /* percent handling  -------------------------------------------------*/
17475067f4fSPoul-Henning Kamp 
17575067f4fSPoul-Henning Kamp static int
__printf_arginfo_pct(const struct printf_info * pi __unused,size_t n __unused,int * argt __unused)17675067f4fSPoul-Henning Kamp __printf_arginfo_pct(const struct printf_info *pi __unused, size_t n __unused, int *argt __unused)
17775067f4fSPoul-Henning Kamp {
17875067f4fSPoul-Henning Kamp 
17975067f4fSPoul-Henning Kamp 	return (0);
18075067f4fSPoul-Henning Kamp }
18175067f4fSPoul-Henning Kamp 
18275067f4fSPoul-Henning Kamp static int
__printf_render_pct(struct __printf_io * io,const struct printf_info * pi __unused,const void * const * arg __unused)18375067f4fSPoul-Henning Kamp __printf_render_pct(struct __printf_io *io, const struct printf_info *pi __unused, const void *const *arg __unused)
18475067f4fSPoul-Henning Kamp {
18575067f4fSPoul-Henning Kamp 
18675067f4fSPoul-Henning Kamp 	return (__printf_puts(io, "%", 1));
18775067f4fSPoul-Henning Kamp }
18875067f4fSPoul-Henning Kamp 
18975067f4fSPoul-Henning Kamp /* 'n' ---------------------------------------------------------------*/
19075067f4fSPoul-Henning Kamp 
19175067f4fSPoul-Henning Kamp static int
__printf_arginfo_n(const struct printf_info * pi,size_t n,int * argt)19275067f4fSPoul-Henning Kamp __printf_arginfo_n(const struct printf_info *pi, size_t n, int *argt)
19375067f4fSPoul-Henning Kamp {
19475067f4fSPoul-Henning Kamp 
19575067f4fSPoul-Henning Kamp 	assert(n >= 1);
19675067f4fSPoul-Henning Kamp 	argt[0] = PA_POINTER;
19775067f4fSPoul-Henning Kamp 	return (1);
19875067f4fSPoul-Henning Kamp }
19975067f4fSPoul-Henning Kamp 
20075067f4fSPoul-Henning Kamp /*
20175067f4fSPoul-Henning Kamp  * This is a printf_render so that all output has been flushed before it
20275067f4fSPoul-Henning Kamp  * gets called.
20375067f4fSPoul-Henning Kamp  */
20475067f4fSPoul-Henning Kamp 
20575067f4fSPoul-Henning Kamp static int
__printf_render_n(FILE * io __unused,const struct printf_info * pi,const void * const * arg)20675067f4fSPoul-Henning Kamp __printf_render_n(FILE *io __unused, const struct printf_info *pi, const void *const *arg)
20775067f4fSPoul-Henning Kamp {
20875067f4fSPoul-Henning Kamp 
20975067f4fSPoul-Henning Kamp 	if (pi->is_char)
21075067f4fSPoul-Henning Kamp 		**((signed char **)arg[0]) = (signed char)pi->sofar;
21175067f4fSPoul-Henning Kamp 	else if (pi->is_short)
21275067f4fSPoul-Henning Kamp 		**((short **)arg[0]) = (short)pi->sofar;
21375067f4fSPoul-Henning Kamp 	else if (pi->is_long)
21475067f4fSPoul-Henning Kamp 		**((long **)arg[0]) = pi->sofar;
21575067f4fSPoul-Henning Kamp 	else if (pi->is_long_double)
21675067f4fSPoul-Henning Kamp 		**((long long **)arg[0]) = pi->sofar;
21775067f4fSPoul-Henning Kamp 	else if (pi->is_intmax)
21875067f4fSPoul-Henning Kamp 		**((intmax_t **)arg[0]) = pi->sofar;
21975067f4fSPoul-Henning Kamp 	else if (pi->is_ptrdiff)
22075067f4fSPoul-Henning Kamp 		**((ptrdiff_t **)arg[0]) = pi->sofar;
22175067f4fSPoul-Henning Kamp 	else if (pi->is_quad)
22275067f4fSPoul-Henning Kamp 		**((quad_t **)arg[0]) = pi->sofar;
22375067f4fSPoul-Henning Kamp 	else if (pi->is_size)
22475067f4fSPoul-Henning Kamp 		**((size_t **)arg[0]) = pi->sofar;
22575067f4fSPoul-Henning Kamp 	else
22675067f4fSPoul-Henning Kamp 		**((int **)arg[0]) = pi->sofar;
22775067f4fSPoul-Henning Kamp 
22875067f4fSPoul-Henning Kamp 	return (0);
22975067f4fSPoul-Henning Kamp }
23075067f4fSPoul-Henning Kamp 
23175067f4fSPoul-Henning Kamp /* table -------------------------------------------------------------*/
23275067f4fSPoul-Henning Kamp 
23375067f4fSPoul-Henning Kamp /*lint -esym(785, printf_tbl) */
23475067f4fSPoul-Henning Kamp static struct {
23575067f4fSPoul-Henning Kamp 	printf_arginfo_function	*arginfo;
23675067f4fSPoul-Henning Kamp 	printf_function		*gnurender;
23775067f4fSPoul-Henning Kamp 	printf_render		*render;
23875067f4fSPoul-Henning Kamp } printf_tbl[256] = {
23975067f4fSPoul-Henning Kamp 	['%'] = { __printf_arginfo_pct,		NULL,	__printf_render_pct },
24075067f4fSPoul-Henning Kamp 	['A'] = { __printf_arginfo_float,	NULL,	__printf_render_float },
24175067f4fSPoul-Henning Kamp 	['C'] = { __printf_arginfo_chr,		NULL,	__printf_render_chr },
24275067f4fSPoul-Henning Kamp 	['E'] = { __printf_arginfo_float,	NULL,	__printf_render_float },
24375067f4fSPoul-Henning Kamp 	['F'] = { __printf_arginfo_float,	NULL,	__printf_render_float },
24475067f4fSPoul-Henning Kamp 	['G'] = { __printf_arginfo_float,	NULL,	__printf_render_float },
24575067f4fSPoul-Henning Kamp 	['S'] = { __printf_arginfo_str,		NULL,	__printf_render_str },
24675067f4fSPoul-Henning Kamp 	['X'] = { __printf_arginfo_int,		NULL,	__printf_render_int },
24775067f4fSPoul-Henning Kamp 	['a'] = { __printf_arginfo_float,	NULL,	__printf_render_float },
24875067f4fSPoul-Henning Kamp 	['c'] = { __printf_arginfo_chr,		NULL,	__printf_render_chr },
24975067f4fSPoul-Henning Kamp 	['d'] = { __printf_arginfo_int,		NULL,	__printf_render_int },
25075067f4fSPoul-Henning Kamp 	['e'] = { __printf_arginfo_float,	NULL,	__printf_render_float },
25175067f4fSPoul-Henning Kamp 	['f'] = { __printf_arginfo_float,	NULL,	__printf_render_float },
25275067f4fSPoul-Henning Kamp 	['g'] = { __printf_arginfo_float,	NULL,	__printf_render_float },
25375067f4fSPoul-Henning Kamp 	['i'] = { __printf_arginfo_int,		NULL,	__printf_render_int },
25475067f4fSPoul-Henning Kamp 	['n'] = { __printf_arginfo_n,		__printf_render_n, NULL },
25575067f4fSPoul-Henning Kamp 	['o'] = { __printf_arginfo_int,		NULL,	__printf_render_int },
25675067f4fSPoul-Henning Kamp 	['p'] = { __printf_arginfo_ptr,		NULL,	__printf_render_ptr },
25775067f4fSPoul-Henning Kamp 	['q'] = { __printf_arginfo_int,		NULL,	__printf_render_int },
25875067f4fSPoul-Henning Kamp 	['s'] = { __printf_arginfo_str,		NULL,	__printf_render_str },
25975067f4fSPoul-Henning Kamp 	['u'] = { __printf_arginfo_int,		NULL,	__printf_render_int },
26075067f4fSPoul-Henning Kamp 	['x'] = { __printf_arginfo_int,		NULL,	__printf_render_int },
26175067f4fSPoul-Henning Kamp };
26275067f4fSPoul-Henning Kamp 
26375067f4fSPoul-Henning Kamp 
26475067f4fSPoul-Henning Kamp static int
__v2printf(FILE * fp,const char * fmt0,unsigned pct,va_list ap)265525cd732SKonstantin Belousov __v2printf(FILE *fp, const char *fmt0, unsigned pct, va_list ap)
26675067f4fSPoul-Henning Kamp {
26775067f4fSPoul-Henning Kamp 	struct printf_info	*pi, *pil;
26875067f4fSPoul-Henning Kamp 	const char		*fmt;
26975067f4fSPoul-Henning Kamp 	int			ch;
27075067f4fSPoul-Henning Kamp 	struct printf_info	pia[pct + 10];
27175067f4fSPoul-Henning Kamp 	int			argt[pct + 10];
27275067f4fSPoul-Henning Kamp 	union arg		args[pct + 10];
27375067f4fSPoul-Henning Kamp 	int			nextarg;
27475067f4fSPoul-Henning Kamp 	int			maxarg;
27575067f4fSPoul-Henning Kamp 	int			ret = 0;
27675067f4fSPoul-Henning Kamp 	int			n;
27775067f4fSPoul-Henning Kamp 	struct __printf_io	io;
27875067f4fSPoul-Henning Kamp 
27975067f4fSPoul-Henning Kamp 	__printf_init(&io);
28075067f4fSPoul-Henning Kamp 	io.fp = fp;
28175067f4fSPoul-Henning Kamp 
28275067f4fSPoul-Henning Kamp 	fmt = fmt0;
28375067f4fSPoul-Henning Kamp 	maxarg = 0;
28475067f4fSPoul-Henning Kamp 	nextarg = 1;
28575067f4fSPoul-Henning Kamp 	memset(argt, 0, sizeof argt);
28675067f4fSPoul-Henning Kamp 	for (pi = pia; ; pi++) {
28775067f4fSPoul-Henning Kamp 		memset(pi, 0, sizeof *pi);
28875067f4fSPoul-Henning Kamp 		pil = pi;
28975067f4fSPoul-Henning Kamp 		if (*fmt == '\0')
29075067f4fSPoul-Henning Kamp 			break;
29175067f4fSPoul-Henning Kamp 		pil = pi + 1;
29275067f4fSPoul-Henning Kamp 		pi->prec = -1;
29375067f4fSPoul-Henning Kamp 		pi->pad = ' ';
29475067f4fSPoul-Henning Kamp 		pi->begin = pi->end = fmt;
29575067f4fSPoul-Henning Kamp 		while (*fmt != '\0' && *fmt != '%')
29675067f4fSPoul-Henning Kamp 			pi->end = ++fmt;
29775067f4fSPoul-Henning Kamp 		if (*fmt == '\0')
29875067f4fSPoul-Henning Kamp 			break;
29975067f4fSPoul-Henning Kamp 		fmt++;
30075067f4fSPoul-Henning Kamp 		for (;;) {
30175067f4fSPoul-Henning Kamp 			pi->spec = *fmt;
30275067f4fSPoul-Henning Kamp 			switch (pi->spec) {
30375067f4fSPoul-Henning Kamp 			case ' ':
30475067f4fSPoul-Henning Kamp 				/*-
30575067f4fSPoul-Henning Kamp 				 * ``If the space and + flags both appear, the space
30675067f4fSPoul-Henning Kamp 				 * flag will be ignored.''
30775067f4fSPoul-Henning Kamp 				 *      -- ANSI X3J11
30875067f4fSPoul-Henning Kamp 				 */
30975067f4fSPoul-Henning Kamp 				if (pi->showsign == 0)
31075067f4fSPoul-Henning Kamp 					pi->showsign = ' ';
31175067f4fSPoul-Henning Kamp 				fmt++;
31275067f4fSPoul-Henning Kamp 				continue;
31375067f4fSPoul-Henning Kamp 			case '#':
31475067f4fSPoul-Henning Kamp 				pi->alt = 1;
31575067f4fSPoul-Henning Kamp 				fmt++;
31675067f4fSPoul-Henning Kamp 				continue;
31775067f4fSPoul-Henning Kamp 			case '.':
31875067f4fSPoul-Henning Kamp 				pi->prec = 0;
31975067f4fSPoul-Henning Kamp 				fmt++;
32075067f4fSPoul-Henning Kamp 				if (*fmt == '*') {
32175067f4fSPoul-Henning Kamp 					fmt++;
32275067f4fSPoul-Henning Kamp 					pi->get_prec = nextarg;
32375067f4fSPoul-Henning Kamp 					argt[nextarg++] = PA_INT;
32475067f4fSPoul-Henning Kamp 					continue;
32575067f4fSPoul-Henning Kamp 				}
32675067f4fSPoul-Henning Kamp 				while (*fmt != '\0' && is_digit(*fmt)) {
32775067f4fSPoul-Henning Kamp 					pi->prec *= 10;
32875067f4fSPoul-Henning Kamp 					pi->prec += to_digit(*fmt);
32975067f4fSPoul-Henning Kamp 					fmt++;
33075067f4fSPoul-Henning Kamp 				}
33175067f4fSPoul-Henning Kamp 				continue;
33275067f4fSPoul-Henning Kamp 			case '-':
33375067f4fSPoul-Henning Kamp 				pi->left = 1;
33475067f4fSPoul-Henning Kamp 				fmt++;
33575067f4fSPoul-Henning Kamp 				continue;
33675067f4fSPoul-Henning Kamp 			case '+':
33775067f4fSPoul-Henning Kamp 				pi->showsign = '+';
33875067f4fSPoul-Henning Kamp 				fmt++;
33975067f4fSPoul-Henning Kamp 				continue;
34075067f4fSPoul-Henning Kamp 			case '*':
34175067f4fSPoul-Henning Kamp 				fmt++;
34275067f4fSPoul-Henning Kamp 				pi->get_width = nextarg;
34375067f4fSPoul-Henning Kamp 				argt[nextarg++] = PA_INT;
34475067f4fSPoul-Henning Kamp 				continue;
34575067f4fSPoul-Henning Kamp 			case '%':
34675067f4fSPoul-Henning Kamp 				fmt++;
34775067f4fSPoul-Henning Kamp 				break;
34875067f4fSPoul-Henning Kamp 			case '\'':
34975067f4fSPoul-Henning Kamp 				pi->group = 1;
35075067f4fSPoul-Henning Kamp 				fmt++;
35175067f4fSPoul-Henning Kamp 				continue;
35275067f4fSPoul-Henning Kamp 			case '0':
35375067f4fSPoul-Henning Kamp 				/*-
35475067f4fSPoul-Henning Kamp 				 * ``Note that 0 is taken as a flag, not as the
35575067f4fSPoul-Henning Kamp 				 * beginning of a field width.''
35675067f4fSPoul-Henning Kamp 				 *      -- ANSI X3J11
35775067f4fSPoul-Henning Kamp 				 */
35875067f4fSPoul-Henning Kamp 				pi->pad = '0';
35975067f4fSPoul-Henning Kamp 				fmt++;
36075067f4fSPoul-Henning Kamp 				continue;
36175067f4fSPoul-Henning Kamp 			case '1': case '2': case '3':
36275067f4fSPoul-Henning Kamp 			case '4': case '5': case '6':
36375067f4fSPoul-Henning Kamp 			case '7': case '8': case '9':
36475067f4fSPoul-Henning Kamp 				n = 0;
36575067f4fSPoul-Henning Kamp 				while (*fmt != '\0' && is_digit(*fmt)) {
36675067f4fSPoul-Henning Kamp 					n *= 10;
36775067f4fSPoul-Henning Kamp 					n += to_digit(*fmt);
36875067f4fSPoul-Henning Kamp 					fmt++;
36975067f4fSPoul-Henning Kamp 				}
37075067f4fSPoul-Henning Kamp 				if (*fmt == '$') {
37175067f4fSPoul-Henning Kamp 					if (nextarg > maxarg)
37275067f4fSPoul-Henning Kamp 						maxarg = nextarg;
37375067f4fSPoul-Henning Kamp 					nextarg = n;
37475067f4fSPoul-Henning Kamp 					fmt++;
37575067f4fSPoul-Henning Kamp 				} else
37675067f4fSPoul-Henning Kamp 					pi->width = n;
37775067f4fSPoul-Henning Kamp 				continue;
37875067f4fSPoul-Henning Kamp 			case 'D':
37975067f4fSPoul-Henning Kamp 			case 'O':
38075067f4fSPoul-Henning Kamp 			case 'U':
38175067f4fSPoul-Henning Kamp 				pi->spec += ('a' - 'A');
38275067f4fSPoul-Henning Kamp 				pi->is_intmax = 0;
38375067f4fSPoul-Henning Kamp 				if (pi->is_long_double || pi->is_quad) {
38475067f4fSPoul-Henning Kamp 					pi->is_long = 0;
38575067f4fSPoul-Henning Kamp 					pi->is_long_double = 1;
38675067f4fSPoul-Henning Kamp 				} else {
38775067f4fSPoul-Henning Kamp 					pi->is_long = 1;
38875067f4fSPoul-Henning Kamp 					pi->is_long_double = 0;
38975067f4fSPoul-Henning Kamp 				}
39075067f4fSPoul-Henning Kamp 				fmt++;
39175067f4fSPoul-Henning Kamp 				break;
39275067f4fSPoul-Henning Kamp 			case 'j':
39375067f4fSPoul-Henning Kamp 				pi->is_intmax = 1;
39475067f4fSPoul-Henning Kamp 				fmt++;
39575067f4fSPoul-Henning Kamp 				continue;
39675067f4fSPoul-Henning Kamp 			case 'q':
39775067f4fSPoul-Henning Kamp 				pi->is_long = 0;
39875067f4fSPoul-Henning Kamp 				pi->is_quad = 1;
39975067f4fSPoul-Henning Kamp 				fmt++;
40075067f4fSPoul-Henning Kamp 				continue;
40175067f4fSPoul-Henning Kamp 			case 'L':
40275067f4fSPoul-Henning Kamp 				pi->is_long_double = 1;
40375067f4fSPoul-Henning Kamp 				fmt++;
40475067f4fSPoul-Henning Kamp 				continue;
40575067f4fSPoul-Henning Kamp 			case 'h':
40675067f4fSPoul-Henning Kamp 				fmt++;
40775067f4fSPoul-Henning Kamp 				if (*fmt == 'h') {
40875067f4fSPoul-Henning Kamp 					fmt++;
40975067f4fSPoul-Henning Kamp 					pi->is_char = 1;
41075067f4fSPoul-Henning Kamp 				} else {
41175067f4fSPoul-Henning Kamp 					pi->is_short = 1;
41275067f4fSPoul-Henning Kamp 				}
41375067f4fSPoul-Henning Kamp 				continue;
41475067f4fSPoul-Henning Kamp 			case 'l':
41575067f4fSPoul-Henning Kamp 				fmt++;
41675067f4fSPoul-Henning Kamp 				if (*fmt == 'l') {
41775067f4fSPoul-Henning Kamp 					fmt++;
41875067f4fSPoul-Henning Kamp 					pi->is_long_double = 1;
41975067f4fSPoul-Henning Kamp 					pi->is_quad = 0;
42075067f4fSPoul-Henning Kamp 				} else {
42175067f4fSPoul-Henning Kamp 					pi->is_quad = 0;
42275067f4fSPoul-Henning Kamp 					pi->is_long = 1;
42375067f4fSPoul-Henning Kamp 				}
42475067f4fSPoul-Henning Kamp 				continue;
42575067f4fSPoul-Henning Kamp 			case 't':
42675067f4fSPoul-Henning Kamp 				pi->is_ptrdiff = 1;
42775067f4fSPoul-Henning Kamp 				fmt++;
42875067f4fSPoul-Henning Kamp 				continue;
42975067f4fSPoul-Henning Kamp 			case 'z':
43075067f4fSPoul-Henning Kamp 				pi->is_size = 1;
43175067f4fSPoul-Henning Kamp 				fmt++;
43275067f4fSPoul-Henning Kamp 				continue;
43375067f4fSPoul-Henning Kamp 			default:
43475067f4fSPoul-Henning Kamp 				fmt++;
43575067f4fSPoul-Henning Kamp 				break;
43675067f4fSPoul-Henning Kamp 			}
43775067f4fSPoul-Henning Kamp 			if (printf_tbl[pi->spec].arginfo == NULL)
43875067f4fSPoul-Henning Kamp 				errx(1, "arginfo[%c] = NULL", pi->spec);
43975067f4fSPoul-Henning Kamp 			ch = printf_tbl[pi->spec].arginfo(
44075067f4fSPoul-Henning Kamp 			    pi, __PRINTFMAXARG, &argt[nextarg]);
44175067f4fSPoul-Henning Kamp 			if (ch > 0)
44275067f4fSPoul-Henning Kamp 				pi->arg[0] = &args[nextarg];
44375067f4fSPoul-Henning Kamp 			if (ch > 1)
44475067f4fSPoul-Henning Kamp 				pi->arg[1] = &args[nextarg + 1];
44575067f4fSPoul-Henning Kamp 			nextarg += ch;
44675067f4fSPoul-Henning Kamp 			break;
44775067f4fSPoul-Henning Kamp 		}
44875067f4fSPoul-Henning Kamp 	}
44975067f4fSPoul-Henning Kamp 	if (nextarg > maxarg)
45075067f4fSPoul-Henning Kamp 		maxarg = nextarg;
45175067f4fSPoul-Henning Kamp #if 0
45275067f4fSPoul-Henning Kamp 	fprintf(stderr, "fmt0 <%s>\n", fmt0);
45375067f4fSPoul-Henning Kamp 	fprintf(stderr, "pil %p\n", pil);
45475067f4fSPoul-Henning Kamp #endif
45575067f4fSPoul-Henning Kamp 	for (ch = 1; ch < maxarg; ch++) {
45675067f4fSPoul-Henning Kamp #if 0
45775067f4fSPoul-Henning Kamp 		fprintf(stderr, "arg %d %x\n", ch, argt[ch]);
45875067f4fSPoul-Henning Kamp #endif
45975067f4fSPoul-Henning Kamp 		switch(argt[ch]) {
46075067f4fSPoul-Henning Kamp 		case PA_CHAR:
46175067f4fSPoul-Henning Kamp 			args[ch].intarg = (char)va_arg (ap, int);
46275067f4fSPoul-Henning Kamp 			break;
46375067f4fSPoul-Henning Kamp 		case PA_INT:
46475067f4fSPoul-Henning Kamp 			args[ch].intarg = va_arg (ap, int);
46575067f4fSPoul-Henning Kamp 			break;
46675067f4fSPoul-Henning Kamp 		case PA_INT | PA_FLAG_SHORT:
46775067f4fSPoul-Henning Kamp 			args[ch].intarg = (short)va_arg (ap, int);
46875067f4fSPoul-Henning Kamp 			break;
46975067f4fSPoul-Henning Kamp 		case PA_INT | PA_FLAG_LONG:
47075067f4fSPoul-Henning Kamp 			args[ch].longarg = va_arg (ap, long);
47175067f4fSPoul-Henning Kamp 			break;
47275067f4fSPoul-Henning Kamp 		case PA_INT | PA_FLAG_INTMAX:
47375067f4fSPoul-Henning Kamp 			args[ch].intmaxarg = va_arg (ap, intmax_t);
47475067f4fSPoul-Henning Kamp 			break;
47575067f4fSPoul-Henning Kamp 		case PA_INT | PA_FLAG_QUAD:
47675067f4fSPoul-Henning Kamp 			args[ch].intmaxarg = va_arg (ap, quad_t);
47775067f4fSPoul-Henning Kamp 			break;
47875067f4fSPoul-Henning Kamp 		case PA_INT | PA_FLAG_LONG_LONG:
47975067f4fSPoul-Henning Kamp 			args[ch].intmaxarg = va_arg (ap, long long);
48075067f4fSPoul-Henning Kamp 			break;
48175067f4fSPoul-Henning Kamp 		case PA_INT | PA_FLAG_SIZE:
48275067f4fSPoul-Henning Kamp 			args[ch].intmaxarg = va_arg (ap, size_t);
48375067f4fSPoul-Henning Kamp 			break;
48475067f4fSPoul-Henning Kamp 		case PA_INT | PA_FLAG_PTRDIFF:
48575067f4fSPoul-Henning Kamp 			args[ch].intmaxarg = va_arg (ap, ptrdiff_t);
48675067f4fSPoul-Henning Kamp 			break;
48775067f4fSPoul-Henning Kamp 		case PA_WCHAR:
48875067f4fSPoul-Henning Kamp 			args[ch].wintarg = va_arg (ap, wint_t);
48975067f4fSPoul-Henning Kamp 			break;
49075067f4fSPoul-Henning Kamp 		case PA_POINTER:
49175067f4fSPoul-Henning Kamp 			args[ch].pvoidarg = va_arg (ap, void *);
49275067f4fSPoul-Henning Kamp 			break;
49375067f4fSPoul-Henning Kamp 		case PA_STRING:
49475067f4fSPoul-Henning Kamp 			args[ch].pchararg = va_arg (ap, char *);
49575067f4fSPoul-Henning Kamp 			break;
49675067f4fSPoul-Henning Kamp 		case PA_WSTRING:
49775067f4fSPoul-Henning Kamp 			args[ch].pwchararg = va_arg (ap, wchar_t *);
49875067f4fSPoul-Henning Kamp 			break;
49975067f4fSPoul-Henning Kamp 		case PA_DOUBLE:
50075239a01SPoul-Henning Kamp #ifndef NO_FLOATING_POINT
50175067f4fSPoul-Henning Kamp 			args[ch].doublearg = va_arg (ap, double);
50275239a01SPoul-Henning Kamp #endif
50375067f4fSPoul-Henning Kamp 			break;
50475067f4fSPoul-Henning Kamp 		case PA_DOUBLE | PA_FLAG_LONG_DOUBLE:
50575239a01SPoul-Henning Kamp #ifndef NO_FLOATING_POINT
50675067f4fSPoul-Henning Kamp 			args[ch].longdoublearg = va_arg (ap, long double);
50775239a01SPoul-Henning Kamp #endif
50875067f4fSPoul-Henning Kamp 			break;
50975067f4fSPoul-Henning Kamp 		default:
51075067f4fSPoul-Henning Kamp 			errx(1, "argtype = %x (fmt = \"%s\")\n",
51175067f4fSPoul-Henning Kamp 			    argt[ch], fmt0);
51275067f4fSPoul-Henning Kamp 		}
51375067f4fSPoul-Henning Kamp 	}
51475067f4fSPoul-Henning Kamp 	for (pi = pia; pi < pil; pi++) {
51575067f4fSPoul-Henning Kamp #if 0
51675067f4fSPoul-Henning Kamp 		fprintf(stderr, "pi %p", pi);
51775067f4fSPoul-Henning Kamp 		fprintf(stderr, " spec '%c'", pi->spec);
51875067f4fSPoul-Henning Kamp 		fprintf(stderr, " args %d",
51975067f4fSPoul-Henning Kamp 		    ((uintptr_t)pi->arg[0] - (uintptr_t)args) / sizeof args[0]);
52075067f4fSPoul-Henning Kamp 		if (pi->width) fprintf(stderr, " width %d", pi->width);
52175067f4fSPoul-Henning Kamp 		if (pi->pad) fprintf(stderr, " pad 0x%x", pi->pad);
52275067f4fSPoul-Henning Kamp 		if (pi->left) fprintf(stderr, " left");
52375067f4fSPoul-Henning Kamp 		if (pi->showsign) fprintf(stderr, " showsign");
52475067f4fSPoul-Henning Kamp 		if (pi->prec != -1) fprintf(stderr, " prec %d", pi->prec);
52575067f4fSPoul-Henning Kamp 		if (pi->is_char) fprintf(stderr, " char");
52675067f4fSPoul-Henning Kamp 		if (pi->is_short) fprintf(stderr, " short");
52775067f4fSPoul-Henning Kamp 		if (pi->is_long) fprintf(stderr, " long");
52875067f4fSPoul-Henning Kamp 		if (pi->is_long_double) fprintf(stderr, " long_double");
52975067f4fSPoul-Henning Kamp 		fprintf(stderr, "\n");
53075067f4fSPoul-Henning Kamp 		fprintf(stderr, "\t\"%.*s\"\n", pi->end - pi->begin, pi->begin);
53175067f4fSPoul-Henning Kamp #endif
53275067f4fSPoul-Henning Kamp 		if (pi->get_width) {
53375067f4fSPoul-Henning Kamp 			pi->width = args[pi->get_width].intarg;
53475067f4fSPoul-Henning Kamp 			/*-
53575067f4fSPoul-Henning Kamp 			 * ``A negative field width argument is taken as a
53675067f4fSPoul-Henning Kamp 			 * - flag followed by a positive field width.''
53775067f4fSPoul-Henning Kamp 			 *      -- ANSI X3J11
53875067f4fSPoul-Henning Kamp 			 * They don't exclude field widths read from args.
53975067f4fSPoul-Henning Kamp 			 */
54075067f4fSPoul-Henning Kamp 			if (pi->width < 0) {
54175067f4fSPoul-Henning Kamp 				pi->left = 1;
54275067f4fSPoul-Henning Kamp 				pi->width = -pi->width;
54375067f4fSPoul-Henning Kamp 			}
54475067f4fSPoul-Henning Kamp 		}
54575067f4fSPoul-Henning Kamp 		if (pi->get_prec)
54675067f4fSPoul-Henning Kamp 			pi->prec = args[pi->get_prec].intarg;
54775067f4fSPoul-Henning Kamp 		ret += __printf_puts(&io, pi->begin, pi->end - pi->begin);
54875067f4fSPoul-Henning Kamp 		if (printf_tbl[pi->spec].gnurender != NULL) {
54975067f4fSPoul-Henning Kamp 			__printf_flush(&io);
55075067f4fSPoul-Henning Kamp 			pi->sofar = ret;
55175067f4fSPoul-Henning Kamp 			ret += printf_tbl[pi->spec].gnurender(
55275067f4fSPoul-Henning Kamp 			    fp, pi, (const void *)pi->arg);
55375067f4fSPoul-Henning Kamp 		} else if (printf_tbl[pi->spec].render != NULL) {
55475067f4fSPoul-Henning Kamp 			pi->sofar = ret;
55575067f4fSPoul-Henning Kamp 			n = printf_tbl[pi->spec].render(
55675067f4fSPoul-Henning Kamp 			    &io, pi, (const void *)pi->arg);
55775067f4fSPoul-Henning Kamp 			if (n < 0)
55875067f4fSPoul-Henning Kamp 				io.fp->_flags |= __SERR;
55975067f4fSPoul-Henning Kamp 			else
56075067f4fSPoul-Henning Kamp 				ret += n;
56175067f4fSPoul-Henning Kamp 		} else if (pi->begin == pi->end)
56275067f4fSPoul-Henning Kamp 			errx(1, "render[%c] = NULL", *fmt);
56375067f4fSPoul-Henning Kamp 	}
56475067f4fSPoul-Henning Kamp 	__printf_flush(&io);
56575067f4fSPoul-Henning Kamp 	return (ret);
56675067f4fSPoul-Henning Kamp }
56775067f4fSPoul-Henning Kamp 
56875067f4fSPoul-Henning Kamp extern int      __fflush(FILE *fp);
56975067f4fSPoul-Henning Kamp 
57075067f4fSPoul-Henning Kamp /*
57175067f4fSPoul-Henning Kamp  * Helper function for `fprintf to unbuffered unix file': creates a
57275067f4fSPoul-Henning Kamp  * temporary buffer.  We only work on write-only files; this avoids
57375067f4fSPoul-Henning Kamp  * worries about ungetc buffers and so forth.
57475067f4fSPoul-Henning Kamp  */
57575067f4fSPoul-Henning Kamp static int
__v3printf(FILE * fp,const char * fmt,int pct,va_list ap)57675067f4fSPoul-Henning Kamp __v3printf(FILE *fp, const char *fmt, int pct, va_list ap)
57775067f4fSPoul-Henning Kamp {
57875067f4fSPoul-Henning Kamp 	int ret;
5791b0181dfSJohn Baldwin 	FILE fake = FAKE_FILE;
58075067f4fSPoul-Henning Kamp 	unsigned char buf[BUFSIZ];
58175067f4fSPoul-Henning Kamp 
58275067f4fSPoul-Henning Kamp 	/* copy the important variables */
58375067f4fSPoul-Henning Kamp 	fake._flags = fp->_flags & ~__SNBF;
58475067f4fSPoul-Henning Kamp 	fake._file = fp->_file;
58575067f4fSPoul-Henning Kamp 	fake._cookie = fp->_cookie;
58675067f4fSPoul-Henning Kamp 	fake._write = fp->_write;
5871e98f887SJohn Baldwin 	fake._orientation = fp->_orientation;
5881e98f887SJohn Baldwin 	fake._mbstate = fp->_mbstate;
58975067f4fSPoul-Henning Kamp 
59075067f4fSPoul-Henning Kamp 	/* set up the buffer */
59175067f4fSPoul-Henning Kamp 	fake._bf._base = fake._p = buf;
59275067f4fSPoul-Henning Kamp 	fake._bf._size = fake._w = sizeof(buf);
59375067f4fSPoul-Henning Kamp 	fake._lbfsize = 0;	/* not actually used, but Just In Case */
59475067f4fSPoul-Henning Kamp 
59575067f4fSPoul-Henning Kamp 	/* do the work, then copy any error status */
59675067f4fSPoul-Henning Kamp 	ret = __v2printf(&fake, fmt, pct, ap);
59775067f4fSPoul-Henning Kamp 	if (ret >= 0 && __fflush(&fake))
59875067f4fSPoul-Henning Kamp 		ret = EOF;
59975067f4fSPoul-Henning Kamp 	if (fake._flags & __SERR)
60075067f4fSPoul-Henning Kamp 		fp->_flags |= __SERR;
60175067f4fSPoul-Henning Kamp 	return (ret);
60275067f4fSPoul-Henning Kamp }
60375067f4fSPoul-Henning Kamp 
60475067f4fSPoul-Henning Kamp int
__xvprintf(FILE * fp,const char * fmt0,va_list ap)60575067f4fSPoul-Henning Kamp __xvprintf(FILE *fp, const char *fmt0, va_list ap)
60675067f4fSPoul-Henning Kamp {
60775067f4fSPoul-Henning Kamp 	unsigned u;
60875067f4fSPoul-Henning Kamp 	const char *p;
60975067f4fSPoul-Henning Kamp 
61075067f4fSPoul-Henning Kamp 	/* Count number of '%' signs handling double '%' signs */
61175067f4fSPoul-Henning Kamp 	for (p = fmt0, u = 0; *p; p++) {
61275067f4fSPoul-Henning Kamp 		if (*p != '%')
61375067f4fSPoul-Henning Kamp 			continue;
61475067f4fSPoul-Henning Kamp 		u++;
61575067f4fSPoul-Henning Kamp 		if (p[1] == '%')
61675067f4fSPoul-Henning Kamp 			p++;
61775067f4fSPoul-Henning Kamp 	}
61875067f4fSPoul-Henning Kamp 
61975067f4fSPoul-Henning Kamp 	/* optimise fprintf(stderr) (and other unbuffered Unix files) */
62075067f4fSPoul-Henning Kamp 	if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
62175067f4fSPoul-Henning Kamp 	    fp->_file >= 0)
62275067f4fSPoul-Henning Kamp 		return (__v3printf(fp, fmt0, u, ap));
62375067f4fSPoul-Henning Kamp 	else
62475067f4fSPoul-Henning Kamp 		return (__v2printf(fp, fmt0, u, ap));
62575067f4fSPoul-Henning Kamp }
62675067f4fSPoul-Henning Kamp 
62775067f4fSPoul-Henning Kamp /* extending ---------------------------------------------------------*/
62875067f4fSPoul-Henning Kamp 
62975067f4fSPoul-Henning Kamp int
register_printf_function(int spec,printf_function * render,printf_arginfo_function * arginfo)63075067f4fSPoul-Henning Kamp register_printf_function(int spec, printf_function *render, printf_arginfo_function *arginfo)
63175067f4fSPoul-Henning Kamp {
63275067f4fSPoul-Henning Kamp 
63375067f4fSPoul-Henning Kamp 	if (spec > 255 || spec < 0)
63475067f4fSPoul-Henning Kamp 		return (-1);
63575067f4fSPoul-Henning Kamp 	printf_tbl[spec].gnurender = render;
63675067f4fSPoul-Henning Kamp 	printf_tbl[spec].arginfo = arginfo;
63775067f4fSPoul-Henning Kamp 	__use_xprintf = 1;
63875067f4fSPoul-Henning Kamp 	return (0);
63975067f4fSPoul-Henning Kamp }
64075067f4fSPoul-Henning Kamp 
64175067f4fSPoul-Henning Kamp int
register_printf_render(int spec,printf_render * render,printf_arginfo_function * arginfo)64275067f4fSPoul-Henning Kamp register_printf_render(int spec, printf_render *render, printf_arginfo_function *arginfo)
64375067f4fSPoul-Henning Kamp {
64475067f4fSPoul-Henning Kamp 
64575067f4fSPoul-Henning Kamp 	if (spec > 255 || spec < 0)
64675067f4fSPoul-Henning Kamp 		return (-1);
64775067f4fSPoul-Henning Kamp 	printf_tbl[spec].render = render;
64875067f4fSPoul-Henning Kamp 	printf_tbl[spec].arginfo = arginfo;
64975067f4fSPoul-Henning Kamp 	__use_xprintf = 1;
65075067f4fSPoul-Henning Kamp 	return (0);
65175067f4fSPoul-Henning Kamp }
65275067f4fSPoul-Henning Kamp 
65375067f4fSPoul-Henning Kamp int
register_printf_render_std(const char * specs)654988a521bSPawel Jakub Dawidek register_printf_render_std(const char *specs)
65575067f4fSPoul-Henning Kamp {
65675067f4fSPoul-Henning Kamp 
65775067f4fSPoul-Henning Kamp 	for (; *specs != '\0'; specs++) {
65875067f4fSPoul-Henning Kamp 		switch (*specs) {
65975067f4fSPoul-Henning Kamp 		case 'H':
66075067f4fSPoul-Henning Kamp 			register_printf_render(*specs,
66175067f4fSPoul-Henning Kamp 			    __printf_render_hexdump,
66275067f4fSPoul-Henning Kamp 			    __printf_arginfo_hexdump);
66375067f4fSPoul-Henning Kamp 			break;
6646dbacee2SPoul-Henning Kamp 		case 'M':
6656dbacee2SPoul-Henning Kamp 			register_printf_render(*specs,
6666dbacee2SPoul-Henning Kamp 			    __printf_render_errno,
6676dbacee2SPoul-Henning Kamp 			    __printf_arginfo_errno);
6686dbacee2SPoul-Henning Kamp 			break;
6696dbacee2SPoul-Henning Kamp 		case 'Q':
6706dbacee2SPoul-Henning Kamp 			register_printf_render(*specs,
6716dbacee2SPoul-Henning Kamp 			    __printf_render_quote,
6726dbacee2SPoul-Henning Kamp 			    __printf_arginfo_quote);
6736dbacee2SPoul-Henning Kamp 			break;
67475067f4fSPoul-Henning Kamp 		case 'T':
67575067f4fSPoul-Henning Kamp 			register_printf_render(*specs,
67675067f4fSPoul-Henning Kamp 			    __printf_render_time,
67775067f4fSPoul-Henning Kamp 			    __printf_arginfo_time);
67875067f4fSPoul-Henning Kamp 			break;
67975067f4fSPoul-Henning Kamp 		case 'V':
68075067f4fSPoul-Henning Kamp 			register_printf_render(*specs,
68175067f4fSPoul-Henning Kamp 			    __printf_render_vis,
68275067f4fSPoul-Henning Kamp 			    __printf_arginfo_vis);
68375067f4fSPoul-Henning Kamp 			break;
68475067f4fSPoul-Henning Kamp 		default:
68575067f4fSPoul-Henning Kamp 			return (-1);
68675067f4fSPoul-Henning Kamp 		}
68775067f4fSPoul-Henning Kamp 	}
68875067f4fSPoul-Henning Kamp 	return (0);
68975067f4fSPoul-Henning Kamp }
69075067f4fSPoul-Henning Kamp 
691