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