1/*- 2 * Copyright (c) 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Chris Torek. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 4. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $FreeBSD: src/lib/libc/stdio/printfcommon.h,v 1.4 2009/01/22 08:14:28 das Exp $ 33 */ 34 35/* 36 * This file defines common routines used by both printf and wprintf. 37 * You must define CHAR to either char or wchar_t prior to including this. 38 */ 39 40 41#ifndef NO_FLOATING_POINT 42 43#define dtoa __dtoa 44#define freedtoa __freedtoa 45 46#include <float.h> 47#include <math.h> 48#include "floatio.h" 49#include "gdtoa.h" 50 51#define DEFPREC 6 52 53static int exponent(CHAR *, int, CHAR); 54 55#endif /* !NO_FLOATING_POINT */ 56 57static CHAR *__ujtoa(uintmax_t, CHAR *, int, int, const char *); 58static CHAR *__ultoa(u_long, CHAR *, int, int, const char *); 59 60#define NIOV 8 61struct io_state { 62 FILE *fp; 63 struct __suio uio; /* output information: summary */ 64 struct __siov iov[NIOV];/* ... and individual io vectors */ 65}; 66 67static inline void 68io_init(struct io_state *iop, FILE *fp) 69{ 70 71 iop->uio.uio_iov = iop->iov; 72 iop->uio.uio_resid = 0; 73 iop->uio.uio_iovcnt = 0; 74 iop->fp = fp; 75} 76 77/* 78 * WARNING: The buffer passed to io_print() is not copied immediately; it must 79 * remain valid until io_flush() is called. 80 */ 81static inline int 82io_print(struct io_state *iop, const CHAR * __restrict ptr, int len, locale_t loc) 83{ 84 85 iop->iov[iop->uio.uio_iovcnt].iov_base = (char *)ptr; 86 iop->iov[iop->uio.uio_iovcnt].iov_len = len; 87 iop->uio.uio_resid += len; 88 if (++iop->uio.uio_iovcnt >= NIOV) 89 return (__sprint(iop->fp, loc, &iop->uio)); 90 else 91 return (0); 92} 93 94/* 95 * Choose PADSIZE to trade efficiency vs. size. If larger printf 96 * fields occur frequently, increase PADSIZE and make the initialisers 97 * below longer. 98 */ 99#define PADSIZE 16 /* pad chunk size */ 100static const CHAR blanks[PADSIZE] = 101{' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}; 102static const CHAR zeroes[PADSIZE] = 103{'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}; 104 105/* 106 * Pad with blanks or zeroes. 'with' should point to either the blanks array 107 * or the zeroes array. 108 */ 109static inline int 110io_pad(struct io_state *iop, int howmany, const CHAR * __restrict with, locale_t loc) 111{ 112 int n; 113 114 while (howmany > 0) { 115 n = (howmany >= PADSIZE) ? PADSIZE : howmany; 116 if (io_print(iop, with, n, loc)) 117 return (-1); 118 howmany -= n; 119 } 120 return (0); 121} 122 123/* 124 * Print exactly len characters of the string spanning p to ep, truncating 125 * or padding with 'with' as necessary. 126 */ 127static inline int 128io_printandpad(struct io_state *iop, const CHAR *p, const CHAR *ep, 129 int len, const CHAR * __restrict with, locale_t loc) 130{ 131 int p_len; 132 133 p_len = ep - p; 134 if (p_len > len) 135 p_len = len; 136 if (p_len > 0) { 137 if (io_print(iop, p, p_len, loc)) 138 return (-1); 139 } else { 140 p_len = 0; 141 } 142 return (io_pad(iop, len - p_len, with, loc)); 143} 144 145static inline int 146io_flush(struct io_state *iop, locale_t loc) 147{ 148 149 return (__sprint(iop->fp, loc, &iop->uio)); 150} 151 152/* 153 * Convert an unsigned long to ASCII for printf purposes, returning 154 * a pointer to the first character of the string representation. 155 * Octal numbers can be forced to have a leading zero; hex numbers 156 * use the given digits. 157 */ 158static CHAR * 159__ultoa(u_long val, CHAR *endp, int base, int octzero, const char *xdigs) 160{ 161 CHAR *cp = endp; 162 long sval; 163 164 /* 165 * Handle the three cases separately, in the hope of getting 166 * better/faster code. 167 */ 168 switch (base) { 169 case 10: 170 if (val < 10) { /* many numbers are 1 digit */ 171 *--cp = to_char(val); 172 return (cp); 173 } 174 /* 175 * On many machines, unsigned arithmetic is harder than 176 * signed arithmetic, so we do at most one unsigned mod and 177 * divide; this is sufficient to reduce the range of 178 * the incoming value to where signed arithmetic works. 179 */ 180 if (val > LONG_MAX) { 181 *--cp = to_char(val % 10); 182 sval = val / 10; 183 } else 184 sval = val; 185 do { 186 *--cp = to_char(sval % 10); 187 sval /= 10; 188 } while (sval != 0); 189 break; 190 191 case 8: 192 do { 193 *--cp = to_char(val & 7); 194 val >>= 3; 195 } while (val); 196 if (octzero && *cp != '0') 197 *--cp = '0'; 198 break; 199 200 case 16: 201 do { 202 *--cp = xdigs[val & 15]; 203 val >>= 4; 204 } while (val); 205 break; 206 207 default: /* oops */ 208 LIBC_ABORT("__ultoa: invalid base=%d", base); 209 } 210 return (cp); 211} 212 213/* Identical to __ultoa, but for intmax_t. */ 214static CHAR * 215__ujtoa(uintmax_t val, CHAR *endp, int base, int octzero, const char *xdigs) 216{ 217 CHAR *cp = endp; 218 intmax_t sval; 219 220 /* quick test for small values; __ultoa is typically much faster */ 221 /* (perhaps instead we should run until small, then call __ultoa?) */ 222 if (val <= ULONG_MAX) 223 return (__ultoa((u_long)val, endp, base, octzero, xdigs)); 224 switch (base) { 225 case 10: 226 if (val < 10) { 227 *--cp = to_char(val % 10); 228 return (cp); 229 } 230 if (val > INTMAX_MAX) { 231 *--cp = to_char(val % 10); 232 sval = val / 10; 233 } else 234 sval = val; 235 do { 236 *--cp = to_char(sval % 10); 237 sval /= 10; 238 } while (sval != 0); 239 break; 240 241 case 8: 242 do { 243 *--cp = to_char(val & 7); 244 val >>= 3; 245 } while (val); 246 if (octzero && *cp != '0') 247 *--cp = '0'; 248 break; 249 250 case 16: 251 do { 252 *--cp = xdigs[val & 15]; 253 val >>= 4; 254 } while (val); 255 break; 256 257 default: 258 LIBC_ABORT("__ujtoa: invalid base=%d", base); 259 } 260 return (cp); 261} 262 263#ifndef NO_FLOATING_POINT 264 265static int 266exponent(CHAR *p0, int exp, CHAR fmtch) 267{ 268 CHAR *p, *t; 269 CHAR expbuf[MAXEXPDIG]; 270 271 p = p0; 272 *p++ = fmtch; 273 if (exp < 0) { 274 exp = -exp; 275 *p++ = '-'; 276 } 277 else 278 *p++ = '+'; 279 t = expbuf + MAXEXPDIG; 280 if (exp > 9) { 281 do { 282 *--t = to_char(exp % 10); 283 } while ((exp /= 10) > 9); 284 *--t = to_char(exp); 285 for (; t < expbuf + MAXEXPDIG; *p++ = *t++); 286 } 287 else { 288 /* 289 * Exponents for decimal floating point conversions 290 * (%[eEgG]) must be at least two characters long, 291 * whereas exponents for hexadecimal conversions can 292 * be only one character long. 293 */ 294 if (fmtch == 'e' || fmtch == 'E') 295 *p++ = '0'; 296 *p++ = to_char(exp); 297 } 298 return (p - p0); 299} 300 301#endif /* !NO_FLOATING_POINT */ 302