|
|
1.1 root 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 GNU CC; see the file COPYING. If not, write to
17: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, 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:
27: /* Format floating-point number and print them.
28: Return number of chars printed, or EOF on error.
29:
30: sign_mode == '+' : print "-" or "+"
31: sign_mode == ' ' : print "-" or " "
32: sign_mode == '\0' : print "-' or ""
33: */
34:
35: int _IO_outfloat(value, sb, type, width, precision, flags,
36: sign_mode, fill)
37: double value;
38: _IO_FILE *sb;
39: int type;
40: int width;
41: int precision;
42: int flags;
43: int sign_mode;
44: int fill;
45: {
46: int count = 0;
47: #define PUT(x) do {if (_IO_putc(x, sb) < 0) goto error; count++;} while (0)
48: #define PUTN(p, n) \
49: do {int _n=n; count+=_n; if (_IO_sputn(sb, p,_n) != _n) goto error;} while(0)
50: #define PADN(fill, n) \
51: do {int _n = n; count+=_n; if (_IO_padn(sb, fill, _n) != _n) goto error;} while (0)
52: int pad_kind = flags & (_IO_LEFT|_IO_RIGHT|_IO_INTERNAL);
53: int skip_zeroes = 0;
54: int show_dot = (flags & _IO_SHOWPOINT) != 0;
55: int decpt;
56: int sign;
57: int mode;
58: int exponent_size;
59: int print_sign;
60: int trailing_zeroes, useful_digits;
61: int padding, unpadded_width;
62: char *p;
63: char *exponent_start;
64: register int i;
65: #define EBUF_SIZE 12
66: #define EBUF_END &ebuf[EBUF_SIZE]
67: char ebuf[EBUF_SIZE];
68: char *end;
69: int exp = 0;
70: switch (type)
71: {
72: case 'f':
73: mode = 3;
74: break;
75: case 'e':
76: case 'E':
77: exp = type;
78: mode = 2;
79: if (precision != 999)
80: precision++; /* Add one to include digit before decimal point. */
81: break;
82: case 'g':
83: case 'G':
84: exp = type == 'g' ? 'e' : 'E';
85: if (precision == 0) precision = 1;
86: if (!(flags & _IO_SHOWPOINT))
87: skip_zeroes = 1;
88: type = 'g';
89: mode = 2;
90: break;
91: }
92: /* Do the actual convension */
93: if (precision == 999 && mode != 3)
94: mode = 0;
95: p = _IO_dtoa(value, mode, precision, &decpt, &sign, &end);
96: useful_digits = end-p;
97: exponent_start = EBUF_END;
98: if (mode == 0)
99: precision = useful_digits;
100: /* Check if we need to emit an exponent. */
101: if (mode != 3 && decpt != 9999)
102: {
103: i = decpt - 1;
104: if ((type != 'g' && type != 'F') || i < -4 || i >= precision)
105: {
106: /* Print the exponent into ebuf.
107: We write ebuf in reverse order (right-to-left). */
108: char sign;
109: if (i >= 0)
110: sign = '+';
111: else
112: sign = '-', i = -i;
113: /* Note: ANSI requires at least 2 exponent digits. */
114: do {
115: *--exponent_start = (i % 10) + '0';
116: i /= 10;
117: } while (i >= 10);
118: *--exponent_start = i + '0';
119: *--exponent_start = sign;
120: *--exponent_start = exp;
121: }
122: }
123: exponent_size = EBUF_END - exponent_start;
124: if (mode == 1)
125: precision = 1;
126: /* If we print an exponent, always show just one digit before point. */
127: if (exponent_size)
128: decpt = 1;
129: if (decpt == 9999)
130: { /* Infinity or NaN */
131: decpt = useful_digits;
132: precision = 0;
133: show_dot = 0;
134: }
135:
136: /* dtoa truncates trailing zeroes. Set the variable trailing_zeroes to
137: the number of 0's we have to add (after the decimal point). */
138: if (skip_zeroes)
139: trailing_zeroes = 0;
140: else if (type == 'f')
141: trailing_zeroes = useful_digits <= decpt ? precision
142: : precision-(useful_digits-decpt);
143: else if (exponent_size) /* 'e' 'E' or 'g' format using exponential notation*/
144: trailing_zeroes = precision - useful_digits;
145: else /* 'g' format not using exponential notation. */
146: trailing_zeroes = useful_digits <= decpt ? precision - decpt
147: : precision-useful_digits;
148: if (trailing_zeroes < 0) trailing_zeroes = 0;
149:
150: if (trailing_zeroes != 0 || useful_digits > decpt)
151: show_dot = 1;
152: if (sign_mode == 0)
153: print_sign = sign ? '-' : 0;
154: else if (sign_mode == '+')
155: print_sign = sign ? '-' : '+';
156: else /* if (sign_mode == ' ') */
157: print_sign = sign ? '-' : ' ';
158:
159: /* Calculate the width (before padding). */
160: unpadded_width =
161: (print_sign != 0) + trailing_zeroes + exponent_size + show_dot
162: + useful_digits
163: + (decpt > useful_digits ? decpt - useful_digits
164: : decpt > 0 ? 0 : 1 - decpt);
165:
166: padding = width > unpadded_width ? width - unpadded_width : 0;
167: if (padding > 0 && pad_kind != _IO_LEFT && pad_kind != _IO_INTERNAL)
168: PADN(fill, padding); /* Default (right) adjust */
169: if (print_sign)
170: PUT(print_sign);
171: if (pad_kind == _IO_INTERNAL && padding > 0)
172: PADN(fill, padding);
173: if (decpt > 0)
174: {
175: if (useful_digits >= decpt)
176: PUTN(p, decpt);
177: else
178: {
179: PUTN(p, useful_digits);
180: PADN('0', decpt-useful_digits);
181: }
182: if (show_dot)
183: {
184: PUT('.');
185: /* Print digits after the decimal point. */
186: if (useful_digits > decpt)
187: PUTN(p + decpt, useful_digits-decpt);
188: }
189: }
190: else
191: {
192: PUT('0');
193: if (show_dot)
194: {
195: PUT('.');
196: PADN('0', -decpt);
197: /* Print digits after the decimal point. */
198: PUTN(p, useful_digits);
199: }
200: }
201: PADN('0', trailing_zeroes);
202: if (exponent_size)
203: PUTN(exponent_start, exponent_size);
204: if (pad_kind == _IO_LEFT && padding > 0) /* Left adjustment*/
205: PADN(fill, padding);
206: return count;
207: error:
208: return EOF;
209: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.