Blame


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