1153486Sphk/*- 2153486Sphk * Copyright (c) 2005 Poul-Henning Kamp 3153486Sphk * Copyright (c) 1990, 1993 4153486Sphk * The Regents of the University of California. All rights reserved. 5153486Sphk * 6153486Sphk * This code is derived from software contributed to Berkeley by 7153486Sphk * Chris Torek. 8153486Sphk * 9153486Sphk * Redistribution and use in source and binary forms, with or without 10153486Sphk * modification, are permitted provided that the following conditions 11153486Sphk * are met: 12153486Sphk * 1. Redistributions of source code must retain the above copyright 13153486Sphk * notice, this list of conditions and the following disclaimer. 14153486Sphk * 2. Redistributions in binary form must reproduce the above copyright 15153486Sphk * notice, this list of conditions and the following disclaimer in the 16153486Sphk * documentation and/or other materials provided with the distribution. 17153486Sphk * 3. Neither the name of the University nor the names of its contributors 18153486Sphk * may be used to endorse or promote products derived from this software 19153486Sphk * without specific prior written permission. 20153486Sphk * 21153486Sphk * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22153486Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23153486Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24153486Sphk * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25153486Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26153486Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27153486Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28153486Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29153486Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30153486Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31153486Sphk * SUCH DAMAGE. 32153486Sphk * 33153486Sphk * $FreeBSD$ 34153486Sphk */ 35153486Sphk 36153486Sphk#include <namespace.h> 37153486Sphk#include <stdio.h> 38153486Sphk#include <wchar.h> 39153486Sphk#include <assert.h> 40153486Sphk#include <locale.h> 41153486Sphk#include <limits.h> 42153486Sphk 43153486Sphk#define dtoa __dtoa 44153486Sphk#define freedtoa __freedtoa 45153486Sphk 46153486Sphk#include <float.h> 47153486Sphk#include <math.h> 48153486Sphk#include "gdtoa.h" 49153486Sphk#include "floatio.h" 50153486Sphk#include "printf.h" 51153486Sphk#include <un-namespace.h> 52153486Sphk 53153486Sphk/* 54153486Sphk * The size of the buffer we use as scratch space for integer 55153486Sphk * conversions, among other things. Technically, we would need the 56153486Sphk * most space for base 10 conversions with thousands' grouping 57153486Sphk * characters between each pair of digits. 100 bytes is a 58153486Sphk * conservative overestimate even for a 128-bit uintmax_t. 59153486Sphk */ 60153486Sphk#define BUF 100 61153486Sphk 62153486Sphk#define DEFPREC 6 /* Default FP precision */ 63153486Sphk 64153486Sphk 65153486Sphk/* various globals ---------------------------------------------------*/ 66153486Sphk 67153486Sphk 68153486Sphk/* padding function---------------------------------------------------*/ 69153486Sphk 70153486Sphk#define PRINTANDPAD(p, ep, len, with) do { \ 71153486Sphk n2 = (ep) - (p); \ 72153486Sphk if (n2 > (len)) \ 73153486Sphk n2 = (len); \ 74153486Sphk if (n2 > 0) \ 75153486Sphk ret += __printf_puts(io, (p), n2); \ 76153486Sphk ret += __printf_pad(io, (len) - (n2 > 0 ? n2 : 0), (with)); \ 77153486Sphk} while(0) 78153486Sphk 79153486Sphk/* misc --------------------------------------------------------------*/ 80153486Sphk 81153486Sphk#define to_char(n) ((n) + '0') 82153486Sphk 83153486Sphkstatic int 84153486Sphkexponent(char *p0, int expo, int fmtch) 85153486Sphk{ 86153486Sphk char *p, *t; 87153486Sphk char expbuf[MAXEXPDIG]; 88153486Sphk 89153486Sphk p = p0; 90153486Sphk *p++ = fmtch; 91153486Sphk if (expo < 0) { 92153486Sphk expo = -expo; 93153486Sphk *p++ = '-'; 94153486Sphk } 95153486Sphk else 96153486Sphk *p++ = '+'; 97153486Sphk t = expbuf + MAXEXPDIG; 98153486Sphk if (expo > 9) { 99153486Sphk do { 100153486Sphk *--t = to_char(expo % 10); 101153486Sphk } while ((expo /= 10) > 9); 102153486Sphk *--t = to_char(expo); 103153486Sphk for (; t < expbuf + MAXEXPDIG; *p++ = *t++) 104153486Sphk ; 105153486Sphk } 106153486Sphk else { 107153486Sphk /* 108153486Sphk * Exponents for decimal floating point conversions 109153486Sphk * (%[eEgG]) must be at least two characters long, 110153486Sphk * whereas exponents for hexadecimal conversions can 111153486Sphk * be only one character long. 112153486Sphk */ 113153486Sphk if (fmtch == 'e' || fmtch == 'E') 114153486Sphk *p++ = '0'; 115153486Sphk *p++ = to_char(expo); 116153486Sphk } 117153486Sphk return (p - p0); 118153486Sphk} 119153486Sphk 120153486Sphk/* 'f' ---------------------------------------------------------------*/ 121153486Sphk 122153486Sphkint 123153486Sphk__printf_arginfo_float(const struct printf_info *pi, size_t n, int *argt) 124153486Sphk{ 125153486Sphk assert (n > 0); 126153486Sphk argt[0] = PA_DOUBLE; 127153486Sphk if (pi->is_long_double) 128153486Sphk argt[0] |= PA_FLAG_LONG_DOUBLE; 129153486Sphk return (1); 130153486Sphk} 131153486Sphk 132153486Sphk/* 133153486Sphk * We can decompose the printed representation of floating 134153486Sphk * point numbers into several parts, some of which may be empty: 135153486Sphk * 136153486Sphk * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ 137153486Sphk * A B ---C--- D E F 138153486Sphk * 139153486Sphk * A: 'sign' holds this value if present; '\0' otherwise 140153486Sphk * B: ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal 141153486Sphk * C: cp points to the string MMMNNN. Leading and trailing 142153486Sphk * zeros are not in the string and must be added. 143153486Sphk * D: expchar holds this character; '\0' if no exponent, e.g. %f 144153486Sphk * F: at least two digits for decimal, at least one digit for hex 145153486Sphk */ 146153486Sphk 147153486Sphkint 148153486Sphk__printf_render_float(struct __printf_io *io, const struct printf_info *pi, const void *const *arg) 149153486Sphk{ 150153486Sphk int prec; /* precision from format; <0 for N/A */ 151153486Sphk char *dtoaresult; /* buffer allocated by dtoa */ 152153486Sphk char expchar; /* exponent character: [eEpP\0] */ 153153486Sphk char *cp; 154153486Sphk int expt; /* integer value of exponent */ 155153486Sphk int signflag; /* true if float is negative */ 156153486Sphk char *dtoaend; /* pointer to end of converted digits */ 157153486Sphk char sign; /* sign prefix (' ', '+', '-', or \0) */ 158153486Sphk int size; /* size of converted field or string */ 159153486Sphk int ndig; /* actual number of digits returned by dtoa */ 160153486Sphk int expsize; /* character count for expstr */ 161153486Sphk char expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */ 162153486Sphk int nseps; /* number of group separators with ' */ 163153486Sphk int nrepeats; /* number of repeats of the last group */ 164153486Sphk const char *grouping; /* locale specific numeric grouping rules */ 165153486Sphk int lead; /* sig figs before decimal or group sep */ 166153486Sphk long double ld; 167153486Sphk double d; 168153486Sphk int realsz; /* field size expanded by dprec, sign, etc */ 169153486Sphk int dprec; /* a copy of prec if [diouxX], 0 otherwise */ 170153486Sphk char ox[2]; /* space for 0x; ox[1] is either x, X, or \0 */ 171153486Sphk int prsize; /* max size of printed field */ 172153486Sphk int ret; /* return value accumulator */ 173153486Sphk char *decimal_point; /* locale specific decimal point */ 174153486Sphk int n2; /* XXX: for PRINTANDPAD */ 175153486Sphk char thousands_sep; /* locale specific thousands separator */ 176153486Sphk char buf[BUF]; /* buffer with space for digits of uintmax_t */ 177153486Sphk const char *xdigs; 178153486Sphk int flag; 179153486Sphk 180153486Sphk prec = pi->prec; 181153486Sphk ox[1] = '\0'; 182153486Sphk sign = pi->showsign; 183153486Sphk flag = 0; 184153486Sphk ret = 0; 185153486Sphk 186153486Sphk thousands_sep = *(localeconv()->thousands_sep); 187153486Sphk grouping = NULL; 188153486Sphk if (pi->alt) 189153486Sphk grouping = localeconv()->grouping; 190153486Sphk decimal_point = localeconv()->decimal_point; 191153486Sphk dprec = -1; 192153486Sphk 193153486Sphk switch(pi->spec) { 194153486Sphk case 'a': 195153486Sphk case 'A': 196153486Sphk if (pi->spec == 'a') { 197153486Sphk ox[1] = 'x'; 198153486Sphk xdigs = __lowercase_hex; 199153486Sphk expchar = 'p'; 200153486Sphk } else { 201153486Sphk ox[1] = 'X'; 202153486Sphk xdigs = __uppercase_hex; 203153486Sphk expchar = 'P'; 204153486Sphk } 205153486Sphk if (prec >= 0) 206153486Sphk prec++; 207153486Sphk if (pi->is_long_double) { 208153486Sphk ld = *((long double *)arg[0]); 209153486Sphk dtoaresult = cp = 210153486Sphk __hldtoa(ld, xdigs, prec, 211153486Sphk &expt, &signflag, &dtoaend); 212153486Sphk } else { 213153486Sphk d = *((double *)arg[0]); 214153486Sphk dtoaresult = cp = 215153486Sphk __hdtoa(d, xdigs, prec, 216153486Sphk &expt, &signflag, &dtoaend); 217153486Sphk } 218153486Sphk if (prec < 0) 219153486Sphk prec = dtoaend - cp; 220153486Sphk if (expt == INT_MAX) 221153486Sphk ox[1] = '\0'; 222153486Sphk goto fp_common; 223153486Sphk case 'e': 224153486Sphk case 'E': 225153486Sphk expchar = pi->spec; 226153486Sphk if (prec < 0) /* account for digit before decpt */ 227153486Sphk prec = DEFPREC + 1; 228153486Sphk else 229153486Sphk prec++; 230153486Sphk break; 231153486Sphk case 'f': 232153486Sphk case 'F': 233153486Sphk expchar = '\0'; 234153486Sphk break; 235153486Sphk case 'g': 236153486Sphk case 'G': 237153486Sphk expchar = pi->spec - ('g' - 'e'); 238153486Sphk if (prec == 0) 239153486Sphk prec = 1; 240153486Sphk break; 241153486Sphk default: 242153486Sphk assert(pi->spec == 'f'); 243153486Sphk } 244153486Sphk 245153486Sphk if (prec < 0) 246153486Sphk prec = DEFPREC; 247153486Sphk if (pi->is_long_double) { 248153486Sphk ld = *((long double *)arg[0]); 249153486Sphk dtoaresult = cp = 250153486Sphk __ldtoa(&ld, expchar ? 2 : 3, prec, 251153486Sphk &expt, &signflag, &dtoaend); 252153486Sphk } else { 253153486Sphk d = *((double *)arg[0]); 254153486Sphk dtoaresult = cp = 255153486Sphk dtoa(d, expchar ? 2 : 3, prec, 256153486Sphk &expt, &signflag, &dtoaend); 257153486Sphk if (expt == 9999) 258153486Sphk expt = INT_MAX; 259153486Sphk } 260153486Sphkfp_common: 261153486Sphk if (signflag) 262153486Sphk sign = '-'; 263153486Sphk if (expt == INT_MAX) { /* inf or nan */ 264153486Sphk if (*cp == 'N') { 265153486Sphk cp = (pi->spec >= 'a') ? "nan" : "NAN"; 266153486Sphk sign = '\0'; 267153486Sphk } else 268153486Sphk cp = (pi->spec >= 'a') ? "inf" : "INF"; 269153486Sphk size = 3; 270153486Sphk flag = 1; 271153486Sphk goto here; 272153486Sphk } 273153486Sphk ndig = dtoaend - cp; 274153486Sphk if (pi->spec == 'g' || pi->spec == 'G') { 275153486Sphk if (expt > -4 && expt <= prec) { 276153486Sphk /* Make %[gG] smell like %[fF] */ 277153486Sphk expchar = '\0'; 278153486Sphk if (pi->alt) 279153486Sphk prec -= expt; 280153486Sphk else 281153486Sphk prec = ndig - expt; 282153486Sphk if (prec < 0) 283153486Sphk prec = 0; 284153486Sphk } else { 285153486Sphk /* 286153486Sphk * Make %[gG] smell like %[eE], but 287153486Sphk * trim trailing zeroes if no # flag. 288153486Sphk */ 289153486Sphk if (!pi->alt) 290153486Sphk prec = ndig; 291153486Sphk } 292153486Sphk } 293153486Sphk if (expchar) { 294153486Sphk expsize = exponent(expstr, expt - 1, expchar); 295153486Sphk size = expsize + prec; 296153486Sphk if (prec > 1 || pi->alt) 297153486Sphk ++size; 298153486Sphk } else { 299153486Sphk /* space for digits before decimal point */ 300153486Sphk if (expt > 0) 301153486Sphk size = expt; 302153486Sphk else /* "0" */ 303153486Sphk size = 1; 304153486Sphk /* space for decimal pt and following digits */ 305153486Sphk if (prec || pi->alt) 306153486Sphk size += prec + 1; 307153486Sphk if (grouping && expt > 0) { 308153486Sphk /* space for thousands' grouping */ 309153486Sphk nseps = nrepeats = 0; 310153486Sphk lead = expt; 311153486Sphk while (*grouping != CHAR_MAX) { 312153486Sphk if (lead <= *grouping) 313153486Sphk break; 314153486Sphk lead -= *grouping; 315153486Sphk if (*(grouping+1)) { 316153486Sphk nseps++; 317153486Sphk grouping++; 318153486Sphk } else 319153486Sphk nrepeats++; 320153486Sphk } 321153486Sphk size += nseps + nrepeats; 322153486Sphk } else 323153486Sphk lead = expt; 324153486Sphk } 325153486Sphk 326153486Sphkhere: 327153486Sphk /* 328153486Sphk * All reasonable formats wind up here. At this point, `cp' 329153486Sphk * points to a string which (if not flags&LADJUST) should be 330153486Sphk * padded out to `width' places. If flags&ZEROPAD, it should 331153486Sphk * first be prefixed by any sign or other prefix; otherwise, 332153486Sphk * it should be blank padded before the prefix is emitted. 333153486Sphk * After any left-hand padding and prefixing, emit zeroes 334153486Sphk * required by a decimal [diouxX] precision, then print the 335153486Sphk * string proper, then emit zeroes required by any leftover 336153486Sphk * floating precision; finally, if LADJUST, pad with blanks. 337153486Sphk * 338153486Sphk * Compute actual size, so we know how much to pad. 339153486Sphk * size excludes decimal prec; realsz includes it. 340153486Sphk */ 341153486Sphk realsz = dprec > size ? dprec : size; 342153486Sphk if (sign) 343153486Sphk realsz++; 344153486Sphk if (ox[1]) 345153486Sphk realsz += 2; 346153486Sphk 347153486Sphk prsize = pi->width > realsz ? pi->width : realsz; 348153486Sphk 349153486Sphk /* right-adjusting blank padding */ 350153486Sphk if (pi->pad != '0' && pi->left == 0) 351153486Sphk ret += __printf_pad(io, pi->width - realsz, 0); 352153486Sphk 353153486Sphk /* prefix */ 354153486Sphk if (sign) 355153486Sphk ret += __printf_puts(io, &sign, 1); 356153486Sphk 357153486Sphk if (ox[1]) { /* ox[1] is either x, X, or \0 */ 358153486Sphk ox[0] = '0'; 359153486Sphk ret += __printf_puts(io, ox, 2); 360153486Sphk } 361153486Sphk 362153486Sphk /* right-adjusting zero padding */ 363153486Sphk if (pi->pad == '0' && pi->left == 0) 364153486Sphk ret += __printf_pad(io, pi->width - realsz, 1); 365153486Sphk 366153486Sphk /* leading zeroes from decimal precision */ 367153486Sphk ret += __printf_pad(io, dprec - size, 1); 368153486Sphk 369153486Sphk if (flag) 370153486Sphk ret += __printf_puts(io, cp, size); 371153486Sphk else { 372153486Sphk /* glue together f_p fragments */ 373153486Sphk if (!expchar) { /* %[fF] or sufficiently short %[gG] */ 374153486Sphk if (expt <= 0) { 375153486Sphk ret += __printf_puts(io, "0", 1); 376153486Sphk if (prec || pi->alt) 377153486Sphk ret += __printf_puts(io, decimal_point, 1); 378153486Sphk ret += __printf_pad(io, -expt, 1); 379153486Sphk /* already handled initial 0's */ 380153486Sphk prec += expt; 381153486Sphk } else { 382153486Sphk PRINTANDPAD(cp, dtoaend, lead, 1); 383153486Sphk cp += lead; 384153486Sphk if (grouping) { 385153486Sphk while (nseps>0 || nrepeats>0) { 386153486Sphk if (nrepeats > 0) 387153486Sphk nrepeats--; 388153486Sphk else { 389153486Sphk grouping--; 390153486Sphk nseps--; 391153486Sphk } 392153486Sphk ret += __printf_puts(io, &thousands_sep, 1); 393153486Sphk PRINTANDPAD(cp,dtoaend, 394153486Sphk *grouping, 1); 395153486Sphk cp += *grouping; 396153486Sphk } 397153486Sphk if (cp > dtoaend) 398153486Sphk cp = dtoaend; 399153486Sphk } 400153486Sphk if (prec || pi->alt) 401153486Sphk ret += __printf_puts(io, decimal_point,1); 402153486Sphk } 403153486Sphk PRINTANDPAD(cp, dtoaend, prec, 1); 404153486Sphk } else { /* %[eE] or sufficiently long %[gG] */ 405153486Sphk if (prec > 1 || pi->alt) { 406153486Sphk buf[0] = *cp++; 407153486Sphk buf[1] = *decimal_point; 408153486Sphk ret += __printf_puts(io, buf, 2); 409153486Sphk ret += __printf_puts(io, cp, ndig-1); 410153486Sphk ret += __printf_pad(io, prec - ndig, 1); 411153486Sphk } else /* XeYYY */ 412153486Sphk ret += __printf_puts(io, cp, 1); 413153486Sphk ret += __printf_puts(io, expstr, expsize); 414153486Sphk } 415153486Sphk } 416153486Sphk /* left-adjusting padding (always blank) */ 417153486Sphk if (pi->left) 418153486Sphk ret += __printf_pad(io, pi->width - realsz, 0); 419153486Sphk 420153486Sphk __printf_flush(io); 421153486Sphk if (dtoaresult != NULL) 422153486Sphk freedtoa(dtoaresult); 423153486Sphk 424153486Sphk return (ret); 425153486Sphk} 426