1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 2005 Poul-Henning Kamp 5 * Copyright (c) 1990, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Chris Torek. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * $FreeBSD$ 36 */ 37 38 #include <namespace.h> 39 #include <stdio.h> 40 #include <wchar.h> 41 #include <assert.h> 42 #include <locale.h> 43 #include <limits.h> 44 45 #define dtoa __dtoa 46 #define freedtoa __freedtoa 47 48 #include <float.h> 49 #include <math.h> 50 #include "gdtoa.h" 51 #include "floatio.h" 52 #include "printf.h" 53 #include <un-namespace.h> 54 55 /* 56 * The size of the buffer we use as scratch space for integer 57 * conversions, among other things. Technically, we would need the 58 * most space for base 10 conversions with thousands' grouping 59 * characters between each pair of digits. 100 bytes is a 60 * conservative overestimate even for a 128-bit uintmax_t. 61 */ 62 #define BUF 100 63 64 #define DEFPREC 6 /* Default FP precision */ 65 66 67 /* various globals ---------------------------------------------------*/ 68 69 70 /* padding function---------------------------------------------------*/ 71 72 #define PRINTANDPAD(p, ep, len, with) do { \ 73 n2 = (ep) - (p); \ 74 if (n2 > (len)) \ 75 n2 = (len); \ 76 if (n2 > 0) \ 77 ret += __printf_puts(io, (p), n2); \ 78 ret += __printf_pad(io, (len) - (n2 > 0 ? n2 : 0), (with)); \ 79 } while(0) 80 81 /* misc --------------------------------------------------------------*/ 82 83 #define to_char(n) ((n) + '0') 84 85 static int 86 exponent(char *p0, int expo, int fmtch) 87 { 88 char *p, *t; 89 char expbuf[MAXEXPDIG]; 90 91 p = p0; 92 *p++ = fmtch; 93 if (expo < 0) { 94 expo = -expo; 95 *p++ = '-'; 96 } 97 else 98 *p++ = '+'; 99 t = expbuf + MAXEXPDIG; 100 if (expo > 9) { 101 do { 102 *--t = to_char(expo % 10); 103 } while ((expo /= 10) > 9); 104 *--t = to_char(expo); 105 for (; t < expbuf + MAXEXPDIG; *p++ = *t++) 106 ; 107 } 108 else { 109 /* 110 * Exponents for decimal floating point conversions 111 * (%[eEgG]) must be at least two characters long, 112 * whereas exponents for hexadecimal conversions can 113 * be only one character long. 114 */ 115 if (fmtch == 'e' || fmtch == 'E') 116 *p++ = '0'; 117 *p++ = to_char(expo); 118 } 119 return (p - p0); 120 } 121 122 /* 'f' ---------------------------------------------------------------*/ 123 124 int 125 __printf_arginfo_float(const struct printf_info *pi, size_t n, int *argt) 126 { 127 assert (n > 0); 128 argt[0] = PA_DOUBLE; 129 if (pi->is_long_double) 130 argt[0] |= PA_FLAG_LONG_DOUBLE; 131 return (1); 132 } 133 134 /* 135 * We can decompose the printed representation of floating 136 * point numbers into several parts, some of which may be empty: 137 * 138 * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ 139 * A B ---C--- D E F 140 * 141 * A: 'sign' holds this value if present; '\0' otherwise 142 * B: ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal 143 * C: cp points to the string MMMNNN. Leading and trailing 144 * zeros are not in the string and must be added. 145 * D: expchar holds this character; '\0' if no exponent, e.g. %f 146 * F: at least two digits for decimal, at least one digit for hex 147 */ 148 149 int 150 __printf_render_float(struct __printf_io *io, const struct printf_info *pi, const void *const *arg) 151 { 152 int prec; /* precision from format; <0 for N/A */ 153 char *dtoaresult; /* buffer allocated by dtoa */ 154 char expchar; /* exponent character: [eEpP\0] */ 155 char *cp; 156 int expt; /* integer value of exponent */ 157 int signflag; /* true if float is negative */ 158 char *dtoaend; /* pointer to end of converted digits */ 159 char sign; /* sign prefix (' ', '+', '-', or \0) */ 160 int size; /* size of converted field or string */ 161 int ndig; /* actual number of digits returned by dtoa */ 162 int expsize; /* character count for expstr */ 163 char expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */ 164 int nseps; /* number of group separators with ' */ 165 int nrepeats; /* number of repeats of the last group */ 166 const char *grouping; /* locale specific numeric grouping rules */ 167 int lead; /* sig figs before decimal or group sep */ 168 long double ld; 169 double d; 170 int realsz; /* field size expanded by dprec, sign, etc */ 171 int dprec; /* a copy of prec if [diouxX], 0 otherwise */ 172 char ox[2]; /* space for 0x; ox[1] is either x, X, or \0 */ 173 int ret; /* return value accumulator */ 174 char *decimal_point; /* locale specific decimal point */ 175 int n2; /* XXX: for PRINTANDPAD */ 176 char thousands_sep; /* locale specific thousands separator */ 177 char buf[BUF]; /* buffer with space for digits of uintmax_t */ 178 const char *xdigs; 179 int flag; 180 181 prec = pi->prec; 182 ox[1] = '\0'; 183 sign = pi->showsign; 184 flag = 0; 185 ret = 0; 186 187 thousands_sep = *(localeconv()->thousands_sep); 188 grouping = NULL; 189 if (pi->alt) 190 grouping = localeconv()->grouping; 191 decimal_point = localeconv()->decimal_point; 192 dprec = -1; 193 194 switch(pi->spec) { 195 case 'a': 196 case 'A': 197 if (pi->spec == 'a') { 198 ox[1] = 'x'; 199 xdigs = __lowercase_hex; 200 expchar = 'p'; 201 } else { 202 ox[1] = 'X'; 203 xdigs = __uppercase_hex; 204 expchar = 'P'; 205 } 206 if (prec >= 0) 207 prec++; 208 if (pi->is_long_double) { 209 ld = *((long double *)arg[0]); 210 dtoaresult = cp = 211 __hldtoa(ld, xdigs, prec, 212 &expt, &signflag, &dtoaend); 213 } else { 214 d = *((double *)arg[0]); 215 dtoaresult = cp = 216 __hdtoa(d, xdigs, prec, 217 &expt, &signflag, &dtoaend); 218 } 219 if (prec < 0) 220 prec = dtoaend - cp; 221 if (expt == INT_MAX) 222 ox[1] = '\0'; 223 goto fp_common; 224 case 'e': 225 case 'E': 226 expchar = pi->spec; 227 if (prec < 0) /* account for digit before decpt */ 228 prec = DEFPREC + 1; 229 else 230 prec++; 231 break; 232 case 'f': 233 case 'F': 234 expchar = '\0'; 235 break; 236 case 'g': 237 case 'G': 238 expchar = pi->spec - ('g' - 'e'); 239 if (prec == 0) 240 prec = 1; 241 break; 242 default: 243 assert(pi->spec == 'f'); 244 } 245 246 if (prec < 0) 247 prec = DEFPREC; 248 if (pi->is_long_double) { 249 ld = *((long double *)arg[0]); 250 dtoaresult = cp = 251 __ldtoa(&ld, expchar ? 2 : 3, prec, 252 &expt, &signflag, &dtoaend); 253 } else { 254 d = *((double *)arg[0]); 255 dtoaresult = cp = 256 dtoa(d, expchar ? 2 : 3, prec, 257 &expt, &signflag, &dtoaend); 258 if (expt == 9999) 259 expt = INT_MAX; 260 } 261 fp_common: 262 if (signflag) 263 sign = '-'; 264 if (expt == INT_MAX) { /* inf or nan */ 265 if (*cp == 'N') { 266 cp = (pi->spec >= 'a') ? "nan" : "NAN"; 267 sign = '\0'; 268 } else 269 cp = (pi->spec >= 'a') ? "inf" : "INF"; 270 size = 3; 271 flag = 1; 272 goto here; 273 } 274 ndig = dtoaend - cp; 275 if (pi->spec == 'g' || pi->spec == 'G') { 276 if (expt > -4 && expt <= prec) { 277 /* Make %[gG] smell like %[fF] */ 278 expchar = '\0'; 279 if (pi->alt) 280 prec -= expt; 281 else 282 prec = ndig - expt; 283 if (prec < 0) 284 prec = 0; 285 } else { 286 /* 287 * Make %[gG] smell like %[eE], but 288 * trim trailing zeroes if no # flag. 289 */ 290 if (!pi->alt) 291 prec = ndig; 292 } 293 } 294 if (expchar) { 295 expsize = exponent(expstr, expt - 1, expchar); 296 size = expsize + prec; 297 if (prec > 1 || pi->alt) 298 ++size; 299 } else { 300 /* space for digits before decimal point */ 301 if (expt > 0) 302 size = expt; 303 else /* "0" */ 304 size = 1; 305 /* space for decimal pt and following digits */ 306 if (prec || pi->alt) 307 size += prec + 1; 308 if (grouping && expt > 0) { 309 /* space for thousands' grouping */ 310 nseps = nrepeats = 0; 311 lead = expt; 312 while (*grouping != CHAR_MAX) { 313 if (lead <= *grouping) 314 break; 315 lead -= *grouping; 316 if (*(grouping+1)) { 317 nseps++; 318 grouping++; 319 } else 320 nrepeats++; 321 } 322 size += nseps + nrepeats; 323 } else 324 lead = expt; 325 } 326 327 here: 328 /* 329 * All reasonable formats wind up here. At this point, `cp' 330 * points to a string which (if not flags&LADJUST) should be 331 * padded out to `width' places. If flags&ZEROPAD, it should 332 * first be prefixed by any sign or other prefix; otherwise, 333 * it should be blank padded before the prefix is emitted. 334 * After any left-hand padding and prefixing, emit zeroes 335 * required by a decimal [diouxX] precision, then print the 336 * string proper, then emit zeroes required by any leftover 337 * floating precision; finally, if LADJUST, pad with blanks. 338 * 339 * Compute actual size, so we know how much to pad. 340 * size excludes decimal prec; realsz includes it. 341 */ 342 realsz = dprec > size ? dprec : size; 343 if (sign) 344 realsz++; 345 if (ox[1]) 346 realsz += 2; 347 348 /* right-adjusting blank padding */ 349 if (pi->pad != '0' && pi->left == 0) 350 ret += __printf_pad(io, pi->width - realsz, 0); 351 352 /* prefix */ 353 if (sign) 354 ret += __printf_puts(io, &sign, 1); 355 356 if (ox[1]) { /* ox[1] is either x, X, or \0 */ 357 ox[0] = '0'; 358 ret += __printf_puts(io, ox, 2); 359 } 360 361 /* right-adjusting zero padding */ 362 if (pi->pad == '0' && pi->left == 0) 363 ret += __printf_pad(io, pi->width - realsz, 1); 364 365 /* leading zeroes from decimal precision */ 366 ret += __printf_pad(io, dprec - size, 1); 367 368 if (flag) 369 ret += __printf_puts(io, cp, size); 370 else { 371 /* glue together f_p fragments */ 372 if (!expchar) { /* %[fF] or sufficiently short %[gG] */ 373 if (expt <= 0) { 374 ret += __printf_puts(io, "0", 1); 375 if (prec || pi->alt) 376 ret += __printf_puts(io, decimal_point, 1); 377 ret += __printf_pad(io, -expt, 1); 378 /* already handled initial 0's */ 379 prec += expt; 380 } else { 381 PRINTANDPAD(cp, dtoaend, lead, 1); 382 cp += lead; 383 if (grouping) { 384 while (nseps>0 || nrepeats>0) { 385 if (nrepeats > 0) 386 nrepeats--; 387 else { 388 grouping--; 389 nseps--; 390 } 391 ret += __printf_puts(io, &thousands_sep, 1); 392 PRINTANDPAD(cp,dtoaend, 393 *grouping, 1); 394 cp += *grouping; 395 } 396 if (cp > dtoaend) 397 cp = dtoaend; 398 } 399 if (prec || pi->alt) 400 ret += __printf_puts(io, decimal_point,1); 401 } 402 PRINTANDPAD(cp, dtoaend, prec, 1); 403 } else { /* %[eE] or sufficiently long %[gG] */ 404 if (prec > 1 || pi->alt) { 405 buf[0] = *cp++; 406 buf[1] = *decimal_point; 407 ret += __printf_puts(io, buf, 2); 408 ret += __printf_puts(io, cp, ndig-1); 409 ret += __printf_pad(io, prec - ndig, 1); 410 } else /* XeYYY */ 411 ret += __printf_puts(io, cp, 1); 412 ret += __printf_puts(io, expstr, expsize); 413 } 414 } 415 /* left-adjusting padding (always blank) */ 416 if (pi->left) 417 ret += __printf_pad(io, pi->width - realsz, 0); 418 419 __printf_flush(io); 420 if (dtoaresult != NULL) 421 freedtoa(dtoaresult); 422 423 return (ret); 424 } 425