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