OSDN Git Service

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