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
exponent(char * p0,int expo,int fmtch)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
__printf_arginfo_float(const struct printf_info * pi,size_t n,int * argt)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
__printf_render_float(struct __printf_io * io,const struct printf_info * pi,const void * const * arg)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