]>
Commit | Line | Data |
---|---|---|
6599da04 JM |
1 | /* |
2 | Copyright (C) 1993 Free Software Foundation | |
3 | ||
4 | This file is part of the GNU IO Library. This library is free | |
5 | software; you can redistribute it and/or modify it under the | |
6 | terms of the GNU General Public License as published by the | |
7 | Free Software Foundation; either version 2, or (at your option) | |
8 | any later version. | |
9 | ||
10 | This library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | GNU General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU General Public License | |
16 | along with this library; see the file COPYING. If not, write to the Free | |
17 | Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
18 | ||
19 | As a special exception, if you link this library with files | |
20 | compiled with a GNU compiler to produce an executable, this does not cause | |
21 | the resulting executable to be covered by the GNU General Public License. | |
22 | This exception does not however invalidate any other reasons why | |
23 | the executable file might be covered by the GNU General Public License. */ | |
24 | ||
25 | #include "libioP.h" | |
26 | ||
e693cc28 | 27 | #ifdef _IO_USE_DTOA |
6599da04 JM |
28 | /* Format floating-point number and print them. |
29 | Return number of chars printed, or EOF on error. | |
30 | ||
31 | sign_mode == '+' : print "-" or "+" | |
32 | sign_mode == ' ' : print "-" or " " | |
33 | sign_mode == '\0' : print "-' or "" | |
34 | */ | |
35 | ||
36 | int | |
e693cc28 UD |
37 | _IO_outfloat (value, sb, type, width, precision, flags, sign_mode, fill) |
38 | double value; | |
39 | _IO_FILE *sb; | |
40 | int type; | |
41 | int width; | |
42 | int precision; | |
43 | int flags; | |
44 | int sign_mode; | |
45 | int fill; | |
6599da04 JM |
46 | { |
47 | int count = 0; | |
48 | #define PUT(x) do {if (_IO_putc(x, sb) < 0) goto error; count++;} while (0) | |
49 | #define PUTN(p, n) \ | |
50 | do {int _n=n; count+=_n; if (_IO_sputn(sb, p,_n) != _n) goto error;} while(0) | |
51 | #define PADN(fill, n) \ | |
52 | do {int _n = n; count+=_n; if (_IO_padn(sb, fill, _n) != _n) goto error;} while (0) | |
53 | int pad_kind = flags & (_IO_LEFT|_IO_RIGHT|_IO_INTERNAL); | |
54 | int skip_zeroes = 0; | |
55 | int show_dot = (flags & _IO_SHOWPOINT) != 0; | |
56 | int decpt; | |
57 | int sign; | |
58 | int mode; | |
59 | int exponent_size; | |
60 | int print_sign; | |
61 | int trailing_zeroes, useful_digits; | |
62 | int padding, unpadded_width; | |
63 | char *p; | |
64 | char *exponent_start; | |
65 | register int i; | |
66 | #define EBUF_SIZE 12 | |
67 | #define EBUF_END &ebuf[EBUF_SIZE] | |
68 | char ebuf[EBUF_SIZE]; | |
69 | char *end; | |
70 | int exp = 0; | |
71 | switch (type) | |
72 | { | |
73 | case 'f': | |
74 | mode = 3; | |
75 | break; | |
76 | case 'e': | |
77 | case 'E': | |
78 | exp = type; | |
79 | mode = 2; | |
80 | if (precision != 999) | |
81 | precision++; /* Add one to include digit before decimal point. */ | |
82 | break; | |
83 | case 'g': | |
84 | case 'G': | |
85 | exp = type == 'g' ? 'e' : 'E'; | |
86 | if (precision == 0) precision = 1; | |
87 | if (!(flags & _IO_SHOWPOINT)) | |
88 | skip_zeroes = 1; | |
89 | type = 'g'; | |
90 | mode = 2; | |
91 | break; | |
92 | } | |
93 | /* Do the actual convension */ | |
94 | if (precision == 999 && mode != 3) | |
95 | mode = 0; | |
96 | p = _IO_dtoa(value, mode, precision, &decpt, &sign, &end); | |
97 | useful_digits = end-p; | |
98 | exponent_start = EBUF_END; | |
99 | if (mode == 0) | |
100 | precision = useful_digits; | |
101 | /* Check if we need to emit an exponent. */ | |
102 | if (mode != 3 && decpt != 9999) | |
103 | { | |
104 | i = decpt - 1; | |
105 | if ((type != 'g' && type != 'F') || i < -4 || i >= precision) | |
106 | { | |
107 | /* Print the exponent into ebuf. | |
108 | We write ebuf in reverse order (right-to-left). */ | |
109 | char sign; | |
110 | if (i >= 0) | |
111 | sign = '+'; | |
112 | else | |
113 | sign = '-', i = -i; | |
114 | /* Note: ANSI requires at least 2 exponent digits. */ | |
115 | do { | |
116 | *--exponent_start = (i % 10) + '0'; | |
117 | i /= 10; | |
118 | } while (i >= 10); | |
119 | *--exponent_start = i + '0'; | |
120 | *--exponent_start = sign; | |
121 | *--exponent_start = exp; | |
122 | } | |
123 | } | |
124 | exponent_size = EBUF_END - exponent_start; | |
125 | if (mode == 1) | |
126 | precision = 1; | |
127 | /* If we print an exponent, always show just one digit before point. */ | |
128 | if (exponent_size) | |
129 | decpt = 1; | |
130 | if (decpt == 9999) | |
131 | { /* Infinity or NaN */ | |
132 | decpt = useful_digits; | |
133 | precision = 0; | |
134 | show_dot = 0; | |
135 | } | |
136 | ||
137 | /* dtoa truncates trailing zeroes. Set the variable trailing_zeroes to | |
138 | the number of 0's we have to add (after the decimal point). */ | |
139 | if (skip_zeroes) | |
140 | trailing_zeroes = 0; | |
141 | else if (type == 'f') | |
142 | trailing_zeroes = useful_digits <= decpt ? precision | |
143 | : precision-(useful_digits-decpt); | |
144 | else if (exponent_size) /* 'e' 'E' or 'g' format using exponential notation*/ | |
145 | trailing_zeroes = precision - useful_digits; | |
146 | else /* 'g' format not using exponential notation. */ | |
147 | trailing_zeroes = useful_digits <= decpt ? precision - decpt | |
148 | : precision-useful_digits; | |
149 | if (trailing_zeroes < 0) trailing_zeroes = 0; | |
150 | ||
151 | if (trailing_zeroes != 0 || useful_digits > decpt) | |
152 | show_dot = 1; | |
153 | if (sign_mode == 0) | |
154 | print_sign = sign ? '-' : 0; | |
155 | else if (sign_mode == '+') | |
156 | print_sign = sign ? '-' : '+'; | |
157 | else /* if (sign_mode == ' ') */ | |
158 | print_sign = sign ? '-' : ' '; | |
159 | ||
160 | /* Calculate the width (before padding). */ | |
161 | unpadded_width = | |
162 | (print_sign != 0) + trailing_zeroes + exponent_size + show_dot | |
163 | + useful_digits | |
164 | + (decpt > useful_digits ? decpt - useful_digits | |
165 | : decpt > 0 ? 0 : 1 - decpt); | |
166 | ||
167 | padding = width > unpadded_width ? width - unpadded_width : 0; | |
168 | if (padding > 0 && pad_kind != _IO_LEFT && pad_kind != _IO_INTERNAL) | |
169 | PADN(fill, padding); /* Default (right) adjust */ | |
170 | if (print_sign) | |
171 | PUT(print_sign); | |
172 | if (pad_kind == _IO_INTERNAL && padding > 0) | |
173 | PADN(fill, padding); | |
174 | if (decpt > 0) | |
175 | { | |
176 | if (useful_digits >= decpt) | |
177 | PUTN(p, decpt); | |
178 | else | |
179 | { | |
180 | PUTN(p, useful_digits); | |
181 | PADN('0', decpt-useful_digits); | |
182 | } | |
183 | if (show_dot) | |
184 | { | |
185 | PUT('.'); | |
186 | /* Print digits after the decimal point. */ | |
187 | if (useful_digits > decpt) | |
188 | PUTN(p + decpt, useful_digits-decpt); | |
189 | } | |
190 | } | |
191 | else | |
192 | { | |
193 | PUT('0'); | |
194 | if (show_dot) | |
195 | { | |
196 | PUT('.'); | |
197 | PADN('0', -decpt); | |
198 | /* Print digits after the decimal point. */ | |
199 | PUTN(p, useful_digits); | |
200 | } | |
201 | } | |
202 | PADN('0', trailing_zeroes); | |
203 | if (exponent_size) | |
204 | PUTN(exponent_start, exponent_size); | |
205 | if (pad_kind == _IO_LEFT && padding > 0) /* Left adjustment*/ | |
206 | PADN(fill, padding); | |
207 | return count; | |
208 | error: | |
209 | return EOF; | |
210 | } | |
e693cc28 | 211 | #endif |