1187277Sdas/*- 2187277Sdas * Copyright (c) 1990, 1993 3187277Sdas * The Regents of the University of California. All rights reserved. 4187277Sdas * 5187277Sdas * This code is derived from software contributed to Berkeley by 6187277Sdas * Chris Torek. 7187277Sdas * 8227753Stheraven * Copyright (c) 2011 The FreeBSD Foundation 9227753Stheraven * All rights reserved. 10227753Stheraven * Portions of this software were developed by David Chisnall 11227753Stheraven * under sponsorship from the FreeBSD Foundation. 12227753Stheraven * 13187277Sdas * Redistribution and use in source and binary forms, with or without 14187277Sdas * modification, are permitted provided that the following conditions 15187277Sdas * are met: 16187277Sdas * 1. Redistributions of source code must retain the above copyright 17187277Sdas * notice, this list of conditions and the following disclaimer. 18187277Sdas * 2. Redistributions in binary form must reproduce the above copyright 19187277Sdas * notice, this list of conditions and the following disclaimer in the 20187277Sdas * documentation and/or other materials provided with the distribution. 21187277Sdas * 4. Neither the name of the University nor the names of its contributors 22187277Sdas * may be used to endorse or promote products derived from this software 23187277Sdas * without specific prior written permission. 24187277Sdas * 25187277Sdas * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26187277Sdas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27187277Sdas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28187277Sdas * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29187277Sdas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30187277Sdas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31187277Sdas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32187277Sdas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33187277Sdas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34187277Sdas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35187277Sdas * SUCH DAMAGE. 36187277Sdas * 37187277Sdas * $FreeBSD: releng/11.0/lib/libc/stdio/printfcommon.h 227753 2011-11-20 14:45:42Z theraven $ 38187277Sdas */ 39187277Sdas 40187277Sdas/* 41187277Sdas * This file defines common routines used by both printf and wprintf. 42187277Sdas * You must define CHAR to either char or wchar_t prior to including this. 43187277Sdas */ 44187277Sdas 45187284Sdas 46187284Sdas#ifndef NO_FLOATING_POINT 47187284Sdas 48187284Sdas#define dtoa __dtoa 49187284Sdas#define freedtoa __freedtoa 50187284Sdas 51187284Sdas#include <float.h> 52187284Sdas#include <math.h> 53187284Sdas#include "floatio.h" 54187284Sdas#include "gdtoa.h" 55187284Sdas 56187284Sdas#define DEFPREC 6 57187284Sdas 58187284Sdasstatic int exponent(CHAR *, int, CHAR); 59187284Sdas 60187284Sdas#endif /* !NO_FLOATING_POINT */ 61187284Sdas 62187582Sdasstatic CHAR *__ujtoa(uintmax_t, CHAR *, int, int, const char *); 63187582Sdasstatic CHAR *__ultoa(u_long, CHAR *, int, int, const char *); 64187284Sdas 65187277Sdas#define NIOV 8 66187277Sdasstruct io_state { 67187277Sdas FILE *fp; 68187277Sdas struct __suio uio; /* output information: summary */ 69187277Sdas struct __siov iov[NIOV];/* ... and individual io vectors */ 70187277Sdas}; 71187277Sdas 72187277Sdasstatic inline void 73187277Sdasio_init(struct io_state *iop, FILE *fp) 74187277Sdas{ 75187277Sdas 76187354Sdas iop->uio.uio_iov = iop->iov; 77187277Sdas iop->uio.uio_resid = 0; 78187277Sdas iop->uio.uio_iovcnt = 0; 79187277Sdas iop->fp = fp; 80187277Sdas} 81187277Sdas 82187277Sdas/* 83187277Sdas * WARNING: The buffer passed to io_print() is not copied immediately; it must 84187277Sdas * remain valid until io_flush() is called. 85187277Sdas */ 86187277Sdasstatic inline int 87227753Stheravenio_print(struct io_state *iop, const CHAR * __restrict ptr, int len, locale_t locale) 88187277Sdas{ 89187277Sdas 90187354Sdas iop->iov[iop->uio.uio_iovcnt].iov_base = (char *)ptr; 91187354Sdas iop->iov[iop->uio.uio_iovcnt].iov_len = len; 92187277Sdas iop->uio.uio_resid += len; 93187354Sdas if (++iop->uio.uio_iovcnt >= NIOV) 94227753Stheraven return (__sprint(iop->fp, &iop->uio, locale)); 95187354Sdas else 96187354Sdas return (0); 97187277Sdas} 98187277Sdas 99187277Sdas/* 100187277Sdas * Choose PADSIZE to trade efficiency vs. size. If larger printf 101187277Sdas * fields occur frequently, increase PADSIZE and make the initialisers 102187277Sdas * below longer. 103187277Sdas */ 104187277Sdas#define PADSIZE 16 /* pad chunk size */ 105187277Sdasstatic const CHAR blanks[PADSIZE] = 106187277Sdas{' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}; 107187277Sdasstatic const CHAR zeroes[PADSIZE] = 108187277Sdas{'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}; 109187277Sdas 110187277Sdas/* 111187277Sdas * Pad with blanks or zeroes. 'with' should point to either the blanks array 112187277Sdas * or the zeroes array. 113187277Sdas */ 114187277Sdasstatic inline int 115227753Stheravenio_pad(struct io_state *iop, int howmany, const CHAR * __restrict with, 116227753Stheraven locale_t locale) 117187277Sdas{ 118187354Sdas int n; 119187277Sdas 120187354Sdas while (howmany > 0) { 121187354Sdas n = (howmany >= PADSIZE) ? PADSIZE : howmany; 122227753Stheraven if (io_print(iop, with, n, locale)) 123187277Sdas return (-1); 124187354Sdas howmany -= n; 125187277Sdas } 126187277Sdas return (0); 127187277Sdas} 128187277Sdas 129187277Sdas/* 130187277Sdas * Print exactly len characters of the string spanning p to ep, truncating 131187277Sdas * or padding with 'with' as necessary. 132187277Sdas */ 133187277Sdasstatic inline int 134187277Sdasio_printandpad(struct io_state *iop, const CHAR *p, const CHAR *ep, 135227753Stheraven int len, const CHAR * __restrict with, locale_t locale) 136187277Sdas{ 137187277Sdas int p_len; 138187277Sdas 139187277Sdas p_len = ep - p; 140187277Sdas if (p_len > len) 141187277Sdas p_len = len; 142187354Sdas if (p_len > 0) { 143227753Stheraven if (io_print(iop, p, p_len, locale)) 144187354Sdas return (-1); 145187354Sdas } else { 146187354Sdas p_len = 0; 147187354Sdas } 148227753Stheraven return (io_pad(iop, len - p_len, with, locale)); 149187277Sdas} 150187277Sdas 151187277Sdasstatic inline int 152227753Stheravenio_flush(struct io_state *iop, locale_t locale) 153187277Sdas{ 154187277Sdas 155227753Stheraven return (__sprint(iop->fp, &iop->uio, locale)); 156187277Sdas} 157187284Sdas 158187284Sdas/* 159187284Sdas * Convert an unsigned long to ASCII for printf purposes, returning 160187284Sdas * a pointer to the first character of the string representation. 161187284Sdas * Octal numbers can be forced to have a leading zero; hex numbers 162187284Sdas * use the given digits. 163187284Sdas */ 164187284Sdasstatic CHAR * 165187582Sdas__ultoa(u_long val, CHAR *endp, int base, int octzero, const char *xdigs) 166187284Sdas{ 167187284Sdas CHAR *cp = endp; 168187284Sdas long sval; 169187284Sdas 170187284Sdas /* 171187284Sdas * Handle the three cases separately, in the hope of getting 172187284Sdas * better/faster code. 173187284Sdas */ 174187284Sdas switch (base) { 175187284Sdas case 10: 176187284Sdas if (val < 10) { /* many numbers are 1 digit */ 177187284Sdas *--cp = to_char(val); 178187284Sdas return (cp); 179187284Sdas } 180187284Sdas /* 181187284Sdas * On many machines, unsigned arithmetic is harder than 182187284Sdas * signed arithmetic, so we do at most one unsigned mod and 183187284Sdas * divide; this is sufficient to reduce the range of 184187284Sdas * the incoming value to where signed arithmetic works. 185187284Sdas */ 186187284Sdas if (val > LONG_MAX) { 187187284Sdas *--cp = to_char(val % 10); 188187284Sdas sval = val / 10; 189187284Sdas } else 190187284Sdas sval = val; 191187284Sdas do { 192187284Sdas *--cp = to_char(sval % 10); 193187284Sdas sval /= 10; 194187284Sdas } while (sval != 0); 195187284Sdas break; 196187284Sdas 197187284Sdas case 8: 198187284Sdas do { 199187284Sdas *--cp = to_char(val & 7); 200187284Sdas val >>= 3; 201187284Sdas } while (val); 202187284Sdas if (octzero && *cp != '0') 203187284Sdas *--cp = '0'; 204187284Sdas break; 205187284Sdas 206187284Sdas case 16: 207187284Sdas do { 208187284Sdas *--cp = xdigs[val & 15]; 209187284Sdas val >>= 4; 210187284Sdas } while (val); 211187284Sdas break; 212187284Sdas 213187284Sdas default: /* oops */ 214187284Sdas abort(); 215187284Sdas } 216187284Sdas return (cp); 217187284Sdas} 218187284Sdas 219187284Sdas/* Identical to __ultoa, but for intmax_t. */ 220187284Sdasstatic CHAR * 221187582Sdas__ujtoa(uintmax_t val, CHAR *endp, int base, int octzero, const char *xdigs) 222187284Sdas{ 223187284Sdas CHAR *cp = endp; 224187284Sdas intmax_t sval; 225187284Sdas 226187284Sdas /* quick test for small values; __ultoa is typically much faster */ 227187284Sdas /* (perhaps instead we should run until small, then call __ultoa?) */ 228187284Sdas if (val <= ULONG_MAX) 229187582Sdas return (__ultoa((u_long)val, endp, base, octzero, xdigs)); 230187284Sdas switch (base) { 231187284Sdas case 10: 232187284Sdas if (val < 10) { 233187284Sdas *--cp = to_char(val % 10); 234187284Sdas return (cp); 235187284Sdas } 236187284Sdas if (val > INTMAX_MAX) { 237187284Sdas *--cp = to_char(val % 10); 238187284Sdas sval = val / 10; 239187284Sdas } else 240187284Sdas sval = val; 241187284Sdas do { 242187284Sdas *--cp = to_char(sval % 10); 243187284Sdas sval /= 10; 244187284Sdas } while (sval != 0); 245187284Sdas break; 246187284Sdas 247187284Sdas case 8: 248187284Sdas do { 249187284Sdas *--cp = to_char(val & 7); 250187284Sdas val >>= 3; 251187284Sdas } while (val); 252187284Sdas if (octzero && *cp != '0') 253187284Sdas *--cp = '0'; 254187284Sdas break; 255187284Sdas 256187284Sdas case 16: 257187284Sdas do { 258187284Sdas *--cp = xdigs[val & 15]; 259187284Sdas val >>= 4; 260187284Sdas } while (val); 261187284Sdas break; 262187284Sdas 263187284Sdas default: 264187284Sdas abort(); 265187284Sdas } 266187284Sdas return (cp); 267187284Sdas} 268187284Sdas 269187284Sdas#ifndef NO_FLOATING_POINT 270187284Sdas 271187284Sdasstatic int 272187284Sdasexponent(CHAR *p0, int exp, CHAR fmtch) 273187284Sdas{ 274187284Sdas CHAR *p, *t; 275187284Sdas CHAR expbuf[MAXEXPDIG]; 276187284Sdas 277187284Sdas p = p0; 278187284Sdas *p++ = fmtch; 279187284Sdas if (exp < 0) { 280187284Sdas exp = -exp; 281187284Sdas *p++ = '-'; 282187284Sdas } 283187284Sdas else 284187284Sdas *p++ = '+'; 285187284Sdas t = expbuf + MAXEXPDIG; 286187284Sdas if (exp > 9) { 287187284Sdas do { 288187284Sdas *--t = to_char(exp % 10); 289187284Sdas } while ((exp /= 10) > 9); 290187284Sdas *--t = to_char(exp); 291187284Sdas for (; t < expbuf + MAXEXPDIG; *p++ = *t++); 292187284Sdas } 293187284Sdas else { 294187284Sdas /* 295187284Sdas * Exponents for decimal floating point conversions 296187284Sdas * (%[eEgG]) must be at least two characters long, 297187284Sdas * whereas exponents for hexadecimal conversions can 298187284Sdas * be only one character long. 299187284Sdas */ 300187284Sdas if (fmtch == 'e' || fmtch == 'E') 301187284Sdas *p++ = '0'; 302187284Sdas *p++ = to_char(exp); 303187284Sdas } 304187284Sdas return (p - p0); 305187284Sdas} 306187284Sdas 307187284Sdas#endif /* !NO_FLOATING_POINT */ 308