Loading...
stdio/FreeBSD/xprintf.c Libc-1725.40.4 /dev/null
--- Libc/Libc-1725.40.4/stdio/FreeBSD/xprintf.c
+++ /dev/null
@@ -1,1210 +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: src/lib/libc/stdio/xprintf.c,v 1.9 2010/03/11 17:03:32 jhb Exp $
- */
-
-#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 <errno.h>
-#include "un-namespace.h"
-
-//#define MACHTIME
-#ifdef MACHTIME
-#include <mach/mach_time.h>
-#endif // MACHTIME
-
-#ifdef XPRINTF_PERF
-#include <libkern/OSAtomic.h>
-#endif /* XPRINTF_PERF */
-
-#include "local.h"
-#include "xprintf_private.h"
-#include "xprintf_domain.h"
-#include "fvwrite.h"
-#include "libc_hooks_impl.h"
-
-/*
- * Defining XPRINTF_DEBUG allows the __private_extern__ variable __use_xprintf
- * to be set so that regular printf variants will use the extensible printf
- * code path.  This is normally off, and is only used to test the extensible
- * printf code in the conformance tests.
- */
-#ifdef XPRINTF_DEBUG
-#include <unistd.h>
-int __use_xprintf = 0;
-#endif
-
-/* 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;
-#ifdef VECTORS
-	VECTORTYPE		vectorarg;
-	unsigned char		vuchararg[16];
-	signed char		vchararg[16];
-	unsigned short		vushortarg[8];
-	signed short		vshortarg[8];
-	unsigned int		vuintarg[4];
-	signed int		vintarg[4];
-	float			vfloatarg[4];
-#ifdef V64TYPE
-	double			vdoublearg[2];
-	unsigned long long	vulonglongarg[2];
-	long long		vlonglongarg[2];
-#endif /* V64TYPE */
-#endif /* VECTORS */
-};
-
-/*
- * 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 ---------------------------------------------------*/
-
-__private_extern__ const char __lowercase_hex[17] = "0123456789abcdef?";	/*lint !e784 */
-__private_extern__ 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;
-}
-
-__private_extern__ void
-__printf_flush(struct __printf_io *io)
-{
-
-	__sfvwrite(io->fp, &io->uio);
-	__printf_init(io);
-}
-
-__private_extern__ int
-__printf_puts(struct __printf_io *io, const void *ptr, int len)
-{
-
-
-#if 0
-	if (io->fp->_flags & __SERR)
-		return (0);
-#endif
-	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);
-}
-
-__private_extern__ 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);
-}
-
-__private_extern__ 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  -------------------------------------------------*/
-
-__private_extern__ int
-__printf_arginfo_pct(const struct printf_info *pi __unused, size_t n __unused, int *argt __unused)
-{
-
-	return (0);
-}
-
-__private_extern__ 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' ---------------------------------------------------------------*/
-
-__private_extern__ 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.
- */
-
-__private_extern__ int
-__printf_render_n(FILE *io __unused, const struct printf_info *pi, const void *const *arg)
-{
-	void *ptr = (void*)arg[0];
-	if (pi->is_char) {
-		LIBC_HOOKS_WRITE_SIMPLE_TYPE(ptr, signed char, pi->sofar);
-	} else if (pi->is_short) {
-		LIBC_HOOKS_WRITE_SIMPLE_TYPE(ptr, short, pi->sofar);
-	} else if (pi->is_long) {
-		LIBC_HOOKS_WRITE_SIMPLE_TYPE(ptr, long, pi->sofar);
-	} else if (pi->is_long_double) {
-		LIBC_HOOKS_WRITE_SIMPLE_TYPE(ptr, long long, pi->sofar);
-	} else if (pi->is_intmax) {
-		LIBC_HOOKS_WRITE_SIMPLE_TYPE(ptr, intmax_t, pi->sofar);
-	} else if (pi->is_ptrdiff) {
-		LIBC_HOOKS_WRITE_SIMPLE_TYPE(ptr, ptrdiff_t, pi->sofar);
-	} else if (pi->is_quad) {
-		LIBC_HOOKS_WRITE_SIMPLE_TYPE(ptr, quad_t, pi->sofar);
-	} else if (pi->is_size) {
-		LIBC_HOOKS_WRITE_SIMPLE_TYPE(ptr, size_t, pi->sofar);
-	} else {
-		LIBC_HOOKS_WRITE_SIMPLE_TYPE(ptr, int, pi->sofar);
-	}
-
-	return (0);
-}
-
-/* dynamic array handling  -------------------------------------------------*/
-#define ARRAYDELTA 8
-
-struct array {
-#ifdef XPRINTF_PERF
-	struct array *next;
-#endif /* XPRINTF_PERF */
-	void *data;
-	int itemsize;
-	int max;
-};
-
-#ifdef XPRINTF_PERF
-__private_extern__
-#else /* !XPRINTF_PERF */
-static
-#endif /* !XPRINTF_PERF */
-void
-arrayfree(struct array *a)
-{
-	if(a) free(a->data);
-}
-
-static void *
-arrayget(struct array *a, int i)
-{
-	if (i >= a->max) {
-		int oldsize = a->max * a->itemsize;
-		int newmax = i + ARRAYDELTA;
-		int newsize = newmax * a->itemsize;
-		void *newdata = realloc(a->data, newsize);
-		if(!newdata) return NULL;
-		bzero(newdata + oldsize, newsize - oldsize);
-		a->data = newdata;
-		a->max = newmax;
-	}
-	return a->data + i * a->itemsize;
-}
-
-static struct array *
-arrayinit(struct array *a, int itemsize)
-{
-	a->data = CALLOC(ARRAYDELTA, itemsize);
-	if(!a->data) return NULL;
-	a->itemsize = itemsize;
-	a->max = ARRAYDELTA;
-	return a;
-}
-
-/* dynamic array caching  -------------------------------------------------*/
-/*
- * Normally, dynamic array structures are created on the stack, and array
- * itself is freshly allocated, and then freed when no longer needed.  When
- * the XPRINTF_PERF macro is defined, the dynamic array structures associated
- * with all-in-one printf variants are not freed, but store in a cache for
- * later use (dynamic array structures used for compile/execute continue to
- * be freed after they are no longer needed).  This means there should be
- * at most one structure in the cached per thread that actually used the
- * all-in-one printf variant.
- *
- * The amount of memory that is cached is fairly small, totally about 1K
- * for three structures used by a format string using ten conversion
- * specifiers.  This is too small for purgeable memory.
- *
- * However, we do flush these caches in case we every are unable to allocate
- * memory, and retry the allocation, just in case.
- */
-#ifdef XPRINTF_PERF
-static OSQueueHead arg_type_queue = OS_ATOMIC_QUEUE_INIT;
-static OSQueueHead printf_info_queue = OS_ATOMIC_QUEUE_INIT;
-static OSQueueHead union_arg_queue = OS_ATOMIC_QUEUE_INIT;
-
-#define DEFINE_DEQUEUE(which, type) \
-static struct array * \
-which ## _dequeue(void) \
-{ \
-	struct array *a = (struct array *)OSAtomicDequeue(&which ## _queue, offsetof(struct array, next)); \
- \
-	if (a) { \
-		bzero(a->data, a->max * a->itemsize); \
-		return a; \
-	} \
-	a = (struct array *)MALLOC(sizeof(*a)); \
-	if (!a) return NULL; \
-	if (!arrayinit(a, sizeof(type))) { \
-		free(a); \
-		return NULL; \
-	} \
-	return a; \
-}
-
-#define DEFINE_ENQUEUE(which) \
-__private_extern__ void \
-which ## _enqueue(struct array *a) \
-{ \
-	if (!a) return; \
-	OSAtomicEnqueue(&which ## _queue, a, offsetof(struct array, next)); \
-}
-
-#define DEFINE_FLUSH(which) \
-static void \
-which ## _flush(void) \
-{ \
-	struct array *a; \
-	while((a = (struct array *)OSAtomicDequeue(&which ## _queue, offsetof(struct array, next))) != NULL) { \
-		arrayfree(a); \
-		free(a); \
-	} \
-}
-
-DEFINE_DEQUEUE(arg_type, int)
-DEFINE_ENQUEUE(arg_type)
-DEFINE_FLUSH(arg_type)
-DEFINE_DEQUEUE(printf_info, struct printf_info)
-DEFINE_ENQUEUE(printf_info)
-DEFINE_FLUSH(printf_info)
-DEFINE_DEQUEUE(union_arg, union arg)
-DEFINE_ENQUEUE(union_arg)
-DEFINE_FLUSH(union_arg)
-
-static void
-flush_queues(void)
-{
-    arg_type_flush();
-    printf_info_flush();
-    union_arg_flush();
-}
-
-__private_extern__ void *
-xprintf_calloc(size_t count, size_t size)
-{
-    void *x = calloc(count, size);
-    if(!x) {
-	flush_queues();
-	x = calloc(count, size);
-    }
-    return x;
-}
-
-__private_extern__ void *
-xprintf_malloc(size_t size)
-{
-    void *x = malloc(size);
-    if(!x) {
-	flush_queues();
-	x = malloc(size);
-    }
-    return x;
-}
-
-#if 0
-void
-show_queues(void)
-{
-    struct array *a;
-    printf("arg_type:");
-    while((a = (struct array *)OSAtomicDequeue(&arg_type_queue, offsetof(struct array, next))) != NULL) printf("\n%p", a);
-    printf("\nprintf_info:");
-    while((a = (struct array *)OSAtomicDequeue(&printf_info_queue, offsetof(struct array, next))) != NULL) printf("\n%p", a);
-    printf("\nunion_arg:");
-    while((a = (struct array *)OSAtomicDequeue(&union_arg_queue, offsetof(struct array, next))) != NULL) printf("\n%p", a);
-    printf("\n");
-}
-#endif
-#endif /* XPRINTF_PERF */
-
-/* -------------------------------------------------------------------------*/
-
-__private_extern__ int
-__printf_comp(printf_comp_t restrict pc, printf_domain_t restrict domain)
-{
-	struct printf_info	*pi, *pil;
-	const char		*fmt;
-	int			ch, pii;
-	int			*argt;
-	int			nextarg;
-	int			maxarg;
-	int			ret = 0;
-	int			n;
-#ifndef XPRINTF_PERF
-	struct array		piarr, argtarr;
-#endif /* XPRINTF_PERF */
-	struct array		*pa, *aa;
-
-	fmt = pc->fmt;
-	maxarg = 0;
-	nextarg = 1;
-#ifdef XPRINTF_PERF
-	pa = printf_info_dequeue();
-#else /* !XPRINTF_PERF */
-	pa = arrayinit(&piarr, sizeof(*pi));
-#endif /* !XPRINTF_PERF */
-	if (!pa) {
-#ifdef XPRINTF_PERF
-	    flush_queues();
-#endif /* XPRINTF_PERF */
-	    return EOF;
-	}
-#ifdef XPRINTF_PERF
-	pc->pa = pa;
-	aa = arg_type_dequeue();
-#else /* !XPRINTF_PERF */
-	aa = arrayinit(&argtarr, sizeof(*argt));
-#endif /* !XPRINTF_PERF */
-	if (!aa) {
-		arrayfree(pa);
-#ifdef XPRINTF_PERF
-		free(pa);
-		flush_queues();
-#endif /* XPRINTF_PERF */
-		return EOF;
-	}
-#ifdef XPRINTF_PERF
-	pc->aa = aa;
-#endif /* XPRINTF_PERF */
-	for (pii = 0; ; pii++) {
-		pi = arrayget(pa, pii);
-		if (!pi) {
-			ret = EOF;
-			goto error;
-		}
-		pil = pi;
-		if (*fmt == '\0')
-			break;
-		pil = pi + 1;
-		pi->prec = -1;
-		pi->pad = ' ';
-#ifdef VECTORS
-		pi->vsep = 'X'; /* Illegal value, changed to defaults later. */
-#endif /* VECTORS */
-		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->space = 1;
-					pi->signchar = ' ';
-				}
-				fmt++;
-				continue;
-			case '#':
-				pi->alt = 1;
-				fmt++;
-				continue;
-#ifdef VECTORS
-			case ',': case ';': case ':': case '_':
-				pi->vsep = pi->spec;
-				fmt++;
-				continue;
-#endif /* VECTORS */
-			case '.':
-				pi->prec = 0;
-				fmt++;
-				if (*fmt == '*') {
-					fmt++;
-					/* Look for *nn$ and deal with it */
-					n = 0;
-					while (*fmt != '\0' && is_digit(*fmt)) {
-						n *= 10;
-						n += to_digit(*fmt);
-						fmt++;
-					}
-					if (*fmt == '$') {
-						if ((n + 1) > maxarg)
-							maxarg = (n + 1);
-						fmt++;
-					} else n = nextarg++;
-					pi->get_prec = n;
-					argt = (int *)arrayget(aa, n);
-					if (!argt) {
-						ret = EOF;
-						goto error;
-					}
-					*argt = 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 = 1;
-				pi->signchar = '+';
-				fmt++;
-				continue;
-			case '*':
-				fmt++;
-				/* Look for *nn$ and deal with it */
-				n = 0;
-				while (*fmt != '\0' && is_digit(*fmt)) {
-					n *= 10;
-					n += to_digit(*fmt);
-					fmt++;
-				}
-				if (*fmt == '$') {
-					if ((n + 1) > maxarg)
-						maxarg = (n + 1);
-					fmt++;
-				} else n = nextarg++;
-				pi->get_width = n;
-				argt = (int *)arrayget(aa, n);
-				if (!argt) {
-					ret = EOF;
-					goto error;
-				}
-				*argt = 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;
-#if 0
-			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;
-#endif
-			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 'v':
-#ifdef VECTORS
-				pi->is_vec = 1;
-#endif /* VECTORS */
-				fmt++;
-				continue;
-			case 'z':
-				pi->is_size = 1;
-				fmt++;
-				continue;
-			default:
-				fmt++;
-				break;
-			}
-			if (printf_tbl_in_range(pi->spec)) {
-				switch(domain->type[printf_tbl_index(pi->spec)]) {
-				/* ignore PRINTF_DOMAIN_UNUSED until later */
-				case PRINTF_DOMAIN_FLAG:
-					errx(1, "Unexpected flag: %c", pi->spec);
-				case PRINTF_DOMAIN_GLIBC_API:
-				case PRINTF_DOMAIN_FBSD_API:
-					/*
-					 * Insure that there are always
-					 * __PRINTFMAXARG available.
-					 */
-					if (!arrayget(aa, nextarg + __PRINTFMAXARG - 1)) {
-						ret = EOF;
-						goto error;
-					}
-					pi->context = domain->tbl[printf_tbl_index(pi->spec)].context;
-					pi->loc = pc->loc;
-					ch = domain->tbl[printf_tbl_index(pi->spec)].arginfo(
-					    pi, __PRINTFMAXARG, arrayget(aa, nextarg));
-					if (ch > 0)
-						pi->arg[0] = (void *)(long)nextarg;
-					if (ch > 1)
-						pi->arg[1] = (void *)(long)(nextarg + 1);
-					nextarg += ch;
-					break;
-				}
-			}
-			break;
-		}
-	}
-	if (nextarg > maxarg)
-		maxarg = nextarg;
-	pc->argt = aa->data;
-	pc->pi = pa->data;
-	pc->pil = pil;
-	pc->maxarg = ch = maxarg;
-	if (ch < 1) ch = 1;
-#ifdef XPRINTF_PERF
-	pc->ua = union_arg_dequeue();
-	if (!pc->ua) {
-	    ret = EOF;
-	    goto error;
-	}
-	if (!arrayget(pc->ua, ch)) {
-	    union_arg_enqueue(pc->ua);
-	    ret = EOF;
-	    goto error;
-	}
-	pc->args = pc->ua->data;
-#else /* !XPRINTF_PERF */
-	pc->args = (union arg *)malloc(ch * sizeof(*pc->args));
-	if (!pc->args) {
-		ret = EOF;
-		goto error;
-	}
-#endif /* !XPRINTF_PERF */
-	for (pi = pc->pi; pi < pil; pi++) {
-		if (pi->arg[0]) pi->arg[0] = &pc->args[(long)pi->arg[0]];
-		if (pi->arg[1]) pi->arg[1] = &pc->args[(long)pi->arg[1]];
-	}
-#if 0
-	fprintf(stderr, "fmt0 <%s>\n", fmt0);
-	fprintf(stderr, "pil %p\n", pil);
-#endif
-	pc->domain = domain;
-
-	return (ret);
-error:
-	arrayfree(pa);
-	arrayfree(aa);
-#ifdef XPRINTF_PERF
-	free(pa);
-	free(aa);
-	flush_queues();
-#endif /* XPRINTF_PERF */
-	return (ret);
-}
-
-__private_extern__ int
-__printf_exec(printf_comp_t restrict pc, FILE * restrict fp, va_list ap)
-{
-	struct printf_info	*pi;
-	int			ch;
-	int			ret = 0;
-	int			n;
-	struct __printf_io	io;
-
-	__printf_init(&io);
-	io.fp = fp;
-
-	for (ch = 1; ch < pc->maxarg; ch++) {
-#if 0
-		fprintf(stderr, "arg %d %x\n", ch, pc->argt[ch]);
-#endif
-		switch(pc->argt[ch]) {
-		case PA_CHAR:
-			pc->args[ch].intarg = (char)va_arg (ap, int);
-			break;
-		case PA_INT:
-			pc->args[ch].intarg = va_arg (ap, int);
-			break;
-		case PA_INT | PA_FLAG_SHORT:
-			pc->args[ch].intarg = (short)va_arg (ap, int);
-			break;
-		case PA_INT | PA_FLAG_LONG:
-			pc->args[ch].longarg = va_arg (ap, long);
-			break;
-		case PA_INT | PA_FLAG_INTMAX:
-			pc->args[ch].intmaxarg = va_arg (ap, intmax_t);
-			break;
-		case PA_INT | PA_FLAG_QUAD:
-			pc->args[ch].intmaxarg = va_arg (ap, quad_t);
-			break;
-		case PA_INT | PA_FLAG_LONG_LONG:
-			pc->args[ch].intmaxarg = va_arg (ap, long long);
-			break;
-		case PA_INT | PA_FLAG_SIZE:
-			pc->args[ch].intmaxarg = va_arg (ap, size_t);
-			break;
-		case PA_INT | PA_FLAG_PTRDIFF:
-			pc->args[ch].intmaxarg = (unsigned long)va_arg (ap, ptrdiff_t);
-			break;
-		case PA_WCHAR:
-			pc->args[ch].wintarg = va_arg (ap, wint_t);
-			break;
-		case PA_POINTER:
-			pc->args[ch].pvoidarg = va_arg (ap, void *);
-			break;
-		case PA_STRING: {
-			char *s = va_arg(ap, char *);
-			libc_hooks_will_read_cstring(s);
-			pc->args[ch].pchararg = s;
-			break;
-		}
-		case PA_WSTRING: {
-			wchar_t *wcs = va_arg(ap, wchar_t *);
-			libc_hooks_will_read_wcstring(wcs);
-			pc->args[ch].pwchararg = wcs;
-			break;
-		}
-		case PA_DOUBLE:
-#ifndef NO_FLOATING_POINT
-			pc->args[ch].doublearg = va_arg (ap, double);
-#endif
-			break;
-		case PA_DOUBLE | PA_FLAG_LONG_DOUBLE:
-#ifndef NO_FLOATING_POINT
-			pc->args[ch].longdoublearg = va_arg (ap, long double);
-#endif
-			break;
-#ifdef VECTORS
-		case PA_VECTOR:
-			pc->args[ch].vectorarg = va_arg (ap, VECTORTYPE);
-			break;
-#endif /* VECTORS */
-		default:
-			errx(1, "argtype = %x (fmt = \"%s\")\n",
-			    pc->argt[ch], pc->fmt);
-		}
-	}
-	for (pi = pc->pi; pi < pc->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)pc->args) / sizeof pc->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->signchar) fprintf(stderr, " signchar 0x%x", pi->signchar);
-		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 = pc->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 = pc->args[pi->get_prec].intarg;
-		ret += __printf_puts(&io, pi->begin, pi->end - pi->begin);
-		if (pi->spec) {
-			if (!printf_tbl_in_range(pi->spec)) goto unused;
-			switch(pc->domain->type[printf_tbl_index(pi->spec)]) {
-			case PRINTF_DOMAIN_UNUSED:
-		unused:
-			{
-				char unknown = pi->spec;
-				ret += __printf_out(&io, pi, &unknown, 1);
-				break;
-			}
-			case PRINTF_DOMAIN_GLIBC_API:
-				__printf_flush(&io);
-				pi->sofar = ret;
-				ret += ((printf_function *)pc->domain->tbl[printf_tbl_index(pi->spec)].render)(
-				    fp, pi, (const void *)pi->arg);
-				break;
-			case PRINTF_DOMAIN_FBSD_API:
-				pi->sofar = ret;
-				n = ((printf_render *)pc->domain->tbl[printf_tbl_index(pi->spec)].render)(
-				    &io, pi, (const void *)pi->arg);
-				if (n < 0)
-					io.fp->_flags |= __SERR;
-				else
-					ret += n;
-				break;
-			}
-		}
-	}
-	__printf_flush(&io);
-	return (ret);
-}
-
-__private_extern__ int
-__v2printf(printf_comp_t restrict pc, printf_domain_t restrict domain, FILE * restrict fp, locale_t restrict loc, const char * restrict fmt, va_list ap)
-{
-	struct _printf_compiled spc;
-	int ret, saverrno;
-
-	libc_hooks_will_read(loc, sizeof(*loc));
-	libc_hooks_will_read_cstring(fmt);
-
-	/*
-	 * All the printf family (including extensible printf variants) funnel
-	 * down to this point.  So we can do common work here, and then fork
-	 * out to the appropriate handler.
-	 */
-	/* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
-	if (prepwrite(fp) != 0) {
-		errno = EBADF;
-		return (EOF);
-	}
-	ORIENT(fp, -1);
-
-	if (pc == XPRINTF_PLAIN) {
-		NORMALIZE_LOCALE(loc);
-#ifdef XPRINTF_DEBUG
-		if (!__use_xprintf)
-#endif
-				    return __vfprintf(fp, loc, fmt, ap);
-#ifdef XPRINTF_DEBUG
-		xprintf_domain_init();
-		domain = xprintf_domain_global;
-#endif
-	} else if (pc) {
-	    pthread_mutex_lock(&pc->mutex);
-	    pthread_rwlock_rdlock(&pc->domain->rwlock);
-	    ret = __printf_exec(pc, fp, ap);
-	    saverrno = errno;
-	    pthread_rwlock_unlock(&pc->domain->rwlock);
-	    pthread_mutex_unlock(&pc->mutex);
-	    errno = saverrno;
-	    return ret;
-	}
-	if (!domain) {
-		errno = EINVAL;
-		return EOF;
-	}
-	xprintf_domain_init();
-	bzero(&spc, sizeof(spc));
-	spc.fmt = fmt;
-	DEFAULT_CURRENT_LOCALE(loc);
-	xlocale_retain(loc);
-	spc.loc = loc;
-	/*
-	 * We don't need to lock the printf_comp_t mutex, since the
-	 * printf_comp_t was just created on the stack, and is private.
-	 */
-	pthread_rwlock_rdlock(&domain->rwlock);
-	if (__printf_comp(&spc, domain) < 0) {
-	    saverrno = errno;
-	    pthread_rwlock_unlock(&domain->rwlock);
-	    xlocale_release(loc);
-	    errno = saverrno;
-	    return EOF;
-	}
-	ret = __printf_exec(&spc, fp, ap);
-	saverrno = errno;
-	pthread_rwlock_unlock(&domain->rwlock);
-	xlocale_release(loc);
-
-#ifdef XPRINTF_PERF
-	printf_info_enqueue(spc.pa);
-	arg_type_enqueue(spc.aa);
-	union_arg_enqueue(spc.ua);
-#else /* !XPRINTF_PERF */
-	free(spc.pi);
-	free(spc.argt);
-	free(spc.args);
-#endif /* !XPRINTF_PERF */
-	errno = saverrno;
-	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(printf_comp_t restrict pc, printf_domain_t restrict domain, FILE * restrict fp, locale_t restrict loc, const char * restrict fmt, va_list ap)
-{
-	int ret;
-	FILE fake;
-	struct __sFILEX extra;
-	unsigned char buf[BUFSIZ];
-
-	fake._extra = &extra;
-	INITEXTRA(&fake);
-
-	/* 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(pc, domain, &fake, loc, fmt, ap);
-	if (ret >= 0 && __fflush(&fake))
-		ret = EOF;
-	if (fake._flags & __SERR)
-		fp->_flags |= __SERR;
-	return (ret);
-}
-
-__private_extern__ int
-__xvprintf(printf_comp_t restrict pc, printf_domain_t restrict domain, FILE * restrict fp, locale_t restrict loc, const char * restrict fmt0, va_list ap)
-{
-	int ret;
-
-	/* optimise fprintf(stderr) (and other unbuffered Unix files) */
-	if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
-	    fp->_file >= 0)
-		ret = __v3printf(pc, domain, fp, loc, fmt0, ap);
-	else
-		ret = __v2printf(pc, domain, fp, loc, fmt0, ap);
-	return ret;
-}
-
-/* extending ---------------------------------------------------------*/
-
-// No global domain support
-#if 0
-int
-register_printf_function(int spec, printf_function *render, printf_arginfo_function *arginfo)
-{
-	return register_printf_domain_function(NULL, spec, render, arginfo);
-}
-
-__private_extern__ int
-register_printf_render(int spec, printf_render *render, printf_arginfo_function *arginfo)
-{
-	return register_printf_domain_render(NULL, spec, render, arginfo);
-}
-
-int
-register_printf_render_std(const char *specs)
-{
-	return register_printf_domain_render_std(NULL, specs);
-}
-#endif
-
-#ifdef VECTORS
-/* vector support ----------------------------------------------------*/
-
-#define PRINTVECTOR(_io, _pi, _arg, _cnt, _type, _elem, _render, _ret) { \
-	int i; \
-	_type a, *ap; \
-	a = (_type)(_arg)->_elem[0]; \
-	ap = &a; \
-	(_ret) += _render((_io), (_pi), (const void *)&ap); \
-	for(i = 1; i < (_cnt); i++) { \
-		(_ret) += __printf_puts((_io), (_pi)->begin, (_pi)->end - (_pi)->begin); \
-		a = (_type)(_arg)->_elem[i]; \
-		(_ret) += _render((_io), (_pi), (const void *)&ap); \
-	} \
-}
-
-#define PRINTVECTOR_P(_io, _pi, _arg, _cnt, _elem, _render, _ret) { \
-	int i; \
-	void * a, *ap; \
-	a = (void *)(uintptr_t)(_arg)->_elem[0]; \
-	ap = &a; \
-	(_ret) += _render((_io), (_pi), (const void *)&ap); \
-	for(i = 1; i < (_cnt); i++) { \
-		(_ret) += __printf_puts((_io), (_pi)->begin, (_pi)->end - (_pi)->begin); \
-		a = (void *)(uintptr_t)(_arg)->_elem[i]; \
-		(_ret) += _render((_io), (_pi), (const void *)&ap); \
-	} \
-}
-
-__private_extern__ int
-__xprintf_vector(struct __printf_io *io, const struct printf_info *pi, const void *const *arg)
-{
-	char vsep;	/* Vector separator character. */
-	const union arg *argp;
-	int ret = 0;
-	struct printf_info info = *pi;
-
-	argp = arg[0];
-	vsep = pi->vsep;
-	if (vsep == 'X') {
-		if (pi->spec == 'c')
-			vsep = '\0';
-		else
-			vsep = ' ';
-	}
-	info.begin = info.end = &vsep;
-	if (vsep) info.end++;
-	info.is_vec = 0;
-
-	if (pi->is_short) {
-		if (pi->spec == 'p') {
-			PRINTVECTOR_P(io, &info, argp, 8, vushortarg, __printf_render_ptr, ret);
-		} else {
-			PRINTVECTOR(io, &info, argp, 8, unsigned int, vushortarg, __printf_render_int, ret);
-		}
-	} else if (pi->is_long) {
-		info.is_long = 0;
-		if (pi->spec == 'p') {
-			PRINTVECTOR_P(io, &info, argp, 4, vuintarg, __printf_render_ptr, ret);
-		} else {
-			PRINTVECTOR(io, &info, argp, 4, unsigned int, vuintarg, __printf_render_int, ret);
-		}
-#ifdef V64TYPE
-	} else if (pi->is_long_double) {
-		switch (pi->spec) {
-		case 'a':
-		case 'A':
-		case 'e':
-		case 'E':
-		case 'f':
-		case 'g':
-		case 'G':
-			info.is_long_double = 0;
-			PRINTVECTOR(io, &info, argp, 2, double, vdoublearg, __printf_render_float, ret);
-			break;
-		case 'p':
-			info.is_long_double = 0;
-			PRINTVECTOR_P(io, &info, argp, 2, vulonglongarg, __printf_render_ptr, ret);
-			break;
-		case 'd':
-		case 'i':
-		case 'u':
-		case 'o':
-		case 'x':
-		case 'X':
-			PRINTVECTOR(io, &info, argp, 2, unsigned long long, vulonglongarg, __printf_render_int, ret);
-			break;
-		default:
-			/*
-			 * The default case should never
-			 * happen.
-			 */
-		case 'c':
-			info.is_long_double = 0;
-			PRINTVECTOR(io, &info, argp, 16, unsigned int, vuchararg, __printf_render_chr, ret);
-		}
-#endif /* V64TYPE */
-	} else {
-		switch (pi->spec) {
-		case 'a':
-		case 'A':
-		case 'e':
-		case 'E':
-		case 'f':
-		case 'g':
-		case 'G':
-			PRINTVECTOR(io, &info, argp, 4, double, vfloatarg, __printf_render_float, ret);
-			break;
-		default:
-			/*
-			 * The default case should never
-			 * happen.
-			 */
-		case 'p':
-			PRINTVECTOR_P(io, &info, argp, 16, vuchararg, __printf_render_ptr, ret);
-			break;
-		case 'd':
-		case 'i':
-		case 'u':
-		case 'o':
-		case 'x':
-		case 'X':
-			info.is_char = 1;
-			PRINTVECTOR(io, &info, argp, 16, unsigned int, vuchararg, __printf_render_int, ret);
-			break;
-		case 'c':
-			PRINTVECTOR(io, &info, argp, 16, unsigned int, vuchararg, __printf_render_chr, ret);
-		}
-	}
-	return ret;
-}
-#endif /* VECTORS */