Loading...
--- 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 */