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