Blame


1 b2cfc4e2 2003-09-30 devnull /*
2 b2cfc4e2 2003-09-30 devnull * The authors of this software are Rob Pike and Ken Thompson.
3 b2cfc4e2 2003-09-30 devnull * Copyright (c) 2002 by Lucent Technologies.
4 b2cfc4e2 2003-09-30 devnull * Permission to use, copy, modify, and distribute this software for any
5 b2cfc4e2 2003-09-30 devnull * purpose without fee is hereby granted, provided that this entire notice
6 b2cfc4e2 2003-09-30 devnull * is included in all copies of any software which is or includes a copy
7 b2cfc4e2 2003-09-30 devnull * or modification of this software and in all copies of the supporting
8 b2cfc4e2 2003-09-30 devnull * documentation for such software.
9 b2cfc4e2 2003-09-30 devnull * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
10 b2cfc4e2 2003-09-30 devnull * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
11 b2cfc4e2 2003-09-30 devnull * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
12 b2cfc4e2 2003-09-30 devnull * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
13 b2cfc4e2 2003-09-30 devnull */
14 b2cfc4e2 2003-09-30 devnull #include <stdio.h>
15 b2cfc4e2 2003-09-30 devnull #include <math.h>
16 b2cfc4e2 2003-09-30 devnull #include <float.h>
17 b2cfc4e2 2003-09-30 devnull #include <string.h>
18 b2cfc4e2 2003-09-30 devnull #include <stdlib.h>
19 b2cfc4e2 2003-09-30 devnull #include <errno.h>
20 b2cfc4e2 2003-09-30 devnull #include <stdarg.h>
21 b2cfc4e2 2003-09-30 devnull #include "fmt.h"
22 b2cfc4e2 2003-09-30 devnull #include "fmtdef.h"
23 b2cfc4e2 2003-09-30 devnull #include "nan.h"
24 b2cfc4e2 2003-09-30 devnull
25 b2cfc4e2 2003-09-30 devnull enum
26 b2cfc4e2 2003-09-30 devnull {
27 b2cfc4e2 2003-09-30 devnull FDEFLT = 6,
28 b2cfc4e2 2003-09-30 devnull NSIGNIF = 17
29 b2cfc4e2 2003-09-30 devnull };
30 b2cfc4e2 2003-09-30 devnull
31 b2cfc4e2 2003-09-30 devnull /*
32 b2cfc4e2 2003-09-30 devnull * first few powers of 10, enough for about 1/2 of the
33 b2cfc4e2 2003-09-30 devnull * total space for doubles.
34 b2cfc4e2 2003-09-30 devnull */
35 b2cfc4e2 2003-09-30 devnull static double pows10[] =
36 b2cfc4e2 2003-09-30 devnull {
37 b2cfc4e2 2003-09-30 devnull 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
38 b2cfc4e2 2003-09-30 devnull 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
39 b2cfc4e2 2003-09-30 devnull 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29,
40 b2cfc4e2 2003-09-30 devnull 1e30, 1e31, 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39,
41 b2cfc4e2 2003-09-30 devnull 1e40, 1e41, 1e42, 1e43, 1e44, 1e45, 1e46, 1e47, 1e48, 1e49,
42 b2cfc4e2 2003-09-30 devnull 1e50, 1e51, 1e52, 1e53, 1e54, 1e55, 1e56, 1e57, 1e58, 1e59,
43 b2cfc4e2 2003-09-30 devnull 1e60, 1e61, 1e62, 1e63, 1e64, 1e65, 1e66, 1e67, 1e68, 1e69,
44 b2cfc4e2 2003-09-30 devnull 1e70, 1e71, 1e72, 1e73, 1e74, 1e75, 1e76, 1e77, 1e78, 1e79,
45 b2cfc4e2 2003-09-30 devnull 1e80, 1e81, 1e82, 1e83, 1e84, 1e85, 1e86, 1e87, 1e88, 1e89,
46 b2cfc4e2 2003-09-30 devnull 1e90, 1e91, 1e92, 1e93, 1e94, 1e95, 1e96, 1e97, 1e98, 1e99,
47 b2cfc4e2 2003-09-30 devnull 1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109,
48 b2cfc4e2 2003-09-30 devnull 1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119,
49 b2cfc4e2 2003-09-30 devnull 1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129,
50 b2cfc4e2 2003-09-30 devnull 1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139,
51 b2cfc4e2 2003-09-30 devnull 1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149,
52 b2cfc4e2 2003-09-30 devnull 1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159,
53 b2cfc4e2 2003-09-30 devnull };
54 b2cfc4e2 2003-09-30 devnull
55 b2cfc4e2 2003-09-30 devnull static double
56 b2cfc4e2 2003-09-30 devnull pow10(int n)
57 b2cfc4e2 2003-09-30 devnull {
58 b2cfc4e2 2003-09-30 devnull double d;
59 b2cfc4e2 2003-09-30 devnull int neg;
60 b2cfc4e2 2003-09-30 devnull
61 b2cfc4e2 2003-09-30 devnull neg = 0;
62 b2cfc4e2 2003-09-30 devnull if(n < 0){
63 b2cfc4e2 2003-09-30 devnull if(n < DBL_MIN_10_EXP){
64 b2cfc4e2 2003-09-30 devnull return 0.;
65 b2cfc4e2 2003-09-30 devnull }
66 b2cfc4e2 2003-09-30 devnull neg = 1;
67 b2cfc4e2 2003-09-30 devnull n = -n;
68 b2cfc4e2 2003-09-30 devnull }else if(n > DBL_MAX_10_EXP){
69 b2cfc4e2 2003-09-30 devnull return HUGE_VAL;
70 b2cfc4e2 2003-09-30 devnull }
71 b2cfc4e2 2003-09-30 devnull if(n < (int)(sizeof(pows10)/sizeof(pows10[0])))
72 b2cfc4e2 2003-09-30 devnull d = pows10[n];
73 b2cfc4e2 2003-09-30 devnull else{
74 b2cfc4e2 2003-09-30 devnull d = pows10[sizeof(pows10)/sizeof(pows10[0]) - 1];
75 b2cfc4e2 2003-09-30 devnull for(;;){
76 b2cfc4e2 2003-09-30 devnull n -= sizeof(pows10)/sizeof(pows10[0]) - 1;
77 b2cfc4e2 2003-09-30 devnull if(n < (int)(sizeof(pows10)/sizeof(pows10[0]))){
78 b2cfc4e2 2003-09-30 devnull d *= pows10[n];
79 b2cfc4e2 2003-09-30 devnull break;
80 b2cfc4e2 2003-09-30 devnull }
81 b2cfc4e2 2003-09-30 devnull d *= pows10[sizeof(pows10)/sizeof(pows10[0]) - 1];
82 b2cfc4e2 2003-09-30 devnull }
83 b2cfc4e2 2003-09-30 devnull }
84 b2cfc4e2 2003-09-30 devnull if(neg){
85 b2cfc4e2 2003-09-30 devnull return 1./d;
86 b2cfc4e2 2003-09-30 devnull }
87 b2cfc4e2 2003-09-30 devnull return d;
88 b2cfc4e2 2003-09-30 devnull }
89 b2cfc4e2 2003-09-30 devnull
90 b2cfc4e2 2003-09-30 devnull static int
91 b2cfc4e2 2003-09-30 devnull xadd(char *a, int n, int v)
92 b2cfc4e2 2003-09-30 devnull {
93 b2cfc4e2 2003-09-30 devnull char *b;
94 b2cfc4e2 2003-09-30 devnull int c;
95 b2cfc4e2 2003-09-30 devnull
96 b2cfc4e2 2003-09-30 devnull if(n < 0 || n >= NSIGNIF)
97 b2cfc4e2 2003-09-30 devnull return 0;
98 b2cfc4e2 2003-09-30 devnull for(b = a+n; b >= a; b--) {
99 b2cfc4e2 2003-09-30 devnull c = *b + v;
100 b2cfc4e2 2003-09-30 devnull if(c <= '9') {
101 b2cfc4e2 2003-09-30 devnull *b = c;
102 b2cfc4e2 2003-09-30 devnull return 0;
103 b2cfc4e2 2003-09-30 devnull }
104 b2cfc4e2 2003-09-30 devnull *b = '0';
105 b2cfc4e2 2003-09-30 devnull v = 1;
106 b2cfc4e2 2003-09-30 devnull }
107 b2cfc4e2 2003-09-30 devnull *a = '1'; /* overflow adding */
108 b2cfc4e2 2003-09-30 devnull return 1;
109 b2cfc4e2 2003-09-30 devnull }
110 b2cfc4e2 2003-09-30 devnull
111 b2cfc4e2 2003-09-30 devnull static int
112 b2cfc4e2 2003-09-30 devnull xsub(char *a, int n, int v)
113 b2cfc4e2 2003-09-30 devnull {
114 b2cfc4e2 2003-09-30 devnull char *b;
115 b2cfc4e2 2003-09-30 devnull int c;
116 b2cfc4e2 2003-09-30 devnull
117 b2cfc4e2 2003-09-30 devnull for(b = a+n; b >= a; b--) {
118 b2cfc4e2 2003-09-30 devnull c = *b - v;
119 b2cfc4e2 2003-09-30 devnull if(c >= '0') {
120 b2cfc4e2 2003-09-30 devnull *b = c;
121 b2cfc4e2 2003-09-30 devnull return 0;
122 b2cfc4e2 2003-09-30 devnull }
123 b2cfc4e2 2003-09-30 devnull *b = '9';
124 b2cfc4e2 2003-09-30 devnull v = 1;
125 b2cfc4e2 2003-09-30 devnull }
126 b2cfc4e2 2003-09-30 devnull *a = '9'; /* underflow subtracting */
127 b2cfc4e2 2003-09-30 devnull return 1;
128 b2cfc4e2 2003-09-30 devnull }
129 b2cfc4e2 2003-09-30 devnull
130 b2cfc4e2 2003-09-30 devnull static void
131 b2cfc4e2 2003-09-30 devnull xaddexp(char *p, int e)
132 b2cfc4e2 2003-09-30 devnull {
133 b2cfc4e2 2003-09-30 devnull char se[9];
134 b2cfc4e2 2003-09-30 devnull int i;
135 b2cfc4e2 2003-09-30 devnull
136 b2cfc4e2 2003-09-30 devnull *p++ = 'e';
137 b2cfc4e2 2003-09-30 devnull if(e < 0) {
138 b2cfc4e2 2003-09-30 devnull *p++ = '-';
139 b2cfc4e2 2003-09-30 devnull e = -e;
140 b2cfc4e2 2003-09-30 devnull }
141 b2cfc4e2 2003-09-30 devnull i = 0;
142 b2cfc4e2 2003-09-30 devnull while(e) {
143 b2cfc4e2 2003-09-30 devnull se[i++] = e % 10 + '0';
144 b2cfc4e2 2003-09-30 devnull e /= 10;
145 b2cfc4e2 2003-09-30 devnull }
146 b2cfc4e2 2003-09-30 devnull if(i == 0) {
147 b2cfc4e2 2003-09-30 devnull *p++ = '0';
148 b2cfc4e2 2003-09-30 devnull } else {
149 b2cfc4e2 2003-09-30 devnull while(i > 0)
150 b2cfc4e2 2003-09-30 devnull *p++ = se[--i];
151 b2cfc4e2 2003-09-30 devnull }
152 b2cfc4e2 2003-09-30 devnull *p++ = '\0';
153 b2cfc4e2 2003-09-30 devnull }
154 b2cfc4e2 2003-09-30 devnull
155 b2cfc4e2 2003-09-30 devnull static char*
156 b2cfc4e2 2003-09-30 devnull xdodtoa(char *s1, double f, int chr, int prec, int *decpt, int *rsign)
157 b2cfc4e2 2003-09-30 devnull {
158 b2cfc4e2 2003-09-30 devnull char s2[NSIGNIF+10];
159 b2cfc4e2 2003-09-30 devnull double g, h;
160 b2cfc4e2 2003-09-30 devnull int e, d, i;
161 b2cfc4e2 2003-09-30 devnull int c2, sign, oerr;
162 b2cfc4e2 2003-09-30 devnull
163 b2cfc4e2 2003-09-30 devnull if(chr == 'F')
164 b2cfc4e2 2003-09-30 devnull chr = 'f';
165 b2cfc4e2 2003-09-30 devnull if(prec > NSIGNIF)
166 b2cfc4e2 2003-09-30 devnull prec = NSIGNIF;
167 b2cfc4e2 2003-09-30 devnull if(prec < 0)
168 b2cfc4e2 2003-09-30 devnull prec = 0;
169 b2cfc4e2 2003-09-30 devnull if(__isNaN(f)) {
170 b2cfc4e2 2003-09-30 devnull *decpt = 9999;
171 b2cfc4e2 2003-09-30 devnull *rsign = 0;
172 b2cfc4e2 2003-09-30 devnull strcpy(s1, "nan");
173 b2cfc4e2 2003-09-30 devnull return &s1[3];
174 b2cfc4e2 2003-09-30 devnull }
175 b2cfc4e2 2003-09-30 devnull sign = 0;
176 b2cfc4e2 2003-09-30 devnull if(f < 0) {
177 b2cfc4e2 2003-09-30 devnull f = -f;
178 b2cfc4e2 2003-09-30 devnull sign++;
179 b2cfc4e2 2003-09-30 devnull }
180 b2cfc4e2 2003-09-30 devnull *rsign = sign;
181 b2cfc4e2 2003-09-30 devnull if(__isInf(f, 1) || __isInf(f, -1)) {
182 b2cfc4e2 2003-09-30 devnull *decpt = 9999;
183 b2cfc4e2 2003-09-30 devnull strcpy(s1, "inf");
184 b2cfc4e2 2003-09-30 devnull return &s1[3];
185 b2cfc4e2 2003-09-30 devnull }
186 b2cfc4e2 2003-09-30 devnull
187 b2cfc4e2 2003-09-30 devnull e = 0;
188 b2cfc4e2 2003-09-30 devnull g = f;
189 b2cfc4e2 2003-09-30 devnull if(g != 0) {
190 b2cfc4e2 2003-09-30 devnull frexp(f, &e);
191 b2cfc4e2 2003-09-30 devnull e = (int)(e * .301029995664);
192 b2cfc4e2 2003-09-30 devnull if(e >= -150 && e <= +150) {
193 b2cfc4e2 2003-09-30 devnull d = 0;
194 b2cfc4e2 2003-09-30 devnull h = f;
195 b2cfc4e2 2003-09-30 devnull } else {
196 b2cfc4e2 2003-09-30 devnull d = e/2;
197 b2cfc4e2 2003-09-30 devnull h = f * pow10(-d);
198 b2cfc4e2 2003-09-30 devnull }
199 b2cfc4e2 2003-09-30 devnull g = h * pow10(d-e);
200 b2cfc4e2 2003-09-30 devnull while(g < 1) {
201 b2cfc4e2 2003-09-30 devnull e--;
202 b2cfc4e2 2003-09-30 devnull g = h * pow10(d-e);
203 b2cfc4e2 2003-09-30 devnull }
204 b2cfc4e2 2003-09-30 devnull while(g >= 10) {
205 b2cfc4e2 2003-09-30 devnull e++;
206 b2cfc4e2 2003-09-30 devnull g = h * pow10(d-e);
207 b2cfc4e2 2003-09-30 devnull }
208 b2cfc4e2 2003-09-30 devnull }
209 b2cfc4e2 2003-09-30 devnull
210 b2cfc4e2 2003-09-30 devnull /*
211 b2cfc4e2 2003-09-30 devnull * convert NSIGNIF digits and convert
212 b2cfc4e2 2003-09-30 devnull * back to get accuracy.
213 b2cfc4e2 2003-09-30 devnull */
214 b2cfc4e2 2003-09-30 devnull for(i=0; i<NSIGNIF; i++) {
215 b2cfc4e2 2003-09-30 devnull d = (int)g;
216 b2cfc4e2 2003-09-30 devnull s1[i] = d + '0';
217 b2cfc4e2 2003-09-30 devnull g = (g - d) * 10;
218 b2cfc4e2 2003-09-30 devnull }
219 b2cfc4e2 2003-09-30 devnull s1[i] = 0;
220 b2cfc4e2 2003-09-30 devnull
221 b2cfc4e2 2003-09-30 devnull /*
222 b2cfc4e2 2003-09-30 devnull * try decimal rounding to eliminate 9s
223 b2cfc4e2 2003-09-30 devnull */
224 b2cfc4e2 2003-09-30 devnull c2 = prec + 1;
225 b2cfc4e2 2003-09-30 devnull if(chr == 'f')
226 b2cfc4e2 2003-09-30 devnull c2 += e;
227 b2cfc4e2 2003-09-30 devnull oerr = errno;
228 b2cfc4e2 2003-09-30 devnull if(c2 >= NSIGNIF-2) {
229 b2cfc4e2 2003-09-30 devnull strcpy(s2, s1);
230 b2cfc4e2 2003-09-30 devnull d = e;
231 b2cfc4e2 2003-09-30 devnull s1[NSIGNIF-2] = '0';
232 b2cfc4e2 2003-09-30 devnull s1[NSIGNIF-1] = '0';
233 b2cfc4e2 2003-09-30 devnull xaddexp(s1+NSIGNIF, e-NSIGNIF+1);
234 b2cfc4e2 2003-09-30 devnull g = fmtstrtod(s1, nil);
235 b2cfc4e2 2003-09-30 devnull if(g == f)
236 b2cfc4e2 2003-09-30 devnull goto found;
237 b2cfc4e2 2003-09-30 devnull if(xadd(s1, NSIGNIF-3, 1)) {
238 b2cfc4e2 2003-09-30 devnull e++;
239 b2cfc4e2 2003-09-30 devnull xaddexp(s1+NSIGNIF, e-NSIGNIF+1);
240 b2cfc4e2 2003-09-30 devnull }
241 b2cfc4e2 2003-09-30 devnull g = fmtstrtod(s1, nil);
242 b2cfc4e2 2003-09-30 devnull if(g == f)
243 b2cfc4e2 2003-09-30 devnull goto found;
244 b2cfc4e2 2003-09-30 devnull strcpy(s1, s2);
245 b2cfc4e2 2003-09-30 devnull e = d;
246 b2cfc4e2 2003-09-30 devnull }
247 b2cfc4e2 2003-09-30 devnull
248 b2cfc4e2 2003-09-30 devnull /*
249 b2cfc4e2 2003-09-30 devnull * convert back so s1 gets exact answer
250 b2cfc4e2 2003-09-30 devnull */
251 b2cfc4e2 2003-09-30 devnull for(d = 0; d < 10; d++) {
252 b2cfc4e2 2003-09-30 devnull xaddexp(s1+NSIGNIF, e-NSIGNIF+1);
253 b2cfc4e2 2003-09-30 devnull g = fmtstrtod(s1, nil);
254 b2cfc4e2 2003-09-30 devnull if(f > g) {
255 b2cfc4e2 2003-09-30 devnull if(xadd(s1, NSIGNIF-1, 1))
256 b2cfc4e2 2003-09-30 devnull e--;
257 b2cfc4e2 2003-09-30 devnull continue;
258 b2cfc4e2 2003-09-30 devnull }
259 b2cfc4e2 2003-09-30 devnull if(f < g) {
260 b2cfc4e2 2003-09-30 devnull if(xsub(s1, NSIGNIF-1, 1))
261 b2cfc4e2 2003-09-30 devnull e++;
262 b2cfc4e2 2003-09-30 devnull continue;
263 b2cfc4e2 2003-09-30 devnull }
264 b2cfc4e2 2003-09-30 devnull break;
265 b2cfc4e2 2003-09-30 devnull }
266 b2cfc4e2 2003-09-30 devnull
267 b2cfc4e2 2003-09-30 devnull found:
268 b2cfc4e2 2003-09-30 devnull errno = oerr;
269 b2cfc4e2 2003-09-30 devnull
270 b2cfc4e2 2003-09-30 devnull /*
271 b2cfc4e2 2003-09-30 devnull * sign
272 b2cfc4e2 2003-09-30 devnull */
273 b2cfc4e2 2003-09-30 devnull d = 0;
274 b2cfc4e2 2003-09-30 devnull i = 0;
275 b2cfc4e2 2003-09-30 devnull
276 b2cfc4e2 2003-09-30 devnull /*
277 b2cfc4e2 2003-09-30 devnull * round & adjust 'f' digits
278 b2cfc4e2 2003-09-30 devnull */
279 b2cfc4e2 2003-09-30 devnull c2 = prec + 1;
280 b2cfc4e2 2003-09-30 devnull if(chr == 'f'){
281 b2cfc4e2 2003-09-30 devnull if(xadd(s1, c2+e, 5))
282 b2cfc4e2 2003-09-30 devnull e++;
283 b2cfc4e2 2003-09-30 devnull c2 += e;
284 b2cfc4e2 2003-09-30 devnull if(c2 < 0){
285 b2cfc4e2 2003-09-30 devnull c2 = 0;
286 b2cfc4e2 2003-09-30 devnull e = -prec - 1;
287 b2cfc4e2 2003-09-30 devnull }
288 b2cfc4e2 2003-09-30 devnull }else{
289 b2cfc4e2 2003-09-30 devnull if(xadd(s1, c2, 5))
290 b2cfc4e2 2003-09-30 devnull e++;
291 b2cfc4e2 2003-09-30 devnull }
292 b2cfc4e2 2003-09-30 devnull if(c2 > NSIGNIF){
293 b2cfc4e2 2003-09-30 devnull c2 = NSIGNIF;
294 b2cfc4e2 2003-09-30 devnull }
295 b2cfc4e2 2003-09-30 devnull
296 b2cfc4e2 2003-09-30 devnull *decpt = e + 1;
297 b2cfc4e2 2003-09-30 devnull
298 b2cfc4e2 2003-09-30 devnull /*
299 b2cfc4e2 2003-09-30 devnull * terminate the converted digits
300 b2cfc4e2 2003-09-30 devnull */
301 b2cfc4e2 2003-09-30 devnull s1[c2] = '\0';
302 b2cfc4e2 2003-09-30 devnull return &s1[c2];
303 b2cfc4e2 2003-09-30 devnull }
304 b2cfc4e2 2003-09-30 devnull
305 b2cfc4e2 2003-09-30 devnull /*
306 b2cfc4e2 2003-09-30 devnull * this function works like the standard dtoa, if you want it.
307 b2cfc4e2 2003-09-30 devnull */
308 b2cfc4e2 2003-09-30 devnull #if 0
309 b2cfc4e2 2003-09-30 devnull static char*
310 b2cfc4e2 2003-09-30 devnull __dtoa(double f, int mode, int ndigits, int *decpt, int *rsign, char **rve)
311 b2cfc4e2 2003-09-30 devnull {
312 b2cfc4e2 2003-09-30 devnull static char s2[NSIGNIF + 10];
313 b2cfc4e2 2003-09-30 devnull char *es;
314 b2cfc4e2 2003-09-30 devnull int chr, prec;
315 b2cfc4e2 2003-09-30 devnull
316 b2cfc4e2 2003-09-30 devnull switch(mode) {
317 b2cfc4e2 2003-09-30 devnull /* like 'e' */
318 b2cfc4e2 2003-09-30 devnull case 2:
319 b2cfc4e2 2003-09-30 devnull case 4:
320 b2cfc4e2 2003-09-30 devnull case 6:
321 b2cfc4e2 2003-09-30 devnull case 8:
322 b2cfc4e2 2003-09-30 devnull chr = 'e';
323 b2cfc4e2 2003-09-30 devnull break;
324 b2cfc4e2 2003-09-30 devnull /* like 'g' */
325 b2cfc4e2 2003-09-30 devnull case 0:
326 b2cfc4e2 2003-09-30 devnull case 1:
327 b2cfc4e2 2003-09-30 devnull default:
328 b2cfc4e2 2003-09-30 devnull chr = 'g';
329 b2cfc4e2 2003-09-30 devnull break;
330 b2cfc4e2 2003-09-30 devnull /* like 'f' */
331 b2cfc4e2 2003-09-30 devnull case 3:
332 b2cfc4e2 2003-09-30 devnull case 5:
333 b2cfc4e2 2003-09-30 devnull case 7:
334 b2cfc4e2 2003-09-30 devnull case 9:
335 b2cfc4e2 2003-09-30 devnull chr = 'f';
336 b2cfc4e2 2003-09-30 devnull break;
337 b2cfc4e2 2003-09-30 devnull }
338 b2cfc4e2 2003-09-30 devnull
339 b2cfc4e2 2003-09-30 devnull if(chr != 'f' && ndigits){
340 b2cfc4e2 2003-09-30 devnull ndigits--;
341 b2cfc4e2 2003-09-30 devnull }
342 b2cfc4e2 2003-09-30 devnull prec = ndigits;
343 b2cfc4e2 2003-09-30 devnull if(prec > NSIGNIF)
344 b2cfc4e2 2003-09-30 devnull prec = NSIGNIF;
345 b2cfc4e2 2003-09-30 devnull if(ndigits == 0)
346 b2cfc4e2 2003-09-30 devnull prec = NSIGNIF;
347 b2cfc4e2 2003-09-30 devnull es = xdodtoa(s2, f, chr, prec, decpt, rsign);
348 b2cfc4e2 2003-09-30 devnull
349 b2cfc4e2 2003-09-30 devnull /*
350 b2cfc4e2 2003-09-30 devnull * strip trailing 0
351 b2cfc4e2 2003-09-30 devnull */
352 b2cfc4e2 2003-09-30 devnull for(; es > s2 + 1; es--){
353 b2cfc4e2 2003-09-30 devnull if(es[-1] != '0'){
354 b2cfc4e2 2003-09-30 devnull break;
355 b2cfc4e2 2003-09-30 devnull }
356 b2cfc4e2 2003-09-30 devnull }
357 b2cfc4e2 2003-09-30 devnull *es = '\0';
358 b2cfc4e2 2003-09-30 devnull if(rve != NULL)
359 b2cfc4e2 2003-09-30 devnull *rve = es;
360 b2cfc4e2 2003-09-30 devnull return s2;
361 b2cfc4e2 2003-09-30 devnull }
362 b2cfc4e2 2003-09-30 devnull #endif
363 b2cfc4e2 2003-09-30 devnull
364 b2cfc4e2 2003-09-30 devnull static int
365 b2cfc4e2 2003-09-30 devnull fmtzdotpad(Fmt *f, int n, int pt)
366 b2cfc4e2 2003-09-30 devnull {
367 b2cfc4e2 2003-09-30 devnull char *t, *s;
368 b2cfc4e2 2003-09-30 devnull int i;
369 b2cfc4e2 2003-09-30 devnull Rune *rt, *rs;
370 b2cfc4e2 2003-09-30 devnull
371 b2cfc4e2 2003-09-30 devnull if(f->runes){
372 b2cfc4e2 2003-09-30 devnull rt = (Rune*)f->to;
373 b2cfc4e2 2003-09-30 devnull rs = (Rune*)f->stop;
374 b2cfc4e2 2003-09-30 devnull for(i = 0; i < n; i++){
375 b2cfc4e2 2003-09-30 devnull if(i == pt){
376 b2cfc4e2 2003-09-30 devnull FMTRCHAR(f, rt, rs, '.');
377 b2cfc4e2 2003-09-30 devnull }
378 b2cfc4e2 2003-09-30 devnull FMTRCHAR(f, rt, rs, '0');
379 b2cfc4e2 2003-09-30 devnull }
380 b2cfc4e2 2003-09-30 devnull f->nfmt += rt - (Rune*)f->to;
381 b2cfc4e2 2003-09-30 devnull f->to = rt;
382 b2cfc4e2 2003-09-30 devnull }else{
383 b2cfc4e2 2003-09-30 devnull t = (char*)f->to;
384 b2cfc4e2 2003-09-30 devnull s = (char*)f->stop;
385 b2cfc4e2 2003-09-30 devnull for(i = 0; i < n; i++){
386 b2cfc4e2 2003-09-30 devnull if(i == pt){
387 b2cfc4e2 2003-09-30 devnull FMTCHAR(f, t, s, '.');
388 b2cfc4e2 2003-09-30 devnull }
389 b2cfc4e2 2003-09-30 devnull FMTCHAR(f, t, s, '0');
390 b2cfc4e2 2003-09-30 devnull }
391 b2cfc4e2 2003-09-30 devnull f->nfmt += t - (char *)f->to;
392 b2cfc4e2 2003-09-30 devnull f->to = t;
393 b2cfc4e2 2003-09-30 devnull }
394 b2cfc4e2 2003-09-30 devnull return 0;
395 b2cfc4e2 2003-09-30 devnull }
396 b2cfc4e2 2003-09-30 devnull
397 b2cfc4e2 2003-09-30 devnull int
398 b2cfc4e2 2003-09-30 devnull __efgfmt(Fmt *fmt)
399 b2cfc4e2 2003-09-30 devnull {
400 b2cfc4e2 2003-09-30 devnull double f;
401 b2cfc4e2 2003-09-30 devnull char s1[NSIGNIF+10];
402 b2cfc4e2 2003-09-30 devnull int e, d, n;
403 b2cfc4e2 2003-09-30 devnull int c1, c2, c3, c4, ucase, sign, chr, prec, fl;
404 b2cfc4e2 2003-09-30 devnull
405 b2cfc4e2 2003-09-30 devnull f = va_arg(fmt->args, double);
406 b2cfc4e2 2003-09-30 devnull prec = FDEFLT;
407 b2cfc4e2 2003-09-30 devnull fl = fmt->flags;
408 b2cfc4e2 2003-09-30 devnull fmt->flags = 0;
409 b2cfc4e2 2003-09-30 devnull if(fl & FmtPrec)
410 b2cfc4e2 2003-09-30 devnull prec = fmt->prec;
411 b2cfc4e2 2003-09-30 devnull chr = fmt->r;
412 b2cfc4e2 2003-09-30 devnull ucase = 0;
413 b2cfc4e2 2003-09-30 devnull if(chr == 'E'){
414 b2cfc4e2 2003-09-30 devnull chr = 'e';
415 b2cfc4e2 2003-09-30 devnull ucase = 1;
416 b2cfc4e2 2003-09-30 devnull }else if(chr == 'F'){
417 b2cfc4e2 2003-09-30 devnull chr = 'f';
418 b2cfc4e2 2003-09-30 devnull ucase = 1;
419 b2cfc4e2 2003-09-30 devnull }else if(chr == 'G'){
420 b2cfc4e2 2003-09-30 devnull chr = 'g';
421 b2cfc4e2 2003-09-30 devnull ucase = 1;
422 b2cfc4e2 2003-09-30 devnull }
423 b2cfc4e2 2003-09-30 devnull if(prec > 0 && chr == 'g')
424 b2cfc4e2 2003-09-30 devnull prec--;
425 b2cfc4e2 2003-09-30 devnull if(prec < 0)
426 b2cfc4e2 2003-09-30 devnull prec = 0;
427 b2cfc4e2 2003-09-30 devnull
428 b2cfc4e2 2003-09-30 devnull xdodtoa(s1, f, chr, prec, &e, &sign);
429 b2cfc4e2 2003-09-30 devnull e--;
430 b2cfc4e2 2003-09-30 devnull if(*s1 == 'i' || *s1 == 'n'){
431 b2cfc4e2 2003-09-30 devnull if(ucase){
432 b2cfc4e2 2003-09-30 devnull if(*s1 == 'i'){
433 b2cfc4e2 2003-09-30 devnull strcpy(s1, "INF");
434 b2cfc4e2 2003-09-30 devnull }else{
435 b2cfc4e2 2003-09-30 devnull strcpy(s1, "NAN");
436 b2cfc4e2 2003-09-30 devnull }
437 b2cfc4e2 2003-09-30 devnull }
438 b2cfc4e2 2003-09-30 devnull fmt->flags = fl & (FmtWidth|FmtLeft);
439 b2cfc4e2 2003-09-30 devnull return __fmtcpy(fmt, (const void*)s1, 3, 3);
440 b2cfc4e2 2003-09-30 devnull }
441 b2cfc4e2 2003-09-30 devnull
442 b2cfc4e2 2003-09-30 devnull /*
443 b2cfc4e2 2003-09-30 devnull * copy into final place
444 b2cfc4e2 2003-09-30 devnull * c1 digits of leading '0'
445 b2cfc4e2 2003-09-30 devnull * c2 digits from conversion
446 b2cfc4e2 2003-09-30 devnull * c3 digits of trailing '0'
447 b2cfc4e2 2003-09-30 devnull * c4 digits after '.'
448 b2cfc4e2 2003-09-30 devnull */
449 b2cfc4e2 2003-09-30 devnull c1 = 0;
450 b2cfc4e2 2003-09-30 devnull c2 = prec + 1;
451 b2cfc4e2 2003-09-30 devnull c3 = 0;
452 b2cfc4e2 2003-09-30 devnull c4 = prec;
453 b2cfc4e2 2003-09-30 devnull switch(chr) {
454 b2cfc4e2 2003-09-30 devnull default:
455 b2cfc4e2 2003-09-30 devnull chr = 'e';
456 b2cfc4e2 2003-09-30 devnull break;
457 b2cfc4e2 2003-09-30 devnull case 'g':
458 b2cfc4e2 2003-09-30 devnull /*
459 b2cfc4e2 2003-09-30 devnull * decide on 'e' of 'f' style convers
460 b2cfc4e2 2003-09-30 devnull */
461 b2cfc4e2 2003-09-30 devnull if(e >= -4 && e <= prec) {
462 b2cfc4e2 2003-09-30 devnull c1 = -e;
463 b2cfc4e2 2003-09-30 devnull c4 = prec - e;
464 b2cfc4e2 2003-09-30 devnull chr = 'h'; /* flag for 'f' style */
465 b2cfc4e2 2003-09-30 devnull }
466 b2cfc4e2 2003-09-30 devnull break;
467 b2cfc4e2 2003-09-30 devnull case 'f':
468 b2cfc4e2 2003-09-30 devnull c1 = -e;
469 b2cfc4e2 2003-09-30 devnull if(c1 > prec)
470 b2cfc4e2 2003-09-30 devnull c1 = prec + 1;
471 b2cfc4e2 2003-09-30 devnull c2 += e;
472 b2cfc4e2 2003-09-30 devnull break;
473 b2cfc4e2 2003-09-30 devnull }
474 b2cfc4e2 2003-09-30 devnull
475 b2cfc4e2 2003-09-30 devnull /*
476 b2cfc4e2 2003-09-30 devnull * clean up c1 c2 and c3
477 b2cfc4e2 2003-09-30 devnull */
478 b2cfc4e2 2003-09-30 devnull if(c1 < 0)
479 b2cfc4e2 2003-09-30 devnull c1 = 0;
480 b2cfc4e2 2003-09-30 devnull if(c2 < 0)
481 b2cfc4e2 2003-09-30 devnull c2 = 0;
482 b2cfc4e2 2003-09-30 devnull if(c2 > NSIGNIF) {
483 b2cfc4e2 2003-09-30 devnull c3 = c2-NSIGNIF;
484 b2cfc4e2 2003-09-30 devnull c2 = NSIGNIF;
485 b2cfc4e2 2003-09-30 devnull }
486 b2cfc4e2 2003-09-30 devnull
487 b2cfc4e2 2003-09-30 devnull /*
488 b2cfc4e2 2003-09-30 devnull * trim trailing zeros for %g
489 b2cfc4e2 2003-09-30 devnull */
490 b2cfc4e2 2003-09-30 devnull if(!(fl & FmtSharp)
491 b2cfc4e2 2003-09-30 devnull && (chr == 'g' || chr == 'h')){
492 b2cfc4e2 2003-09-30 devnull if(c4 >= c3){
493 b2cfc4e2 2003-09-30 devnull c4 -= c3;
494 b2cfc4e2 2003-09-30 devnull c3 = 0;
495 b2cfc4e2 2003-09-30 devnull }else{
496 b2cfc4e2 2003-09-30 devnull c3 -= c4;
497 b2cfc4e2 2003-09-30 devnull c4 = 0;
498 b2cfc4e2 2003-09-30 devnull }
499 b2cfc4e2 2003-09-30 devnull while(c4 && c2 > 1 && s1[c2 - 1] == '0'){
500 b2cfc4e2 2003-09-30 devnull c4--;
501 b2cfc4e2 2003-09-30 devnull c2--;
502 b2cfc4e2 2003-09-30 devnull }
503 b2cfc4e2 2003-09-30 devnull }
504 b2cfc4e2 2003-09-30 devnull
505 b2cfc4e2 2003-09-30 devnull /*
506 b2cfc4e2 2003-09-30 devnull * calculate the total length
507 b2cfc4e2 2003-09-30 devnull */
508 b2cfc4e2 2003-09-30 devnull n = c1 + c2 + c3;
509 b2cfc4e2 2003-09-30 devnull if(sign || (fl & (FmtSign|FmtSpace)))
510 b2cfc4e2 2003-09-30 devnull n++;
511 b2cfc4e2 2003-09-30 devnull if(c4 || (fl & FmtSharp)){
512 b2cfc4e2 2003-09-30 devnull n++;
513 b2cfc4e2 2003-09-30 devnull }
514 b2cfc4e2 2003-09-30 devnull if(chr == 'e' || chr == 'g'){
515 b2cfc4e2 2003-09-30 devnull n += 4;
516 b2cfc4e2 2003-09-30 devnull if(e >= 100)
517 b2cfc4e2 2003-09-30 devnull n++;
518 b2cfc4e2 2003-09-30 devnull }
519 b2cfc4e2 2003-09-30 devnull
520 b2cfc4e2 2003-09-30 devnull /*
521 b2cfc4e2 2003-09-30 devnull * pad to width if right justified
522 b2cfc4e2 2003-09-30 devnull */
523 b2cfc4e2 2003-09-30 devnull if((fl & (FmtWidth|FmtLeft)) == FmtWidth && n < fmt->width){
524 b2cfc4e2 2003-09-30 devnull if(fl & FmtZero){
525 b2cfc4e2 2003-09-30 devnull c1 += fmt->width - n;
526 b2cfc4e2 2003-09-30 devnull }else{
527 b2cfc4e2 2003-09-30 devnull if(__fmtpad(fmt, fmt->width - n) < 0){
528 b2cfc4e2 2003-09-30 devnull return -1;
529 b2cfc4e2 2003-09-30 devnull }
530 b2cfc4e2 2003-09-30 devnull }
531 b2cfc4e2 2003-09-30 devnull }
532 b2cfc4e2 2003-09-30 devnull
533 b2cfc4e2 2003-09-30 devnull /*
534 b2cfc4e2 2003-09-30 devnull * sign
535 b2cfc4e2 2003-09-30 devnull */
536 b2cfc4e2 2003-09-30 devnull d = 0;
537 b2cfc4e2 2003-09-30 devnull if(sign)
538 b2cfc4e2 2003-09-30 devnull d = '-';
539 b2cfc4e2 2003-09-30 devnull else if(fl & FmtSign)
540 b2cfc4e2 2003-09-30 devnull d = '+';
541 b2cfc4e2 2003-09-30 devnull else if(fl & FmtSpace)
542 b2cfc4e2 2003-09-30 devnull d = ' ';
543 b2cfc4e2 2003-09-30 devnull if(d && fmtrune(fmt, d) < 0){
544 b2cfc4e2 2003-09-30 devnull return -1;
545 b2cfc4e2 2003-09-30 devnull }
546 b2cfc4e2 2003-09-30 devnull
547 b2cfc4e2 2003-09-30 devnull /*
548 b2cfc4e2 2003-09-30 devnull * copy digits
549 b2cfc4e2 2003-09-30 devnull */
550 b2cfc4e2 2003-09-30 devnull c4 = c1 + c2 + c3 - c4;
551 b2cfc4e2 2003-09-30 devnull if(c1 > 0){
552 b2cfc4e2 2003-09-30 devnull if(fmtzdotpad(fmt, c1, c4) < 0){
553 b2cfc4e2 2003-09-30 devnull return -1;
554 b2cfc4e2 2003-09-30 devnull }
555 b2cfc4e2 2003-09-30 devnull c4 -= c1;
556 b2cfc4e2 2003-09-30 devnull }
557 b2cfc4e2 2003-09-30 devnull d = 0;
558 b2cfc4e2 2003-09-30 devnull if(c4 >= 0 && c4 < c2){
559 b2cfc4e2 2003-09-30 devnull if(__fmtcpy(fmt, s1, c4, c4) < 0 || fmtrune(fmt, '.') < 0)
560 b2cfc4e2 2003-09-30 devnull return -1;
561 b2cfc4e2 2003-09-30 devnull d = c4;
562 b2cfc4e2 2003-09-30 devnull c2 -= c4;
563 b2cfc4e2 2003-09-30 devnull c4 = -1;
564 b2cfc4e2 2003-09-30 devnull }
565 b2cfc4e2 2003-09-30 devnull if(__fmtcpy(fmt, (const void*)(s1 + d), c2, c2) < 0){
566 b2cfc4e2 2003-09-30 devnull return -1;
567 b2cfc4e2 2003-09-30 devnull }
568 b2cfc4e2 2003-09-30 devnull c4 -= c2;
569 b2cfc4e2 2003-09-30 devnull if(c3 > 0){
570 b2cfc4e2 2003-09-30 devnull if(fmtzdotpad(fmt, c3, c4) < 0){
571 b2cfc4e2 2003-09-30 devnull return -1;
572 b2cfc4e2 2003-09-30 devnull }
573 b2cfc4e2 2003-09-30 devnull c4 -= c3;
574 b2cfc4e2 2003-09-30 devnull }
575 b2cfc4e2 2003-09-30 devnull
576 b2cfc4e2 2003-09-30 devnull /*
577 b2cfc4e2 2003-09-30 devnull * strip trailing '0' on g conv
578 b2cfc4e2 2003-09-30 devnull */
579 b2cfc4e2 2003-09-30 devnull if((fl & FmtSharp) && c4 == 0 && fmtrune(fmt, '.') < 0){
580 b2cfc4e2 2003-09-30 devnull return -1;
581 b2cfc4e2 2003-09-30 devnull }
582 b2cfc4e2 2003-09-30 devnull if(chr == 'e' || chr == 'g') {
583 b2cfc4e2 2003-09-30 devnull d = 0;
584 b2cfc4e2 2003-09-30 devnull if(ucase)
585 b2cfc4e2 2003-09-30 devnull s1[d++] = 'E';
586 b2cfc4e2 2003-09-30 devnull else
587 b2cfc4e2 2003-09-30 devnull s1[d++] = 'e';
588 b2cfc4e2 2003-09-30 devnull c1 = e;
589 b2cfc4e2 2003-09-30 devnull if(c1 < 0) {
590 b2cfc4e2 2003-09-30 devnull s1[d++] = '-';
591 b2cfc4e2 2003-09-30 devnull c1 = -c1;
592 b2cfc4e2 2003-09-30 devnull } else
593 b2cfc4e2 2003-09-30 devnull s1[d++] = '+';
594 b2cfc4e2 2003-09-30 devnull if(c1 >= 100) {
595 b2cfc4e2 2003-09-30 devnull s1[d++] = c1/100 + '0';
596 b2cfc4e2 2003-09-30 devnull c1 = c1%100;
597 b2cfc4e2 2003-09-30 devnull }
598 b2cfc4e2 2003-09-30 devnull s1[d++] = c1/10 + '0';
599 b2cfc4e2 2003-09-30 devnull s1[d++] = c1%10 + '0';
600 b2cfc4e2 2003-09-30 devnull if(__fmtcpy(fmt, s1, d, d) < 0){
601 b2cfc4e2 2003-09-30 devnull return -1;
602 b2cfc4e2 2003-09-30 devnull }
603 b2cfc4e2 2003-09-30 devnull }
604 b2cfc4e2 2003-09-30 devnull if((fl & (FmtWidth|FmtLeft)) == (FmtWidth|FmtLeft) && n < fmt->width){
605 b2cfc4e2 2003-09-30 devnull if(__fmtpad(fmt, fmt->width - n) < 0){
606 b2cfc4e2 2003-09-30 devnull return -1;
607 b2cfc4e2 2003-09-30 devnull }
608 b2cfc4e2 2003-09-30 devnull }
609 b2cfc4e2 2003-09-30 devnull return 0;
610 b2cfc4e2 2003-09-30 devnull }