]>
git.saurik.com Git - apple/libc.git/blob - stdio/FreeBSD/xprintf_float.c
2 * Copyright (c) 2005 Poul-Henning Kamp
3 * Copyright (c) 1990, 1993
4 * The Regents of the University of California. All rights reserved.
6 * This code is derived from software contributed to Berkeley by
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * $FreeBSD: src/lib/libc/stdio/xprintf_float.c,v 1.1 2005/12/16 18:56:38 phk Exp $
36 #include <namespace.h>
37 #include "xlocale_private.h"
45 #define freedtoa __freedtoa
52 #include "xprintf_private.h"
53 #include <un-namespace.h>
56 * The size of the buffer we use as scratch space for integer
57 * conversions, among other things. Technically, we would need the
58 * most space for base 10 conversions with thousands' grouping
59 * characters between each pair of digits. 100 bytes is a
60 * conservative overestimate even for a 128-bit uintmax_t.
64 #define DEFPREC 6 /* Default FP precision */
67 /* various globals ---------------------------------------------------*/
70 /* padding function---------------------------------------------------*/
72 #define PRINTANDPAD(p, ep, len, with) do { \
77 ret += __printf_puts(io, (p), n2); \
78 ret += __printf_pad(io, (len) - (n2 > 0 ? n2 : 0), (with)); \
81 /* misc --------------------------------------------------------------*/
83 extern const char *__fix_nogrouping(const char *str
);
85 #define to_char(n) ((n) + '0')
88 exponent(char *p0
, int expo
, int fmtch
)
91 char expbuf
[MAXEXPDIG
];
101 t
= expbuf
+ MAXEXPDIG
;
104 *--t
= to_char(expo
% 10);
105 } while ((expo
/= 10) > 9);
106 *--t
= to_char(expo
);
107 for (; t
< expbuf
+ MAXEXPDIG
; *p
++ = *t
++)
112 * Exponents for decimal floating point conversions
113 * (%[eEgG]) must be at least two characters long,
114 * whereas exponents for hexadecimal conversions can
115 * be only one character long.
117 if (fmtch
== 'e' || fmtch
== 'E')
119 *p
++ = to_char(expo
);
124 /* 'f' ---------------------------------------------------------------*/
126 __private_extern__
int
127 __printf_arginfo_float(const struct printf_info
*pi
, size_t n
, int *argt
)
136 if (pi
->is_long_double
)
137 argt
[0] |= PA_FLAG_LONG_DOUBLE
;
145 * We can decompose the printed representation of floating
146 * point numbers into several parts, some of which may be empty:
148 * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ
151 * A: 'sign' holds this value if present; '\0' otherwise
152 * B: ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal
153 * C: cp points to the string MMMNNN. Leading and trailing
154 * zeros are not in the string and must be added.
155 * D: expchar holds this character; '\0' if no exponent, e.g. %f
156 * F: at least two digits for decimal, at least one digit for hex
159 __private_extern__
int
160 __printf_render_float(struct __printf_io
*io
, const struct printf_info
*pi
, const void *const *arg
)
162 int prec
; /* precision from format; <0 for N/A */
163 char *dtoaresult
; /* buffer allocated by dtoa */
164 char expchar
; /* exponent character: [eEpP\0] */
166 int expt
; /* integer value of exponent */
167 int signflag
; /* true if float is negative */
168 char *dtoaend
; /* pointer to end of converted digits */
169 char sign
; /* sign prefix (' ', '+', '-', or \0) */
170 int size
; /* size of converted field or string */
171 int ndig
; /* actual number of digits returned by dtoa */
172 int expsize
; /* character count for expstr */
173 char expstr
[MAXEXPDIG
+2]; /* buffer for exponent string: e+ZZZ */
174 int nseps
; /* number of group separators with ' */
175 int nrepeats
; /* number of repeats of the last group */
176 const char *grouping
; /* locale specific numeric grouping rules */
177 int lead
; /* sig figs before decimal or group sep */
180 int realsz
; /* field size expanded by dprec, sign, etc */
181 int dprec
; /* a copy of prec if [diouxX], 0 otherwise */
182 char ox
[2]; /* space for 0x; ox[1] is either x, X, or \0 */
183 int prsize
; /* max size of printed field */
184 int ret
; /* return value accumulator */
185 const char *decimal_point
; /* locale specific decimal point */
186 int decimal_point_len
; /* length of locale specific decimal point */
187 int n2
; /* XXX: for PRINTANDPAD */
188 const char *thousands_sep
; /* locale specific thousands separator */
189 int thousands_sep_len
; /* length of locale specific thousands separator */
190 char buf
[BUF
]; /* buffer with space for digits of uintmax_t */
195 if (pi
->is_vec
) return __xprintf_vector(io
, pi
, arg
);
204 thousands_sep
= localeconv_l(pi
->loc
)->thousands_sep
;
205 thousands_sep_len
= strlen(thousands_sep
);
208 grouping
= __fix_nogrouping(localeconv_l(pi
->loc
)->grouping
);
209 decimal_point
= localeconv_l(pi
->loc
)->decimal_point
;
210 decimal_point_len
= strlen(decimal_point
);
216 if (pi
->spec
== 'a') {
218 xdigs
= __lowercase_hex
;
222 xdigs
= __uppercase_hex
;
227 if (pi
->is_long_double
) {
228 ld
= *((long double *)arg
[0]);
230 __hldtoa(ld
, xdigs
, prec
,
231 &expt
, &signflag
, &dtoaend
);
233 d
= *((double *)arg
[0]);
235 __hdtoa(d
, xdigs
, prec
,
236 &expt
, &signflag
, &dtoaend
);
246 if (prec
< 0) /* account for digit before decpt */
257 expchar
= pi
->spec
- ('g' - 'e');
262 assert(pi
->spec
== 'f');
267 if (pi
->is_long_double
) {
268 ld
= *((long double *)arg
[0]);
270 __ldtoa(&ld
, expchar
? 2 : 3, prec
,
271 &expt
, &signflag
, &dtoaend
);
273 d
= *((double *)arg
[0]);
275 dtoa(d
, expchar
? 2 : 3, prec
,
276 &expt
, &signflag
, &dtoaend
);
283 if (expt
== INT_MAX
) { /* inf or nan */
285 cp
= (pi
->spec
>= 'a') ? "nan" : "NAN";
288 cp
= (pi
->spec
>= 'a') ? "inf" : "INF";
294 if (pi
->spec
== 'g' || pi
->spec
== 'G') {
295 if (expt
> -4 && expt
<= prec
) {
296 /* Make %[gG] smell like %[fF] */
306 * Make %[gG] smell like %[eE], but
307 * trim trailing zeroes if no # flag.
314 expsize
= exponent(expstr
, expt
- 1, expchar
);
315 size
= expsize
+ prec
;
316 if (prec
> 1 || pi
->alt
)
319 /* space for digits before decimal point */
324 /* space for decimal pt and following digits */
327 if (grouping
&& expt
> 0) {
328 /* space for thousands' grouping */
329 nseps
= nrepeats
= 0;
331 while (*grouping
!= CHAR_MAX
) {
332 if (lead
<= *grouping
)
341 size
+= nseps
+ nrepeats
;
348 * All reasonable formats wind up here. At this point, `cp'
349 * points to a string which (if not flags&LADJUST) should be
350 * padded out to `width' places. If flags&ZEROPAD, it should
351 * first be prefixed by any sign or other prefix; otherwise,
352 * it should be blank padded before the prefix is emitted.
353 * After any left-hand padding and prefixing, emit zeroes
354 * required by a decimal [diouxX] precision, then print the
355 * string proper, then emit zeroes required by any leftover
356 * floating precision; finally, if LADJUST, pad with blanks.
358 * Compute actual size, so we know how much to pad.
359 * size excludes decimal prec; realsz includes it.
361 realsz
= dprec
> size
? dprec
: size
;
367 prsize
= pi
->width
> realsz
? pi
->width
: realsz
;
369 /* right-adjusting blank padding */
370 if (pi
->pad
!= '0' && pi
->left
== 0)
371 ret
+= __printf_pad(io
, pi
->width
- realsz
, 0);
375 ret
+= __printf_puts(io
, &sign
, 1);
377 if (ox
[1]) { /* ox[1] is either x, X, or \0 */
379 ret
+= __printf_puts(io
, ox
, 2);
382 /* right-adjusting zero padding */
383 if (pi
->pad
== '0' && pi
->left
== 0)
384 ret
+= __printf_pad(io
, pi
->width
- realsz
, 1);
386 /* leading zeroes from decimal precision */
387 ret
+= __printf_pad(io
, dprec
- size
, 1);
390 ret
+= __printf_puts(io
, cp
, size
);
392 /* glue together f_p fragments */
393 if (!expchar
) { /* %[fF] or sufficiently short %[gG] */
395 ret
+= __printf_puts(io
, "0", 1);
397 ret
+= __printf_puts(io
, decimal_point
, decimal_point_len
);
398 ret
+= __printf_pad(io
, -expt
, 1);
399 /* already handled initial 0's */
402 PRINTANDPAD(cp
, dtoaend
, lead
, 1);
405 while (nseps
>0 || nrepeats
>0) {
412 ret
+= __printf_puts(io
, thousands_sep
, thousands_sep_len
);
413 PRINTANDPAD(cp
,dtoaend
,
421 ret
+= __printf_puts(io
, decimal_point
, decimal_point_len
);
423 PRINTANDPAD(cp
, dtoaend
, prec
, 1);
424 } else { /* %[eE] or sufficiently long %[gG] */
425 if (prec
> 1 || pi
->alt
) {
427 memcpy(buf
+ 1, decimal_point
, decimal_point_len
);
428 ret
+= __printf_puts(io
, buf
, decimal_point_len
+ 1);
429 ret
+= __printf_puts(io
, cp
, ndig
-1);
430 ret
+= __printf_pad(io
, prec
- ndig
, 1);
432 ret
+= __printf_puts(io
, cp
, 1);
433 ret
+= __printf_puts(io
, expstr
, expsize
);
436 /* left-adjusting padding (always blank) */
438 ret
+= __printf_pad(io
, pi
->width
- realsz
, 0);
441 if (dtoaresult
!= NULL
)
442 freedtoa(dtoaresult
);