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