175067f4fSPoul-Henning Kamp /*- 2*8a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 3*8a16b7a1SPedro F. Giffuni * 475067f4fSPoul-Henning Kamp * Copyright (c) 2005 Poul-Henning Kamp 575067f4fSPoul-Henning Kamp * Copyright (c) 1990, 1993 675067f4fSPoul-Henning Kamp * The Regents of the University of California. All rights reserved. 775067f4fSPoul-Henning Kamp * 875067f4fSPoul-Henning Kamp * This code is derived from software contributed to Berkeley by 975067f4fSPoul-Henning Kamp * Chris Torek. 1075067f4fSPoul-Henning Kamp * 1175067f4fSPoul-Henning Kamp * Redistribution and use in source and binary forms, with or without 1275067f4fSPoul-Henning Kamp * modification, are permitted provided that the following conditions 1375067f4fSPoul-Henning Kamp * are met: 1475067f4fSPoul-Henning Kamp * 1. Redistributions of source code must retain the above copyright 1575067f4fSPoul-Henning Kamp * notice, this list of conditions and the following disclaimer. 1675067f4fSPoul-Henning Kamp * 2. Redistributions in binary form must reproduce the above copyright 1775067f4fSPoul-Henning Kamp * notice, this list of conditions and the following disclaimer in the 1875067f4fSPoul-Henning Kamp * documentation and/or other materials provided with the distribution. 1975067f4fSPoul-Henning Kamp * 3. Neither the name of the University nor the names of its contributors 2075067f4fSPoul-Henning Kamp * may be used to endorse or promote products derived from this software 2175067f4fSPoul-Henning Kamp * without specific prior written permission. 2275067f4fSPoul-Henning Kamp * 2375067f4fSPoul-Henning Kamp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2475067f4fSPoul-Henning Kamp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2575067f4fSPoul-Henning Kamp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2675067f4fSPoul-Henning Kamp * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2775067f4fSPoul-Henning Kamp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2875067f4fSPoul-Henning Kamp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2975067f4fSPoul-Henning Kamp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3075067f4fSPoul-Henning Kamp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3175067f4fSPoul-Henning Kamp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3275067f4fSPoul-Henning Kamp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3375067f4fSPoul-Henning Kamp * SUCH DAMAGE. 3475067f4fSPoul-Henning Kamp * 3575067f4fSPoul-Henning Kamp * $FreeBSD$ 3675067f4fSPoul-Henning Kamp */ 3775067f4fSPoul-Henning Kamp 3875067f4fSPoul-Henning Kamp #include <namespace.h> 3975067f4fSPoul-Henning Kamp #include <stdio.h> 4075067f4fSPoul-Henning Kamp #include <wchar.h> 4175067f4fSPoul-Henning Kamp #include <assert.h> 4275067f4fSPoul-Henning Kamp #include <locale.h> 4375067f4fSPoul-Henning Kamp #include <limits.h> 4475067f4fSPoul-Henning Kamp 4575067f4fSPoul-Henning Kamp #define dtoa __dtoa 4675067f4fSPoul-Henning Kamp #define freedtoa __freedtoa 4775067f4fSPoul-Henning Kamp 4875067f4fSPoul-Henning Kamp #include <float.h> 4975067f4fSPoul-Henning Kamp #include <math.h> 5075067f4fSPoul-Henning Kamp #include "gdtoa.h" 5175067f4fSPoul-Henning Kamp #include "floatio.h" 5275067f4fSPoul-Henning Kamp #include "printf.h" 5375067f4fSPoul-Henning Kamp #include <un-namespace.h> 5475067f4fSPoul-Henning Kamp 5575067f4fSPoul-Henning Kamp /* 5675067f4fSPoul-Henning Kamp * The size of the buffer we use as scratch space for integer 5775067f4fSPoul-Henning Kamp * conversions, among other things. Technically, we would need the 5875067f4fSPoul-Henning Kamp * most space for base 10 conversions with thousands' grouping 5975067f4fSPoul-Henning Kamp * characters between each pair of digits. 100 bytes is a 6075067f4fSPoul-Henning Kamp * conservative overestimate even for a 128-bit uintmax_t. 6175067f4fSPoul-Henning Kamp */ 6275067f4fSPoul-Henning Kamp #define BUF 100 6375067f4fSPoul-Henning Kamp 6475067f4fSPoul-Henning Kamp #define DEFPREC 6 /* Default FP precision */ 6575067f4fSPoul-Henning Kamp 6675067f4fSPoul-Henning Kamp 6775067f4fSPoul-Henning Kamp /* various globals ---------------------------------------------------*/ 6875067f4fSPoul-Henning Kamp 6975067f4fSPoul-Henning Kamp 7075067f4fSPoul-Henning Kamp /* padding function---------------------------------------------------*/ 7175067f4fSPoul-Henning Kamp 7275067f4fSPoul-Henning Kamp #define PRINTANDPAD(p, ep, len, with) do { \ 7375067f4fSPoul-Henning Kamp n2 = (ep) - (p); \ 7475067f4fSPoul-Henning Kamp if (n2 > (len)) \ 7575067f4fSPoul-Henning Kamp n2 = (len); \ 7675067f4fSPoul-Henning Kamp if (n2 > 0) \ 7775067f4fSPoul-Henning Kamp ret += __printf_puts(io, (p), n2); \ 7875067f4fSPoul-Henning Kamp ret += __printf_pad(io, (len) - (n2 > 0 ? n2 : 0), (with)); \ 7975067f4fSPoul-Henning Kamp } while(0) 8075067f4fSPoul-Henning Kamp 8175067f4fSPoul-Henning Kamp /* misc --------------------------------------------------------------*/ 8275067f4fSPoul-Henning Kamp 8375067f4fSPoul-Henning Kamp #define to_char(n) ((n) + '0') 8475067f4fSPoul-Henning Kamp 8575067f4fSPoul-Henning Kamp static int 8675067f4fSPoul-Henning Kamp exponent(char *p0, int expo, int fmtch) 8775067f4fSPoul-Henning Kamp { 8875067f4fSPoul-Henning Kamp char *p, *t; 8975067f4fSPoul-Henning Kamp char expbuf[MAXEXPDIG]; 9075067f4fSPoul-Henning Kamp 9175067f4fSPoul-Henning Kamp p = p0; 9275067f4fSPoul-Henning Kamp *p++ = fmtch; 9375067f4fSPoul-Henning Kamp if (expo < 0) { 9475067f4fSPoul-Henning Kamp expo = -expo; 9575067f4fSPoul-Henning Kamp *p++ = '-'; 9675067f4fSPoul-Henning Kamp } 9775067f4fSPoul-Henning Kamp else 9875067f4fSPoul-Henning Kamp *p++ = '+'; 9975067f4fSPoul-Henning Kamp t = expbuf + MAXEXPDIG; 10075067f4fSPoul-Henning Kamp if (expo > 9) { 10175067f4fSPoul-Henning Kamp do { 10275067f4fSPoul-Henning Kamp *--t = to_char(expo % 10); 10375067f4fSPoul-Henning Kamp } while ((expo /= 10) > 9); 10475067f4fSPoul-Henning Kamp *--t = to_char(expo); 10575067f4fSPoul-Henning Kamp for (; t < expbuf + MAXEXPDIG; *p++ = *t++) 10675067f4fSPoul-Henning Kamp ; 10775067f4fSPoul-Henning Kamp } 10875067f4fSPoul-Henning Kamp else { 10975067f4fSPoul-Henning Kamp /* 11075067f4fSPoul-Henning Kamp * Exponents for decimal floating point conversions 11175067f4fSPoul-Henning Kamp * (%[eEgG]) must be at least two characters long, 11275067f4fSPoul-Henning Kamp * whereas exponents for hexadecimal conversions can 11375067f4fSPoul-Henning Kamp * be only one character long. 11475067f4fSPoul-Henning Kamp */ 11575067f4fSPoul-Henning Kamp if (fmtch == 'e' || fmtch == 'E') 11675067f4fSPoul-Henning Kamp *p++ = '0'; 11775067f4fSPoul-Henning Kamp *p++ = to_char(expo); 11875067f4fSPoul-Henning Kamp } 11975067f4fSPoul-Henning Kamp return (p - p0); 12075067f4fSPoul-Henning Kamp } 12175067f4fSPoul-Henning Kamp 12275067f4fSPoul-Henning Kamp /* 'f' ---------------------------------------------------------------*/ 12375067f4fSPoul-Henning Kamp 12475067f4fSPoul-Henning Kamp int 12575067f4fSPoul-Henning Kamp __printf_arginfo_float(const struct printf_info *pi, size_t n, int *argt) 12675067f4fSPoul-Henning Kamp { 12775067f4fSPoul-Henning Kamp assert (n > 0); 12875067f4fSPoul-Henning Kamp argt[0] = PA_DOUBLE; 12975067f4fSPoul-Henning Kamp if (pi->is_long_double) 13075067f4fSPoul-Henning Kamp argt[0] |= PA_FLAG_LONG_DOUBLE; 13175067f4fSPoul-Henning Kamp return (1); 13275067f4fSPoul-Henning Kamp } 13375067f4fSPoul-Henning Kamp 13475067f4fSPoul-Henning Kamp /* 13575067f4fSPoul-Henning Kamp * We can decompose the printed representation of floating 13675067f4fSPoul-Henning Kamp * point numbers into several parts, some of which may be empty: 13775067f4fSPoul-Henning Kamp * 13875067f4fSPoul-Henning Kamp * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ 13975067f4fSPoul-Henning Kamp * A B ---C--- D E F 14075067f4fSPoul-Henning Kamp * 14175067f4fSPoul-Henning Kamp * A: 'sign' holds this value if present; '\0' otherwise 14275067f4fSPoul-Henning Kamp * B: ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal 14375067f4fSPoul-Henning Kamp * C: cp points to the string MMMNNN. Leading and trailing 14475067f4fSPoul-Henning Kamp * zeros are not in the string and must be added. 14575067f4fSPoul-Henning Kamp * D: expchar holds this character; '\0' if no exponent, e.g. %f 14675067f4fSPoul-Henning Kamp * F: at least two digits for decimal, at least one digit for hex 14775067f4fSPoul-Henning Kamp */ 14875067f4fSPoul-Henning Kamp 14975067f4fSPoul-Henning Kamp int 15075067f4fSPoul-Henning Kamp __printf_render_float(struct __printf_io *io, const struct printf_info *pi, const void *const *arg) 15175067f4fSPoul-Henning Kamp { 15275067f4fSPoul-Henning Kamp int prec; /* precision from format; <0 for N/A */ 15375067f4fSPoul-Henning Kamp char *dtoaresult; /* buffer allocated by dtoa */ 15475067f4fSPoul-Henning Kamp char expchar; /* exponent character: [eEpP\0] */ 15575067f4fSPoul-Henning Kamp char *cp; 15675067f4fSPoul-Henning Kamp int expt; /* integer value of exponent */ 15775067f4fSPoul-Henning Kamp int signflag; /* true if float is negative */ 15875067f4fSPoul-Henning Kamp char *dtoaend; /* pointer to end of converted digits */ 15975067f4fSPoul-Henning Kamp char sign; /* sign prefix (' ', '+', '-', or \0) */ 16075067f4fSPoul-Henning Kamp int size; /* size of converted field or string */ 16175067f4fSPoul-Henning Kamp int ndig; /* actual number of digits returned by dtoa */ 16275067f4fSPoul-Henning Kamp int expsize; /* character count for expstr */ 16375067f4fSPoul-Henning Kamp char expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */ 16475067f4fSPoul-Henning Kamp int nseps; /* number of group separators with ' */ 16575067f4fSPoul-Henning Kamp int nrepeats; /* number of repeats of the last group */ 16675067f4fSPoul-Henning Kamp const char *grouping; /* locale specific numeric grouping rules */ 16775067f4fSPoul-Henning Kamp int lead; /* sig figs before decimal or group sep */ 16875067f4fSPoul-Henning Kamp long double ld; 16975067f4fSPoul-Henning Kamp double d; 17075067f4fSPoul-Henning Kamp int realsz; /* field size expanded by dprec, sign, etc */ 17175067f4fSPoul-Henning Kamp int dprec; /* a copy of prec if [diouxX], 0 otherwise */ 17275067f4fSPoul-Henning Kamp char ox[2]; /* space for 0x; ox[1] is either x, X, or \0 */ 17375067f4fSPoul-Henning Kamp int ret; /* return value accumulator */ 17475067f4fSPoul-Henning Kamp char *decimal_point; /* locale specific decimal point */ 17575067f4fSPoul-Henning Kamp int n2; /* XXX: for PRINTANDPAD */ 17675067f4fSPoul-Henning Kamp char thousands_sep; /* locale specific thousands separator */ 17775067f4fSPoul-Henning Kamp char buf[BUF]; /* buffer with space for digits of uintmax_t */ 17875067f4fSPoul-Henning Kamp const char *xdigs; 17975067f4fSPoul-Henning Kamp int flag; 18075067f4fSPoul-Henning Kamp 18175067f4fSPoul-Henning Kamp prec = pi->prec; 18275067f4fSPoul-Henning Kamp ox[1] = '\0'; 18375067f4fSPoul-Henning Kamp sign = pi->showsign; 18475067f4fSPoul-Henning Kamp flag = 0; 18575067f4fSPoul-Henning Kamp ret = 0; 18675067f4fSPoul-Henning Kamp 18775067f4fSPoul-Henning Kamp thousands_sep = *(localeconv()->thousands_sep); 18875067f4fSPoul-Henning Kamp grouping = NULL; 18975067f4fSPoul-Henning Kamp if (pi->alt) 19075067f4fSPoul-Henning Kamp grouping = localeconv()->grouping; 19175067f4fSPoul-Henning Kamp decimal_point = localeconv()->decimal_point; 19275067f4fSPoul-Henning Kamp dprec = -1; 19375067f4fSPoul-Henning Kamp 19475067f4fSPoul-Henning Kamp switch(pi->spec) { 19575067f4fSPoul-Henning Kamp case 'a': 19675067f4fSPoul-Henning Kamp case 'A': 19775067f4fSPoul-Henning Kamp if (pi->spec == 'a') { 19875067f4fSPoul-Henning Kamp ox[1] = 'x'; 19975067f4fSPoul-Henning Kamp xdigs = __lowercase_hex; 20075067f4fSPoul-Henning Kamp expchar = 'p'; 20175067f4fSPoul-Henning Kamp } else { 20275067f4fSPoul-Henning Kamp ox[1] = 'X'; 20375067f4fSPoul-Henning Kamp xdigs = __uppercase_hex; 20475067f4fSPoul-Henning Kamp expchar = 'P'; 20575067f4fSPoul-Henning Kamp } 20675067f4fSPoul-Henning Kamp if (prec >= 0) 20775067f4fSPoul-Henning Kamp prec++; 20875067f4fSPoul-Henning Kamp if (pi->is_long_double) { 20975067f4fSPoul-Henning Kamp ld = *((long double *)arg[0]); 21075067f4fSPoul-Henning Kamp dtoaresult = cp = 21175067f4fSPoul-Henning Kamp __hldtoa(ld, xdigs, prec, 21275067f4fSPoul-Henning Kamp &expt, &signflag, &dtoaend); 21375067f4fSPoul-Henning Kamp } else { 21475067f4fSPoul-Henning Kamp d = *((double *)arg[0]); 21575067f4fSPoul-Henning Kamp dtoaresult = cp = 21675067f4fSPoul-Henning Kamp __hdtoa(d, xdigs, prec, 21775067f4fSPoul-Henning Kamp &expt, &signflag, &dtoaend); 21875067f4fSPoul-Henning Kamp } 21975067f4fSPoul-Henning Kamp if (prec < 0) 22075067f4fSPoul-Henning Kamp prec = dtoaend - cp; 22175067f4fSPoul-Henning Kamp if (expt == INT_MAX) 22275067f4fSPoul-Henning Kamp ox[1] = '\0'; 22375067f4fSPoul-Henning Kamp goto fp_common; 22475067f4fSPoul-Henning Kamp case 'e': 22575067f4fSPoul-Henning Kamp case 'E': 22675067f4fSPoul-Henning Kamp expchar = pi->spec; 22775067f4fSPoul-Henning Kamp if (prec < 0) /* account for digit before decpt */ 22875067f4fSPoul-Henning Kamp prec = DEFPREC + 1; 22975067f4fSPoul-Henning Kamp else 23075067f4fSPoul-Henning Kamp prec++; 23175067f4fSPoul-Henning Kamp break; 23275067f4fSPoul-Henning Kamp case 'f': 23375067f4fSPoul-Henning Kamp case 'F': 23475067f4fSPoul-Henning Kamp expchar = '\0'; 23575067f4fSPoul-Henning Kamp break; 23675067f4fSPoul-Henning Kamp case 'g': 23775067f4fSPoul-Henning Kamp case 'G': 23875067f4fSPoul-Henning Kamp expchar = pi->spec - ('g' - 'e'); 23975067f4fSPoul-Henning Kamp if (prec == 0) 24075067f4fSPoul-Henning Kamp prec = 1; 24175067f4fSPoul-Henning Kamp break; 24275067f4fSPoul-Henning Kamp default: 24375067f4fSPoul-Henning Kamp assert(pi->spec == 'f'); 24475067f4fSPoul-Henning Kamp } 24575067f4fSPoul-Henning Kamp 24675067f4fSPoul-Henning Kamp if (prec < 0) 24775067f4fSPoul-Henning Kamp prec = DEFPREC; 24875067f4fSPoul-Henning Kamp if (pi->is_long_double) { 24975067f4fSPoul-Henning Kamp ld = *((long double *)arg[0]); 25075067f4fSPoul-Henning Kamp dtoaresult = cp = 25175067f4fSPoul-Henning Kamp __ldtoa(&ld, expchar ? 2 : 3, prec, 25275067f4fSPoul-Henning Kamp &expt, &signflag, &dtoaend); 25375067f4fSPoul-Henning Kamp } else { 25475067f4fSPoul-Henning Kamp d = *((double *)arg[0]); 25575067f4fSPoul-Henning Kamp dtoaresult = cp = 25675067f4fSPoul-Henning Kamp dtoa(d, expchar ? 2 : 3, prec, 25775067f4fSPoul-Henning Kamp &expt, &signflag, &dtoaend); 25875067f4fSPoul-Henning Kamp if (expt == 9999) 25975067f4fSPoul-Henning Kamp expt = INT_MAX; 26075067f4fSPoul-Henning Kamp } 26175067f4fSPoul-Henning Kamp fp_common: 26275067f4fSPoul-Henning Kamp if (signflag) 26375067f4fSPoul-Henning Kamp sign = '-'; 26475067f4fSPoul-Henning Kamp if (expt == INT_MAX) { /* inf or nan */ 26575067f4fSPoul-Henning Kamp if (*cp == 'N') { 26675067f4fSPoul-Henning Kamp cp = (pi->spec >= 'a') ? "nan" : "NAN"; 26775067f4fSPoul-Henning Kamp sign = '\0'; 26875067f4fSPoul-Henning Kamp } else 26975067f4fSPoul-Henning Kamp cp = (pi->spec >= 'a') ? "inf" : "INF"; 27075067f4fSPoul-Henning Kamp size = 3; 27175067f4fSPoul-Henning Kamp flag = 1; 27275067f4fSPoul-Henning Kamp goto here; 27375067f4fSPoul-Henning Kamp } 27475067f4fSPoul-Henning Kamp ndig = dtoaend - cp; 27575067f4fSPoul-Henning Kamp if (pi->spec == 'g' || pi->spec == 'G') { 27675067f4fSPoul-Henning Kamp if (expt > -4 && expt <= prec) { 27775067f4fSPoul-Henning Kamp /* Make %[gG] smell like %[fF] */ 27875067f4fSPoul-Henning Kamp expchar = '\0'; 27975067f4fSPoul-Henning Kamp if (pi->alt) 28075067f4fSPoul-Henning Kamp prec -= expt; 28175067f4fSPoul-Henning Kamp else 28275067f4fSPoul-Henning Kamp prec = ndig - expt; 28375067f4fSPoul-Henning Kamp if (prec < 0) 28475067f4fSPoul-Henning Kamp prec = 0; 28575067f4fSPoul-Henning Kamp } else { 28675067f4fSPoul-Henning Kamp /* 28775067f4fSPoul-Henning Kamp * Make %[gG] smell like %[eE], but 28875067f4fSPoul-Henning Kamp * trim trailing zeroes if no # flag. 28975067f4fSPoul-Henning Kamp */ 29075067f4fSPoul-Henning Kamp if (!pi->alt) 29175067f4fSPoul-Henning Kamp prec = ndig; 29275067f4fSPoul-Henning Kamp } 29375067f4fSPoul-Henning Kamp } 29475067f4fSPoul-Henning Kamp if (expchar) { 29575067f4fSPoul-Henning Kamp expsize = exponent(expstr, expt - 1, expchar); 29675067f4fSPoul-Henning Kamp size = expsize + prec; 29775067f4fSPoul-Henning Kamp if (prec > 1 || pi->alt) 29875067f4fSPoul-Henning Kamp ++size; 29975067f4fSPoul-Henning Kamp } else { 30075067f4fSPoul-Henning Kamp /* space for digits before decimal point */ 30175067f4fSPoul-Henning Kamp if (expt > 0) 30275067f4fSPoul-Henning Kamp size = expt; 30375067f4fSPoul-Henning Kamp else /* "0" */ 30475067f4fSPoul-Henning Kamp size = 1; 30575067f4fSPoul-Henning Kamp /* space for decimal pt and following digits */ 30675067f4fSPoul-Henning Kamp if (prec || pi->alt) 30775067f4fSPoul-Henning Kamp size += prec + 1; 30875067f4fSPoul-Henning Kamp if (grouping && expt > 0) { 30975067f4fSPoul-Henning Kamp /* space for thousands' grouping */ 31075067f4fSPoul-Henning Kamp nseps = nrepeats = 0; 31175067f4fSPoul-Henning Kamp lead = expt; 31275067f4fSPoul-Henning Kamp while (*grouping != CHAR_MAX) { 31375067f4fSPoul-Henning Kamp if (lead <= *grouping) 31475067f4fSPoul-Henning Kamp break; 31575067f4fSPoul-Henning Kamp lead -= *grouping; 31675067f4fSPoul-Henning Kamp if (*(grouping+1)) { 31775067f4fSPoul-Henning Kamp nseps++; 31875067f4fSPoul-Henning Kamp grouping++; 31975067f4fSPoul-Henning Kamp } else 32075067f4fSPoul-Henning Kamp nrepeats++; 32175067f4fSPoul-Henning Kamp } 32275067f4fSPoul-Henning Kamp size += nseps + nrepeats; 32375067f4fSPoul-Henning Kamp } else 32475067f4fSPoul-Henning Kamp lead = expt; 32575067f4fSPoul-Henning Kamp } 32675067f4fSPoul-Henning Kamp 32775067f4fSPoul-Henning Kamp here: 32875067f4fSPoul-Henning Kamp /* 32975067f4fSPoul-Henning Kamp * All reasonable formats wind up here. At this point, `cp' 33075067f4fSPoul-Henning Kamp * points to a string which (if not flags&LADJUST) should be 33175067f4fSPoul-Henning Kamp * padded out to `width' places. If flags&ZEROPAD, it should 33275067f4fSPoul-Henning Kamp * first be prefixed by any sign or other prefix; otherwise, 33375067f4fSPoul-Henning Kamp * it should be blank padded before the prefix is emitted. 33475067f4fSPoul-Henning Kamp * After any left-hand padding and prefixing, emit zeroes 33575067f4fSPoul-Henning Kamp * required by a decimal [diouxX] precision, then print the 33675067f4fSPoul-Henning Kamp * string proper, then emit zeroes required by any leftover 33775067f4fSPoul-Henning Kamp * floating precision; finally, if LADJUST, pad with blanks. 33875067f4fSPoul-Henning Kamp * 33975067f4fSPoul-Henning Kamp * Compute actual size, so we know how much to pad. 34075067f4fSPoul-Henning Kamp * size excludes decimal prec; realsz includes it. 34175067f4fSPoul-Henning Kamp */ 34275067f4fSPoul-Henning Kamp realsz = dprec > size ? dprec : size; 34375067f4fSPoul-Henning Kamp if (sign) 34475067f4fSPoul-Henning Kamp realsz++; 34575067f4fSPoul-Henning Kamp if (ox[1]) 34675067f4fSPoul-Henning Kamp realsz += 2; 34775067f4fSPoul-Henning Kamp 34875067f4fSPoul-Henning Kamp /* right-adjusting blank padding */ 34975067f4fSPoul-Henning Kamp if (pi->pad != '0' && pi->left == 0) 35075067f4fSPoul-Henning Kamp ret += __printf_pad(io, pi->width - realsz, 0); 35175067f4fSPoul-Henning Kamp 35275067f4fSPoul-Henning Kamp /* prefix */ 35375067f4fSPoul-Henning Kamp if (sign) 35475067f4fSPoul-Henning Kamp ret += __printf_puts(io, &sign, 1); 35575067f4fSPoul-Henning Kamp 35675067f4fSPoul-Henning Kamp if (ox[1]) { /* ox[1] is either x, X, or \0 */ 35775067f4fSPoul-Henning Kamp ox[0] = '0'; 35875067f4fSPoul-Henning Kamp ret += __printf_puts(io, ox, 2); 35975067f4fSPoul-Henning Kamp } 36075067f4fSPoul-Henning Kamp 36175067f4fSPoul-Henning Kamp /* right-adjusting zero padding */ 36275067f4fSPoul-Henning Kamp if (pi->pad == '0' && pi->left == 0) 36375067f4fSPoul-Henning Kamp ret += __printf_pad(io, pi->width - realsz, 1); 36475067f4fSPoul-Henning Kamp 36575067f4fSPoul-Henning Kamp /* leading zeroes from decimal precision */ 36675067f4fSPoul-Henning Kamp ret += __printf_pad(io, dprec - size, 1); 36775067f4fSPoul-Henning Kamp 36875067f4fSPoul-Henning Kamp if (flag) 36975067f4fSPoul-Henning Kamp ret += __printf_puts(io, cp, size); 37075067f4fSPoul-Henning Kamp else { 37175067f4fSPoul-Henning Kamp /* glue together f_p fragments */ 37275067f4fSPoul-Henning Kamp if (!expchar) { /* %[fF] or sufficiently short %[gG] */ 37375067f4fSPoul-Henning Kamp if (expt <= 0) { 37475067f4fSPoul-Henning Kamp ret += __printf_puts(io, "0", 1); 37575067f4fSPoul-Henning Kamp if (prec || pi->alt) 37675067f4fSPoul-Henning Kamp ret += __printf_puts(io, decimal_point, 1); 37775067f4fSPoul-Henning Kamp ret += __printf_pad(io, -expt, 1); 37875067f4fSPoul-Henning Kamp /* already handled initial 0's */ 37975067f4fSPoul-Henning Kamp prec += expt; 38075067f4fSPoul-Henning Kamp } else { 38175067f4fSPoul-Henning Kamp PRINTANDPAD(cp, dtoaend, lead, 1); 38275067f4fSPoul-Henning Kamp cp += lead; 38375067f4fSPoul-Henning Kamp if (grouping) { 38475067f4fSPoul-Henning Kamp while (nseps>0 || nrepeats>0) { 38575067f4fSPoul-Henning Kamp if (nrepeats > 0) 38675067f4fSPoul-Henning Kamp nrepeats--; 38775067f4fSPoul-Henning Kamp else { 38875067f4fSPoul-Henning Kamp grouping--; 38975067f4fSPoul-Henning Kamp nseps--; 39075067f4fSPoul-Henning Kamp } 39175067f4fSPoul-Henning Kamp ret += __printf_puts(io, &thousands_sep, 1); 39275067f4fSPoul-Henning Kamp PRINTANDPAD(cp,dtoaend, 39375067f4fSPoul-Henning Kamp *grouping, 1); 39475067f4fSPoul-Henning Kamp cp += *grouping; 39575067f4fSPoul-Henning Kamp } 39675067f4fSPoul-Henning Kamp if (cp > dtoaend) 39775067f4fSPoul-Henning Kamp cp = dtoaend; 39875067f4fSPoul-Henning Kamp } 39975067f4fSPoul-Henning Kamp if (prec || pi->alt) 40075067f4fSPoul-Henning Kamp ret += __printf_puts(io, decimal_point,1); 40175067f4fSPoul-Henning Kamp } 40275067f4fSPoul-Henning Kamp PRINTANDPAD(cp, dtoaend, prec, 1); 40375067f4fSPoul-Henning Kamp } else { /* %[eE] or sufficiently long %[gG] */ 40475067f4fSPoul-Henning Kamp if (prec > 1 || pi->alt) { 40575067f4fSPoul-Henning Kamp buf[0] = *cp++; 40675067f4fSPoul-Henning Kamp buf[1] = *decimal_point; 40775067f4fSPoul-Henning Kamp ret += __printf_puts(io, buf, 2); 40875067f4fSPoul-Henning Kamp ret += __printf_puts(io, cp, ndig-1); 40975067f4fSPoul-Henning Kamp ret += __printf_pad(io, prec - ndig, 1); 41075067f4fSPoul-Henning Kamp } else /* XeYYY */ 41175067f4fSPoul-Henning Kamp ret += __printf_puts(io, cp, 1); 41275067f4fSPoul-Henning Kamp ret += __printf_puts(io, expstr, expsize); 41375067f4fSPoul-Henning Kamp } 41475067f4fSPoul-Henning Kamp } 41575067f4fSPoul-Henning Kamp /* left-adjusting padding (always blank) */ 41675067f4fSPoul-Henning Kamp if (pi->left) 41775067f4fSPoul-Henning Kamp ret += __printf_pad(io, pi->width - realsz, 0); 41875067f4fSPoul-Henning Kamp 41975067f4fSPoul-Henning Kamp __printf_flush(io); 42075067f4fSPoul-Henning Kamp if (dtoaresult != NULL) 42175067f4fSPoul-Henning Kamp freedtoa(dtoaresult); 42275067f4fSPoul-Henning Kamp 42375067f4fSPoul-Henning Kamp return (ret); 42475067f4fSPoul-Henning Kamp } 425