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 #ifndef NO_FLOATING_POINT 47 48 #define dtoa __dtoa 49 #define freedtoa __freedtoa 50 51 #include <float.h> 52 #include <math.h> 53 #include "floatio.h" 54 #include "gdtoa.h" 55 56 #define DEFPREC 6 57 58 static int exponent(CHAR *, int, CHAR); 59 60 #endif /* !NO_FLOATING_POINT */ 61 62 static CHAR *__ujtoa(uintmax_t, CHAR *, int, int, const char *); 63 static CHAR *__ultoa(u_long, CHAR *, int, int, const char *); 64 65 #define NIOV 8 66 struct io_state { 67 FILE *fp; 68 struct __suio uio; /* output information: summary */ 69 struct __siov iov[NIOV];/* ... and individual io vectors */ 70 }; 71 72 static inline void 73 io_init(struct io_state *iop, FILE *fp) 74 { 75 76 iop->uio.uio_iov = iop->iov; 77 iop->uio.uio_resid = 0; 78 iop->uio.uio_iovcnt = 0; 79 iop->fp = fp; 80 } 81 82 /* 83 * WARNING: The buffer passed to io_print() is not copied immediately; it must 84 * remain valid until io_flush() is called. 85 */ 86 static inline int 87 io_print(struct io_state *iop, const CHAR * __restrict ptr, int len, locale_t locale) 88 { 89 90 iop->iov[iop->uio.uio_iovcnt].iov_base = (char *)ptr; 91 iop->iov[iop->uio.uio_iovcnt].iov_len = len; 92 iop->uio.uio_resid += len; 93 if (++iop->uio.uio_iovcnt >= NIOV) 94 return (__sprint(iop->fp, &iop->uio, locale)); 95 else 96 return (0); 97 } 98 99 /* 100 * Choose PADSIZE to trade efficiency vs. size. If larger printf 101 * fields occur frequently, increase PADSIZE and make the initialisers 102 * below longer. 103 */ 104 #define PADSIZE 16 /* pad chunk size */ 105 static const CHAR blanks[PADSIZE] = 106 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}; 107 static const CHAR zeroes[PADSIZE] = 108 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}; 109 110 /* 111 * Pad with blanks or zeroes. 'with' should point to either the blanks array 112 * or the zeroes array. 113 */ 114 static inline int 115 io_pad(struct io_state *iop, int howmany, const CHAR * __restrict with, 116 locale_t locale) 117 { 118 int n; 119 120 while (howmany > 0) { 121 n = (howmany >= PADSIZE) ? PADSIZE : howmany; 122 if (io_print(iop, with, n, locale)) 123 return (-1); 124 howmany -= n; 125 } 126 return (0); 127 } 128 129 /* 130 * Print exactly len characters of the string spanning p to ep, truncating 131 * or padding with 'with' as necessary. 132 */ 133 static inline int 134 io_printandpad(struct io_state *iop, const CHAR *p, const CHAR *ep, 135 int len, const CHAR * __restrict with, locale_t locale) 136 { 137 int p_len; 138 139 p_len = ep - p; 140 if (p_len > len) 141 p_len = len; 142 if (p_len > 0) { 143 if (io_print(iop, p, p_len, locale)) 144 return (-1); 145 } else { 146 p_len = 0; 147 } 148 return (io_pad(iop, len - p_len, with, locale)); 149 } 150 151 static inline int 152 io_flush(struct io_state *iop, locale_t locale) 153 { 154 155 return (__sprint(iop->fp, &iop->uio, locale)); 156 } 157 158 /* 159 * Convert an unsigned long to ASCII for printf purposes, returning 160 * a pointer to the first character of the string representation. 161 * Octal numbers can be forced to have a leading zero; hex numbers 162 * use the given digits. 163 */ 164 static CHAR * 165 __ultoa(u_long val, CHAR *endp, int base, int octzero, const char *xdigs) 166 { 167 CHAR *cp = endp; 168 long sval; 169 170 /* 171 * Handle the three cases separately, in the hope of getting 172 * better/faster code. 173 */ 174 switch (base) { 175 case 10: 176 if (val < 10) { /* many numbers are 1 digit */ 177 *--cp = to_char(val); 178 return (cp); 179 } 180 /* 181 * On many machines, unsigned arithmetic is harder than 182 * signed arithmetic, so we do at most one unsigned mod and 183 * divide; this is sufficient to reduce the range of 184 * the incoming value to where signed arithmetic works. 185 */ 186 if (val > LONG_MAX) { 187 *--cp = to_char(val % 10); 188 sval = val / 10; 189 } else 190 sval = val; 191 do { 192 *--cp = to_char(sval % 10); 193 sval /= 10; 194 } while (sval != 0); 195 break; 196 197 case 2: 198 do { 199 *--cp = to_char(val & 1); 200 val >>= 1; 201 } while (val); 202 break; 203 204 case 8: 205 do { 206 *--cp = to_char(val & 7); 207 val >>= 3; 208 } while (val); 209 if (octzero && *cp != '0') 210 *--cp = '0'; 211 break; 212 213 case 16: 214 do { 215 *--cp = xdigs[val & 15]; 216 val >>= 4; 217 } while (val); 218 break; 219 220 default: /* oops */ 221 abort(); 222 } 223 return (cp); 224 } 225 226 /* Identical to __ultoa, but for intmax_t. */ 227 static CHAR * 228 __ujtoa(uintmax_t val, CHAR *endp, int base, int octzero, const char *xdigs) 229 { 230 CHAR *cp = endp; 231 intmax_t sval; 232 233 /* quick test for small values; __ultoa is typically much faster */ 234 /* (perhaps instead we should run until small, then call __ultoa?) */ 235 if (val <= ULONG_MAX) 236 return (__ultoa((u_long)val, endp, base, octzero, xdigs)); 237 switch (base) { 238 case 10: 239 if (val < 10) { 240 *--cp = to_char(val % 10); 241 return (cp); 242 } 243 if (val > INTMAX_MAX) { 244 *--cp = to_char(val % 10); 245 sval = val / 10; 246 } else 247 sval = val; 248 do { 249 *--cp = to_char(sval % 10); 250 sval /= 10; 251 } while (sval != 0); 252 break; 253 254 case 2: 255 do { 256 *--cp = to_char(val & 1); 257 val >>= 1; 258 } while (val); 259 break; 260 261 case 8: 262 do { 263 *--cp = to_char(val & 7); 264 val >>= 3; 265 } while (val); 266 if (octzero && *cp != '0') 267 *--cp = '0'; 268 break; 269 270 case 16: 271 do { 272 *--cp = xdigs[val & 15]; 273 val >>= 4; 274 } while (val); 275 break; 276 277 default: 278 abort(); 279 } 280 return (cp); 281 } 282 283 #ifndef NO_FLOATING_POINT 284 285 static int 286 exponent(CHAR *p0, int exp, CHAR fmtch) 287 { 288 CHAR *p, *t; 289 CHAR expbuf[MAXEXPDIG]; 290 291 p = p0; 292 *p++ = fmtch; 293 if (exp < 0) { 294 exp = -exp; 295 *p++ = '-'; 296 } 297 else 298 *p++ = '+'; 299 t = expbuf + MAXEXPDIG; 300 if (exp > 9) { 301 do { 302 *--t = to_char(exp % 10); 303 } while ((exp /= 10) > 9); 304 *--t = to_char(exp); 305 for (; t < expbuf + MAXEXPDIG; *p++ = *t++); 306 } 307 else { 308 /* 309 * Exponents for decimal floating point conversions 310 * (%[eEgG]) must be at least two characters long, 311 * whereas exponents for hexadecimal conversions can 312 * be only one character long. 313 */ 314 if (fmtch == 'e' || fmtch == 'E') 315 *p++ = '0'; 316 *p++ = to_char(exp); 317 } 318 return (p - p0); 319 } 320 321 #endif /* !NO_FLOATING_POINT */ 322