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