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$ 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 53 static int exponent(CHAR *, int, CHAR); 54 55 #endif /* !NO_FLOATING_POINT */ 56 57 static CHAR *__ujtoa(uintmax_t, CHAR *, int, int, const char *); 58 static CHAR *__ultoa(u_long, CHAR *, int, int, const char *); 59 60 #define NIOV 8 61 struct io_state { 62 FILE *fp; 63 struct __suio uio; /* output information: summary */ 64 struct __siov iov[NIOV];/* ... and individual io vectors */ 65 }; 66 67 static inline void 68 io_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 */ 81 static inline int 82 io_print(struct io_state *iop, const CHAR * __restrict ptr, int len) 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, &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 */ 100 static const CHAR blanks[PADSIZE] = 101 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}; 102 static 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 */ 109 static inline int 110 io_pad(struct io_state *iop, int howmany, const CHAR * __restrict with) 111 { 112 int n; 113 114 while (howmany > 0) { 115 n = (howmany >= PADSIZE) ? PADSIZE : howmany; 116 if (io_print(iop, with, n)) 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 */ 127 static inline int 128 io_printandpad(struct io_state *iop, const CHAR *p, const CHAR *ep, 129 int len, const CHAR * __restrict with) 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)) 138 return (-1); 139 } else { 140 p_len = 0; 141 } 142 return (io_pad(iop, len - p_len, with)); 143 } 144 145 static inline int 146 io_flush(struct io_state *iop) 147 { 148 149 return (__sprint(iop->fp, &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 */ 158 static 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 abort(); 209 } 210 return (cp); 211 } 212 213 /* Identical to __ultoa, but for intmax_t. */ 214 static 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 abort(); 259 } 260 return (cp); 261 } 262 263 #ifndef NO_FLOATING_POINT 264 265 static int 266 exponent(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