1153486Sphk/*- 2153486Sphk * Copyright (c) 2005 Poul-Henning Kamp 3153486Sphk * Copyright (c) 1990, 1993 4153486Sphk * The Regents of the University of California. All rights reserved. 5153486Sphk * 6153486Sphk * This code is derived from software contributed to Berkeley by 7153486Sphk * Chris Torek. 8153486Sphk * 9153486Sphk * Redistribution and use in source and binary forms, with or without 10153486Sphk * modification, are permitted provided that the following conditions 11153486Sphk * are met: 12153486Sphk * 1. Redistributions of source code must retain the above copyright 13153486Sphk * notice, this list of conditions and the following disclaimer. 14153486Sphk * 2. Redistributions in binary form must reproduce the above copyright 15153486Sphk * notice, this list of conditions and the following disclaimer in the 16153486Sphk * documentation and/or other materials provided with the distribution. 17153486Sphk * 3. Neither the name of the University nor the names of its contributors 18153486Sphk * may be used to endorse or promote products derived from this software 19153486Sphk * without specific prior written permission. 20153486Sphk * 21153486Sphk * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22153486Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23153486Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24153486Sphk * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25153486Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26153486Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27153486Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28153486Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29153486Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30153486Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31153486Sphk * SUCH DAMAGE. 32153486Sphk * 33153486Sphk * $FreeBSD$ 34153486Sphk */ 35153486Sphk 36178721Sjhb#include "namespace.h" 37153486Sphk#include <err.h> 38153486Sphk#include <sys/types.h> 39153486Sphk#include <stdio.h> 40153486Sphk#include <stddef.h> 41153486Sphk#include <stdlib.h> 42153486Sphk#include <locale.h> 43153486Sphk#include <stdint.h> 44153486Sphk#include <assert.h> 45153486Sphk#include <stdarg.h> 46153486Sphk#include <namespace.h> 47153486Sphk#include <string.h> 48153486Sphk#include <wchar.h> 49178721Sjhb#include "un-namespace.h" 50153486Sphk 51205021Sjhb#include "local.h" 52153486Sphk#include "printf.h" 53153486Sphk#include "fvwrite.h" 54153486Sphk 55153486Sphkint __use_xprintf = -1; 56153486Sphk 57153486Sphk/* private stuff -----------------------------------------------------*/ 58153486Sphk 59153486Sphkunion arg { 60153486Sphk int intarg; 61153486Sphk long longarg; 62153486Sphk intmax_t intmaxarg; 63153486Sphk#ifndef NO_FLOATING_POINT 64153486Sphk double doublearg; 65153486Sphk long double longdoublearg; 66153486Sphk#endif 67153486Sphk wint_t wintarg; 68153486Sphk char *pchararg; 69153486Sphk wchar_t *pwchararg; 70153486Sphk void *pvoidarg; 71153486Sphk}; 72153486Sphk 73153486Sphk/* 74153486Sphk * Macros for converting digits to letters and vice versa 75153486Sphk */ 76153486Sphk#define to_digit(c) ((c) - '0') 77153486Sphk#define is_digit(c) (((unsigned)to_digit(c)) <= 9) 78153486Sphk 79153486Sphk/* various globals ---------------------------------------------------*/ 80153486Sphk 81153486Sphkconst char __lowercase_hex[17] = "0123456789abcdef?"; /*lint !e784 */ 82153486Sphkconst char __uppercase_hex[17] = "0123456789ABCDEF?"; /*lint !e784 */ 83153486Sphk 84153486Sphk#define PADSIZE 16 85153486Sphkstatic char blanks[PADSIZE] = 86153486Sphk {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}; 87153486Sphkstatic char zeroes[PADSIZE] = 88153486Sphk {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}; 89153486Sphk 90153486Sphk/* printing and padding functions ------------------------------------*/ 91153486Sphk 92153486Sphk#define NIOV 8 93153486Sphk 94153486Sphkstruct __printf_io { 95153486Sphk FILE *fp; 96153486Sphk struct __suio uio; 97153486Sphk struct __siov iov[NIOV]; 98153486Sphk struct __siov *iovp; 99153486Sphk}; 100153486Sphk 101153486Sphkstatic void 102153486Sphk__printf_init(struct __printf_io *io) 103153486Sphk{ 104153486Sphk 105153486Sphk io->uio.uio_iov = io->iovp = &io->iov[0]; 106153486Sphk io->uio.uio_resid = 0; 107153486Sphk io->uio.uio_iovcnt = 0; 108153486Sphk} 109153486Sphk 110153486Sphkvoid 111153486Sphk__printf_flush(struct __printf_io *io) 112153486Sphk{ 113153486Sphk 114153486Sphk __sfvwrite(io->fp, &io->uio); 115153486Sphk __printf_init(io); 116153486Sphk} 117153486Sphk 118153486Sphkint 119153486Sphk__printf_puts(struct __printf_io *io, const void *ptr, int len) 120153486Sphk{ 121153486Sphk 122153486Sphk 123153486Sphk if (io->fp->_flags & __SERR) 124153486Sphk return (0); 125153486Sphk if (len == 0) 126153486Sphk return (0); 127153486Sphk io->iovp->iov_base = __DECONST(void *, ptr); 128153486Sphk io->iovp->iov_len = len; 129153486Sphk io->uio.uio_resid += len; 130153486Sphk io->iovp++; 131153486Sphk io->uio.uio_iovcnt++; 132153486Sphk if (io->uio.uio_iovcnt >= NIOV) 133153486Sphk __printf_flush(io); 134153486Sphk return (len); 135153486Sphk} 136153486Sphk 137153486Sphkint 138153486Sphk__printf_pad(struct __printf_io *io, int howmany, int zero) 139153486Sphk{ 140153486Sphk int n; 141153486Sphk const char *with; 142153486Sphk int ret = 0; 143153486Sphk 144153486Sphk if (zero) 145153486Sphk with = zeroes; 146153486Sphk else 147153486Sphk with = blanks; 148153486Sphk 149153486Sphk if ((n = (howmany)) > 0) { 150153486Sphk while (n > PADSIZE) { 151153486Sphk ret += __printf_puts(io, with, PADSIZE); 152153486Sphk n -= PADSIZE; 153153486Sphk } 154153486Sphk ret += __printf_puts(io, with, n); 155153486Sphk } 156153486Sphk return (ret); 157153486Sphk} 158153486Sphk 159153486Sphkint 160153486Sphk__printf_out(struct __printf_io *io, const struct printf_info *pi, const void *ptr, int len) 161153486Sphk{ 162153486Sphk int ret = 0; 163153486Sphk 164153486Sphk if ((!pi->left) && pi->width > len) 165153486Sphk ret += __printf_pad(io, pi->width - len, pi->pad == '0'); 166153486Sphk ret += __printf_puts(io, ptr, len); 167153486Sphk if (pi->left && pi->width > len) 168153486Sphk ret += __printf_pad(io, pi->width - len, pi->pad == '0'); 169153486Sphk return (ret); 170153486Sphk} 171153486Sphk 172153486Sphk 173153486Sphk/* percent handling -------------------------------------------------*/ 174153486Sphk 175153486Sphkstatic int 176153486Sphk__printf_arginfo_pct(const struct printf_info *pi __unused, size_t n __unused, int *argt __unused) 177153486Sphk{ 178153486Sphk 179153486Sphk return (0); 180153486Sphk} 181153486Sphk 182153486Sphkstatic int 183153486Sphk__printf_render_pct(struct __printf_io *io, const struct printf_info *pi __unused, const void *const *arg __unused) 184153486Sphk{ 185153486Sphk 186153486Sphk return (__printf_puts(io, "%", 1)); 187153486Sphk} 188153486Sphk 189153486Sphk/* 'n' ---------------------------------------------------------------*/ 190153486Sphk 191153486Sphkstatic int 192153486Sphk__printf_arginfo_n(const struct printf_info *pi, size_t n, int *argt) 193153486Sphk{ 194153486Sphk 195153486Sphk assert(n >= 1); 196153486Sphk argt[0] = PA_POINTER; 197153486Sphk return (1); 198153486Sphk} 199153486Sphk 200153486Sphk/* 201153486Sphk * This is a printf_render so that all output has been flushed before it 202153486Sphk * gets called. 203153486Sphk */ 204153486Sphk 205153486Sphkstatic int 206153486Sphk__printf_render_n(FILE *io __unused, const struct printf_info *pi, const void *const *arg) 207153486Sphk{ 208153486Sphk 209153486Sphk if (pi->is_char) 210153486Sphk **((signed char **)arg[0]) = (signed char)pi->sofar; 211153486Sphk else if (pi->is_short) 212153486Sphk **((short **)arg[0]) = (short)pi->sofar; 213153486Sphk else if (pi->is_long) 214153486Sphk **((long **)arg[0]) = pi->sofar; 215153486Sphk else if (pi->is_long_double) 216153486Sphk **((long long **)arg[0]) = pi->sofar; 217153486Sphk else if (pi->is_intmax) 218153486Sphk **((intmax_t **)arg[0]) = pi->sofar; 219153486Sphk else if (pi->is_ptrdiff) 220153486Sphk **((ptrdiff_t **)arg[0]) = pi->sofar; 221153486Sphk else if (pi->is_quad) 222153486Sphk **((quad_t **)arg[0]) = pi->sofar; 223153486Sphk else if (pi->is_size) 224153486Sphk **((size_t **)arg[0]) = pi->sofar; 225153486Sphk else 226153486Sphk **((int **)arg[0]) = pi->sofar; 227153486Sphk 228153486Sphk return (0); 229153486Sphk} 230153486Sphk 231153486Sphk/* table -------------------------------------------------------------*/ 232153486Sphk 233153486Sphk/*lint -esym(785, printf_tbl) */ 234153486Sphkstatic struct { 235153486Sphk printf_arginfo_function *arginfo; 236153486Sphk printf_function *gnurender; 237153486Sphk printf_render *render; 238153486Sphk} printf_tbl[256] = { 239153486Sphk ['%'] = { __printf_arginfo_pct, NULL, __printf_render_pct }, 240153486Sphk ['A'] = { __printf_arginfo_float, NULL, __printf_render_float }, 241153486Sphk ['C'] = { __printf_arginfo_chr, NULL, __printf_render_chr }, 242153486Sphk ['E'] = { __printf_arginfo_float, NULL, __printf_render_float }, 243153486Sphk ['F'] = { __printf_arginfo_float, NULL, __printf_render_float }, 244153486Sphk ['G'] = { __printf_arginfo_float, NULL, __printf_render_float }, 245153486Sphk ['S'] = { __printf_arginfo_str, NULL, __printf_render_str }, 246153486Sphk ['X'] = { __printf_arginfo_int, NULL, __printf_render_int }, 247153486Sphk ['a'] = { __printf_arginfo_float, NULL, __printf_render_float }, 248153486Sphk ['c'] = { __printf_arginfo_chr, NULL, __printf_render_chr }, 249153486Sphk ['d'] = { __printf_arginfo_int, NULL, __printf_render_int }, 250153486Sphk ['e'] = { __printf_arginfo_float, NULL, __printf_render_float }, 251153486Sphk ['f'] = { __printf_arginfo_float, NULL, __printf_render_float }, 252153486Sphk ['g'] = { __printf_arginfo_float, NULL, __printf_render_float }, 253153486Sphk ['i'] = { __printf_arginfo_int, NULL, __printf_render_int }, 254153486Sphk ['n'] = { __printf_arginfo_n, __printf_render_n, NULL }, 255153486Sphk ['o'] = { __printf_arginfo_int, NULL, __printf_render_int }, 256153486Sphk ['p'] = { __printf_arginfo_ptr, NULL, __printf_render_ptr }, 257153486Sphk ['q'] = { __printf_arginfo_int, NULL, __printf_render_int }, 258153486Sphk ['s'] = { __printf_arginfo_str, NULL, __printf_render_str }, 259153486Sphk ['u'] = { __printf_arginfo_int, NULL, __printf_render_int }, 260153486Sphk ['x'] = { __printf_arginfo_int, NULL, __printf_render_int }, 261153486Sphk}; 262153486Sphk 263153486Sphk 264153486Sphkstatic int 265163624Skib__v2printf(FILE *fp, const char *fmt0, unsigned pct, va_list ap) 266153486Sphk{ 267153486Sphk struct printf_info *pi, *pil; 268153486Sphk const char *fmt; 269153486Sphk int ch; 270153486Sphk struct printf_info pia[pct + 10]; 271153486Sphk int argt[pct + 10]; 272153486Sphk union arg args[pct + 10]; 273153486Sphk int nextarg; 274153486Sphk int maxarg; 275153486Sphk int ret = 0; 276153486Sphk int n; 277153486Sphk struct __printf_io io; 278153486Sphk 279153486Sphk __printf_init(&io); 280153486Sphk io.fp = fp; 281153486Sphk 282153486Sphk fmt = fmt0; 283153486Sphk maxarg = 0; 284153486Sphk nextarg = 1; 285153486Sphk memset(argt, 0, sizeof argt); 286153486Sphk for (pi = pia; ; pi++) { 287153486Sphk memset(pi, 0, sizeof *pi); 288153486Sphk pil = pi; 289153486Sphk if (*fmt == '\0') 290153486Sphk break; 291153486Sphk pil = pi + 1; 292153486Sphk pi->prec = -1; 293153486Sphk pi->pad = ' '; 294153486Sphk pi->begin = pi->end = fmt; 295153486Sphk while (*fmt != '\0' && *fmt != '%') 296153486Sphk pi->end = ++fmt; 297153486Sphk if (*fmt == '\0') 298153486Sphk break; 299153486Sphk fmt++; 300153486Sphk for (;;) { 301153486Sphk pi->spec = *fmt; 302153486Sphk switch (pi->spec) { 303153486Sphk case ' ': 304153486Sphk /*- 305153486Sphk * ``If the space and + flags both appear, the space 306153486Sphk * flag will be ignored.'' 307153486Sphk * -- ANSI X3J11 308153486Sphk */ 309153486Sphk if (pi->showsign == 0) 310153486Sphk pi->showsign = ' '; 311153486Sphk fmt++; 312153486Sphk continue; 313153486Sphk case '#': 314153486Sphk pi->alt = 1; 315153486Sphk fmt++; 316153486Sphk continue; 317153486Sphk case '.': 318153486Sphk pi->prec = 0; 319153486Sphk fmt++; 320153486Sphk if (*fmt == '*') { 321153486Sphk fmt++; 322153486Sphk pi->get_prec = nextarg; 323153486Sphk argt[nextarg++] = PA_INT; 324153486Sphk continue; 325153486Sphk } 326153486Sphk while (*fmt != '\0' && is_digit(*fmt)) { 327153486Sphk pi->prec *= 10; 328153486Sphk pi->prec += to_digit(*fmt); 329153486Sphk fmt++; 330153486Sphk } 331153486Sphk continue; 332153486Sphk case '-': 333153486Sphk pi->left = 1; 334153486Sphk fmt++; 335153486Sphk continue; 336153486Sphk case '+': 337153486Sphk pi->showsign = '+'; 338153486Sphk fmt++; 339153486Sphk continue; 340153486Sphk case '*': 341153486Sphk fmt++; 342153486Sphk pi->get_width = nextarg; 343153486Sphk argt[nextarg++] = PA_INT; 344153486Sphk continue; 345153486Sphk case '%': 346153486Sphk fmt++; 347153486Sphk break; 348153486Sphk case '\'': 349153486Sphk pi->group = 1; 350153486Sphk fmt++; 351153486Sphk continue; 352153486Sphk case '0': 353153486Sphk /*- 354153486Sphk * ``Note that 0 is taken as a flag, not as the 355153486Sphk * beginning of a field width.'' 356153486Sphk * -- ANSI X3J11 357153486Sphk */ 358153486Sphk pi->pad = '0'; 359153486Sphk fmt++; 360153486Sphk continue; 361153486Sphk case '1': case '2': case '3': 362153486Sphk case '4': case '5': case '6': 363153486Sphk case '7': case '8': case '9': 364153486Sphk n = 0; 365153486Sphk while (*fmt != '\0' && is_digit(*fmt)) { 366153486Sphk n *= 10; 367153486Sphk n += to_digit(*fmt); 368153486Sphk fmt++; 369153486Sphk } 370153486Sphk if (*fmt == '$') { 371153486Sphk if (nextarg > maxarg) 372153486Sphk maxarg = nextarg; 373153486Sphk nextarg = n; 374153486Sphk fmt++; 375153486Sphk } else 376153486Sphk pi->width = n; 377153486Sphk continue; 378153486Sphk case 'D': 379153486Sphk case 'O': 380153486Sphk case 'U': 381153486Sphk pi->spec += ('a' - 'A'); 382153486Sphk pi->is_intmax = 0; 383153486Sphk if (pi->is_long_double || pi->is_quad) { 384153486Sphk pi->is_long = 0; 385153486Sphk pi->is_long_double = 1; 386153486Sphk } else { 387153486Sphk pi->is_long = 1; 388153486Sphk pi->is_long_double = 0; 389153486Sphk } 390153486Sphk fmt++; 391153486Sphk break; 392153486Sphk case 'j': 393153486Sphk pi->is_intmax = 1; 394153486Sphk fmt++; 395153486Sphk continue; 396153486Sphk case 'q': 397153486Sphk pi->is_long = 0; 398153486Sphk pi->is_quad = 1; 399153486Sphk fmt++; 400153486Sphk continue; 401153486Sphk case 'L': 402153486Sphk pi->is_long_double = 1; 403153486Sphk fmt++; 404153486Sphk continue; 405153486Sphk case 'h': 406153486Sphk fmt++; 407153486Sphk if (*fmt == 'h') { 408153486Sphk fmt++; 409153486Sphk pi->is_char = 1; 410153486Sphk } else { 411153486Sphk pi->is_short = 1; 412153486Sphk } 413153486Sphk continue; 414153486Sphk case 'l': 415153486Sphk fmt++; 416153486Sphk if (*fmt == 'l') { 417153486Sphk fmt++; 418153486Sphk pi->is_long_double = 1; 419153486Sphk pi->is_quad = 0; 420153486Sphk } else { 421153486Sphk pi->is_quad = 0; 422153486Sphk pi->is_long = 1; 423153486Sphk } 424153486Sphk continue; 425153486Sphk case 't': 426153486Sphk pi->is_ptrdiff = 1; 427153486Sphk fmt++; 428153486Sphk continue; 429153486Sphk case 'z': 430153486Sphk pi->is_size = 1; 431153486Sphk fmt++; 432153486Sphk continue; 433153486Sphk default: 434153486Sphk fmt++; 435153486Sphk break; 436153486Sphk } 437153486Sphk if (printf_tbl[pi->spec].arginfo == NULL) 438153486Sphk errx(1, "arginfo[%c] = NULL", pi->spec); 439153486Sphk ch = printf_tbl[pi->spec].arginfo( 440153486Sphk pi, __PRINTFMAXARG, &argt[nextarg]); 441153486Sphk if (ch > 0) 442153486Sphk pi->arg[0] = &args[nextarg]; 443153486Sphk if (ch > 1) 444153486Sphk pi->arg[1] = &args[nextarg + 1]; 445153486Sphk nextarg += ch; 446153486Sphk break; 447153486Sphk } 448153486Sphk } 449153486Sphk if (nextarg > maxarg) 450153486Sphk maxarg = nextarg; 451153486Sphk#if 0 452153486Sphk fprintf(stderr, "fmt0 <%s>\n", fmt0); 453153486Sphk fprintf(stderr, "pil %p\n", pil); 454153486Sphk#endif 455153486Sphk for (ch = 1; ch < maxarg; ch++) { 456153486Sphk#if 0 457153486Sphk fprintf(stderr, "arg %d %x\n", ch, argt[ch]); 458153486Sphk#endif 459153486Sphk switch(argt[ch]) { 460153486Sphk case PA_CHAR: 461153486Sphk args[ch].intarg = (char)va_arg (ap, int); 462153486Sphk break; 463153486Sphk case PA_INT: 464153486Sphk args[ch].intarg = va_arg (ap, int); 465153486Sphk break; 466153486Sphk case PA_INT | PA_FLAG_SHORT: 467153486Sphk args[ch].intarg = (short)va_arg (ap, int); 468153486Sphk break; 469153486Sphk case PA_INT | PA_FLAG_LONG: 470153486Sphk args[ch].longarg = va_arg (ap, long); 471153486Sphk break; 472153486Sphk case PA_INT | PA_FLAG_INTMAX: 473153486Sphk args[ch].intmaxarg = va_arg (ap, intmax_t); 474153486Sphk break; 475153486Sphk case PA_INT | PA_FLAG_QUAD: 476153486Sphk args[ch].intmaxarg = va_arg (ap, quad_t); 477153486Sphk break; 478153486Sphk case PA_INT | PA_FLAG_LONG_LONG: 479153486Sphk args[ch].intmaxarg = va_arg (ap, long long); 480153486Sphk break; 481153486Sphk case PA_INT | PA_FLAG_SIZE: 482153486Sphk args[ch].intmaxarg = va_arg (ap, size_t); 483153486Sphk break; 484153486Sphk case PA_INT | PA_FLAG_PTRDIFF: 485153486Sphk args[ch].intmaxarg = va_arg (ap, ptrdiff_t); 486153486Sphk break; 487153486Sphk case PA_WCHAR: 488153486Sphk args[ch].wintarg = va_arg (ap, wint_t); 489153486Sphk break; 490153486Sphk case PA_POINTER: 491153486Sphk args[ch].pvoidarg = va_arg (ap, void *); 492153486Sphk break; 493153486Sphk case PA_STRING: 494153486Sphk args[ch].pchararg = va_arg (ap, char *); 495153486Sphk break; 496153486Sphk case PA_WSTRING: 497153486Sphk args[ch].pwchararg = va_arg (ap, wchar_t *); 498153486Sphk break; 499153486Sphk case PA_DOUBLE: 500157381Sphk#ifndef NO_FLOATING_POINT 501153486Sphk args[ch].doublearg = va_arg (ap, double); 502157381Sphk#endif 503153486Sphk break; 504153486Sphk case PA_DOUBLE | PA_FLAG_LONG_DOUBLE: 505157381Sphk#ifndef NO_FLOATING_POINT 506153486Sphk args[ch].longdoublearg = va_arg (ap, long double); 507157381Sphk#endif 508153486Sphk break; 509153486Sphk default: 510153486Sphk errx(1, "argtype = %x (fmt = \"%s\")\n", 511153486Sphk argt[ch], fmt0); 512153486Sphk } 513153486Sphk } 514153486Sphk for (pi = pia; pi < pil; pi++) { 515153486Sphk#if 0 516153486Sphk fprintf(stderr, "pi %p", pi); 517153486Sphk fprintf(stderr, " spec '%c'", pi->spec); 518153486Sphk fprintf(stderr, " args %d", 519153486Sphk ((uintptr_t)pi->arg[0] - (uintptr_t)args) / sizeof args[0]); 520153486Sphk if (pi->width) fprintf(stderr, " width %d", pi->width); 521153486Sphk if (pi->pad) fprintf(stderr, " pad 0x%x", pi->pad); 522153486Sphk if (pi->left) fprintf(stderr, " left"); 523153486Sphk if (pi->showsign) fprintf(stderr, " showsign"); 524153486Sphk if (pi->prec != -1) fprintf(stderr, " prec %d", pi->prec); 525153486Sphk if (pi->is_char) fprintf(stderr, " char"); 526153486Sphk if (pi->is_short) fprintf(stderr, " short"); 527153486Sphk if (pi->is_long) fprintf(stderr, " long"); 528153486Sphk if (pi->is_long_double) fprintf(stderr, " long_double"); 529153486Sphk fprintf(stderr, "\n"); 530153486Sphk fprintf(stderr, "\t\"%.*s\"\n", pi->end - pi->begin, pi->begin); 531153486Sphk#endif 532153486Sphk if (pi->get_width) { 533153486Sphk pi->width = args[pi->get_width].intarg; 534153486Sphk /*- 535153486Sphk * ``A negative field width argument is taken as a 536153486Sphk * - flag followed by a positive field width.'' 537153486Sphk * -- ANSI X3J11 538153486Sphk * They don't exclude field widths read from args. 539153486Sphk */ 540153486Sphk if (pi->width < 0) { 541153486Sphk pi->left = 1; 542153486Sphk pi->width = -pi->width; 543153486Sphk } 544153486Sphk } 545153486Sphk if (pi->get_prec) 546153486Sphk pi->prec = args[pi->get_prec].intarg; 547153486Sphk ret += __printf_puts(&io, pi->begin, pi->end - pi->begin); 548153486Sphk if (printf_tbl[pi->spec].gnurender != NULL) { 549153486Sphk __printf_flush(&io); 550153486Sphk pi->sofar = ret; 551153486Sphk ret += printf_tbl[pi->spec].gnurender( 552153486Sphk fp, pi, (const void *)pi->arg); 553153486Sphk } else if (printf_tbl[pi->spec].render != NULL) { 554153486Sphk pi->sofar = ret; 555153486Sphk n = printf_tbl[pi->spec].render( 556153486Sphk &io, pi, (const void *)pi->arg); 557153486Sphk if (n < 0) 558153486Sphk io.fp->_flags |= __SERR; 559153486Sphk else 560153486Sphk ret += n; 561153486Sphk } else if (pi->begin == pi->end) 562153486Sphk errx(1, "render[%c] = NULL", *fmt); 563153486Sphk } 564153486Sphk __printf_flush(&io); 565153486Sphk return (ret); 566153486Sphk} 567153486Sphk 568153486Sphkextern int __fflush(FILE *fp); 569153486Sphk 570153486Sphk/* 571153486Sphk * Helper function for `fprintf to unbuffered unix file': creates a 572153486Sphk * temporary buffer. We only work on write-only files; this avoids 573153486Sphk * worries about ungetc buffers and so forth. 574153486Sphk */ 575153486Sphkstatic int 576153486Sphk__v3printf(FILE *fp, const char *fmt, int pct, va_list ap) 577153486Sphk{ 578153486Sphk int ret; 579205021Sjhb FILE fake = FAKE_FILE; 580153486Sphk unsigned char buf[BUFSIZ]; 581153486Sphk 582153486Sphk /* copy the important variables */ 583153486Sphk fake._flags = fp->_flags & ~__SNBF; 584153486Sphk fake._file = fp->_file; 585153486Sphk fake._cookie = fp->_cookie; 586153486Sphk fake._write = fp->_write; 587178287Sjhb fake._orientation = fp->_orientation; 588178287Sjhb fake._mbstate = fp->_mbstate; 589153486Sphk 590153486Sphk /* set up the buffer */ 591153486Sphk fake._bf._base = fake._p = buf; 592153486Sphk fake._bf._size = fake._w = sizeof(buf); 593153486Sphk fake._lbfsize = 0; /* not actually used, but Just In Case */ 594153486Sphk 595153486Sphk /* do the work, then copy any error status */ 596153486Sphk ret = __v2printf(&fake, fmt, pct, ap); 597153486Sphk if (ret >= 0 && __fflush(&fake)) 598153486Sphk ret = EOF; 599153486Sphk if (fake._flags & __SERR) 600153486Sphk fp->_flags |= __SERR; 601153486Sphk return (ret); 602153486Sphk} 603153486Sphk 604153486Sphkint 605153486Sphk__xvprintf(FILE *fp, const char *fmt0, va_list ap) 606153486Sphk{ 607153486Sphk unsigned u; 608153486Sphk const char *p; 609153486Sphk 610153486Sphk /* Count number of '%' signs handling double '%' signs */ 611153486Sphk for (p = fmt0, u = 0; *p; p++) { 612153486Sphk if (*p != '%') 613153486Sphk continue; 614153486Sphk u++; 615153486Sphk if (p[1] == '%') 616153486Sphk p++; 617153486Sphk } 618153486Sphk 619153486Sphk /* optimise fprintf(stderr) (and other unbuffered Unix files) */ 620153486Sphk if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && 621153486Sphk fp->_file >= 0) 622153486Sphk return (__v3printf(fp, fmt0, u, ap)); 623153486Sphk else 624153486Sphk return (__v2printf(fp, fmt0, u, ap)); 625153486Sphk} 626153486Sphk 627153486Sphk/* extending ---------------------------------------------------------*/ 628153486Sphk 629153486Sphkint 630153486Sphkregister_printf_function(int spec, printf_function *render, printf_arginfo_function *arginfo) 631153486Sphk{ 632153486Sphk 633153486Sphk if (spec > 255 || spec < 0) 634153486Sphk return (-1); 635153486Sphk printf_tbl[spec].gnurender = render; 636153486Sphk printf_tbl[spec].arginfo = arginfo; 637153486Sphk __use_xprintf = 1; 638153486Sphk return (0); 639153486Sphk} 640153486Sphk 641153486Sphkint 642153486Sphkregister_printf_render(int spec, printf_render *render, printf_arginfo_function *arginfo) 643153486Sphk{ 644153486Sphk 645153486Sphk if (spec > 255 || spec < 0) 646153486Sphk return (-1); 647153486Sphk printf_tbl[spec].render = render; 648153486Sphk printf_tbl[spec].arginfo = arginfo; 649153486Sphk __use_xprintf = 1; 650153486Sphk return (0); 651153486Sphk} 652153486Sphk 653153486Sphkint 654238111Spjdregister_printf_render_std(const char *specs) 655153486Sphk{ 656153486Sphk 657153486Sphk for (; *specs != '\0'; specs++) { 658153486Sphk switch (*specs) { 659153486Sphk case 'H': 660153486Sphk register_printf_render(*specs, 661153486Sphk __printf_render_hexdump, 662153486Sphk __printf_arginfo_hexdump); 663153486Sphk break; 664154815Sphk case 'M': 665154815Sphk register_printf_render(*specs, 666154815Sphk __printf_render_errno, 667154815Sphk __printf_arginfo_errno); 668154815Sphk break; 669154815Sphk case 'Q': 670154815Sphk register_printf_render(*specs, 671154815Sphk __printf_render_quote, 672154815Sphk __printf_arginfo_quote); 673154815Sphk break; 674153486Sphk case 'T': 675153486Sphk register_printf_render(*specs, 676153486Sphk __printf_render_time, 677153486Sphk __printf_arginfo_time); 678153486Sphk break; 679153486Sphk case 'V': 680153486Sphk register_printf_render(*specs, 681153486Sphk __printf_render_vis, 682153486Sphk __printf_arginfo_vis); 683153486Sphk break; 684153486Sphk default: 685153486Sphk return (-1); 686153486Sphk } 687153486Sphk } 688153486Sphk return (0); 689153486Sphk} 690153486Sphk 691