1 85231fd8 2006-05-21 devnull /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
2 91c13e54 2004-02-29 devnull #include <stdio.h>
3 91c13e54 2004-02-29 devnull #include <math.h>
4 91c13e54 2004-02-29 devnull #include <float.h>
5 91c13e54 2004-02-29 devnull #include <string.h>
6 91c13e54 2004-02-29 devnull #include <stdlib.h>
7 91c13e54 2004-02-29 devnull #include <errno.h>
8 91c13e54 2004-02-29 devnull #include <stdarg.h>
9 e5aa96ac 2004-12-26 devnull #include <fmt.h>
10 f8955f18 2006-05-22 devnull #include <assert.h>
11 e5aa96ac 2004-12-26 devnull #include "plan9.h"
12 91c13e54 2004-02-29 devnull #include "fmt.h"
13 91c13e54 2004-02-29 devnull #include "fmtdef.h"
14 f8955f18 2006-05-22 devnull #include "nan.h"
18 a76c0fd4 2004-12-26 devnull FDIGIT = 30,
19 91c13e54 2004-02-29 devnull FDEFLT = 6,
20 91c13e54 2004-02-29 devnull NSIGNIF = 17
24 91c13e54 2004-02-29 devnull * first few powers of 10, enough for about 1/2 of the
25 91c13e54 2004-02-29 devnull * total space for doubles.
27 91c13e54 2004-02-29 devnull static double pows10[] =
29 fa325e9b 2020-01-10 cross 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
30 fa325e9b 2020-01-10 cross 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
31 fa325e9b 2020-01-10 cross 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29,
32 fa325e9b 2020-01-10 cross 1e30, 1e31, 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39,
33 fa325e9b 2020-01-10 cross 1e40, 1e41, 1e42, 1e43, 1e44, 1e45, 1e46, 1e47, 1e48, 1e49,
34 fa325e9b 2020-01-10 cross 1e50, 1e51, 1e52, 1e53, 1e54, 1e55, 1e56, 1e57, 1e58, 1e59,
35 fa325e9b 2020-01-10 cross 1e60, 1e61, 1e62, 1e63, 1e64, 1e65, 1e66, 1e67, 1e68, 1e69,
36 fa325e9b 2020-01-10 cross 1e70, 1e71, 1e72, 1e73, 1e74, 1e75, 1e76, 1e77, 1e78, 1e79,
37 fa325e9b 2020-01-10 cross 1e80, 1e81, 1e82, 1e83, 1e84, 1e85, 1e86, 1e87, 1e88, 1e89,
38 fa325e9b 2020-01-10 cross 1e90, 1e91, 1e92, 1e93, 1e94, 1e95, 1e96, 1e97, 1e98, 1e99,
39 fa325e9b 2020-01-10 cross 1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109,
40 fa325e9b 2020-01-10 cross 1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119,
41 fa325e9b 2020-01-10 cross 1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129,
42 fa325e9b 2020-01-10 cross 1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139,
43 fa325e9b 2020-01-10 cross 1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149,
44 fa325e9b 2020-01-10 cross 1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159,
46 f8955f18 2006-05-22 devnull #define npows10 ((int)(sizeof(pows10)/sizeof(pows10[0])))
47 f8955f18 2006-05-22 devnull #define pow10(x) fmtpow10(x)
49 91c13e54 2004-02-29 devnull static double
50 91c13e54 2004-02-29 devnull pow10(int n)
52 91c13e54 2004-02-29 devnull double d;
56 91c13e54 2004-02-29 devnull if(n < 0){
61 f8955f18 2006-05-22 devnull if(n < npows10)
62 91c13e54 2004-02-29 devnull d = pows10[n];
64 f8955f18 2006-05-22 devnull d = pows10[npows10-1];
66 f8955f18 2006-05-22 devnull n -= npows10 - 1;
67 f8955f18 2006-05-22 devnull if(n < npows10){
68 91c13e54 2004-02-29 devnull d *= pows10[n];
71 f8955f18 2006-05-22 devnull d *= pows10[npows10 - 1];
75 91c13e54 2004-02-29 devnull return 1./d;
76 91c13e54 2004-02-29 devnull return d;
80 f8955f18 2006-05-22 devnull * add 1 to the decimal integer string a of length n.
81 f8955f18 2006-05-22 devnull * if 99999 overflows into 10000, return 1 to tell caller
82 f8955f18 2006-05-22 devnull * to move the virtual decimal point.
84 91c13e54 2004-02-29 devnull static int
85 f8955f18 2006-05-22 devnull xadd1(char *a, int n)
90 f8955f18 2006-05-22 devnull if(n < 0 || n > NSIGNIF)
91 91c13e54 2004-02-29 devnull return 0;
92 f8955f18 2006-05-22 devnull for(b = a+n-1; b >= a; b--) {
93 f8955f18 2006-05-22 devnull c = *b + 1;
94 91c13e54 2004-02-29 devnull if(c <= '9') {
96 91c13e54 2004-02-29 devnull return 0;
98 91c13e54 2004-02-29 devnull *b = '0';
101 f8955f18 2006-05-22 devnull * need to overflow adding digit.
102 f8955f18 2006-05-22 devnull * shift number down and insert 1 at beginning.
103 f8955f18 2006-05-22 devnull * decimal is known to be 0s or we wouldn't
104 f8955f18 2006-05-22 devnull * have gotten this far. (e.g., 99999+1 => 00000)
106 f8955f18 2006-05-22 devnull a[0] = '1';
107 91c13e54 2004-02-29 devnull return 1;
111 f8955f18 2006-05-22 devnull * subtract 1 from the decimal integer string a.
112 f8955f18 2006-05-22 devnull * if 10000 underflows into 09999, make it 99999
113 fa325e9b 2020-01-10 cross * and return 1 to tell caller to move the virtual
114 f8955f18 2006-05-22 devnull * decimal point. this way, xsub1 is inverse of xadd1.
116 91c13e54 2004-02-29 devnull static int
117 f8955f18 2006-05-22 devnull xsub1(char *a, int n)
119 91c13e54 2004-02-29 devnull char *b;
122 f8955f18 2006-05-22 devnull if(n < 0 || n > NSIGNIF)
123 f8955f18 2006-05-22 devnull return 0;
124 f8955f18 2006-05-22 devnull for(b = a+n-1; b >= a; b--) {
125 f8955f18 2006-05-22 devnull c = *b - 1;
126 91c13e54 2004-02-29 devnull if(c >= '0') {
127 f8955f18 2006-05-22 devnull if(c == '0' && b == a) {
129 f8955f18 2006-05-22 devnull * just zeroed the top digit; shift everyone up.
130 f8955f18 2006-05-22 devnull * decimal is known to be 9s or we wouldn't
131 f8955f18 2006-05-22 devnull * have gotten this far. (e.g., 10000-1 => 09999)
133 f8955f18 2006-05-22 devnull *b = '9';
134 f8955f18 2006-05-22 devnull return 1;
137 91c13e54 2004-02-29 devnull return 0;
139 91c13e54 2004-02-29 devnull *b = '9';
142 f8955f18 2006-05-22 devnull * can't get here. the number a is always normalized
143 f8955f18 2006-05-22 devnull * so that it has a nonzero first digit.
145 f8955f18 2006-05-22 devnull abort();
149 f8955f18 2006-05-22 devnull * format exponent like sprintf(p, "e%+02d", e)
151 91c13e54 2004-02-29 devnull static void
152 f8955f18 2006-05-22 devnull xfmtexp(char *p, int e, int ucase)
154 f8955f18 2006-05-22 devnull char se[9];
157 f8955f18 2006-05-22 devnull *p++ = ucase ? 'E' : 'e';
158 f8955f18 2006-05-22 devnull if(e < 0) {
159 f8955f18 2006-05-22 devnull *p++ = '-';
162 f8955f18 2006-05-22 devnull *p++ = '+';
164 f8955f18 2006-05-22 devnull while(e) {
165 f8955f18 2006-05-22 devnull se[i++] = e % 10 + '0';
166 f8955f18 2006-05-22 devnull e /= 10;
168 f8955f18 2006-05-22 devnull while(i < 2)
169 f8955f18 2006-05-22 devnull se[i++] = '0';
170 f8955f18 2006-05-22 devnull while(i > 0)
171 f8955f18 2006-05-22 devnull *p++ = se[--i];
172 f8955f18 2006-05-22 devnull *p++ = '\0';
176 f8955f18 2006-05-22 devnull * compute decimal integer m, exp such that:
177 f8955f18 2006-05-22 devnull * f = m*10^exp
178 f8955f18 2006-05-22 devnull * m is as short as possible with losing exactness
179 f8955f18 2006-05-22 devnull * assumes special cases (NaN, +Inf, -Inf) have been handled.
181 f8955f18 2006-05-22 devnull static void
182 f8955f18 2006-05-22 devnull xdtoa(double f, char *s, int *exp, int *neg, int *ns)
184 f8955f18 2006-05-22 devnull int c, d, e2, e, ee, i, ndigit, oerrno;
185 f8955f18 2006-05-22 devnull char tmp[NSIGNIF+10];
186 f8955f18 2006-05-22 devnull double g;
188 f8955f18 2006-05-22 devnull oerrno = errno; /* in case strtod smashes errno */
191 f8955f18 2006-05-22 devnull * make f non-negative.
193 f8955f18 2006-05-22 devnull *neg = 0;
194 91c13e54 2004-02-29 devnull if(f < 0) {
196 f8955f18 2006-05-22 devnull *neg = 1;
200 f8955f18 2006-05-22 devnull * must handle zero specially.
202 f8955f18 2006-05-22 devnull if(f == 0){
203 f8955f18 2006-05-22 devnull *exp = 0;
204 f8955f18 2006-05-22 devnull s[0] = '0';
205 f8955f18 2006-05-22 devnull s[1] = '\0';
206 f8955f18 2006-05-22 devnull *ns = 1;
211 f8955f18 2006-05-22 devnull * find g,e such that f = g*10^e.
212 f8955f18 2006-05-22 devnull * guess 10-exponent using 2-exponent, then fine tune.
214 f8955f18 2006-05-22 devnull frexp(f, &e2);
215 f8955f18 2006-05-22 devnull e = (int)(e2 * .301029995664);
216 f8955f18 2006-05-22 devnull g = f * pow10(-e);
217 f8955f18 2006-05-22 devnull while(g < 1) {
219 f8955f18 2006-05-22 devnull g = f * pow10(-e);
221 f8955f18 2006-05-22 devnull while(g >= 10) {
223 f8955f18 2006-05-22 devnull g = f * pow10(-e);
227 f8955f18 2006-05-22 devnull * convert NSIGNIF digits as a first approximation.
229 f8955f18 2006-05-22 devnull for(i=0; i<NSIGNIF; i++) {
230 f8955f18 2006-05-22 devnull d = (int)g;
231 f8955f18 2006-05-22 devnull s[i] = d+'0';
232 f8955f18 2006-05-22 devnull g = (g-d) * 10;
234 f8955f18 2006-05-22 devnull s[i] = 0;
237 f8955f18 2006-05-22 devnull * adjust e because s is 314159... not 3.14159...
239 f8955f18 2006-05-22 devnull e -= NSIGNIF-1;
240 f8955f18 2006-05-22 devnull xfmtexp(s+NSIGNIF, e, 0);
243 f8955f18 2006-05-22 devnull * adjust conversion until strtod(s) == f exactly.
245 f8955f18 2006-05-22 devnull for(i=0; i<10; i++) {
246 d17b0403 2009-07-29 rsc g = fmtstrtod(s, nil);
247 91c13e54 2004-02-29 devnull if(f > g) {
248 f8955f18 2006-05-22 devnull if(xadd1(s, NSIGNIF)) {
249 f8955f18 2006-05-22 devnull /* gained a digit */
251 f8955f18 2006-05-22 devnull xfmtexp(s+NSIGNIF, e, 0);
253 91c13e54 2004-02-29 devnull continue;
255 91c13e54 2004-02-29 devnull if(f < g) {
256 f8955f18 2006-05-22 devnull if(xsub1(s, NSIGNIF)) {
257 f8955f18 2006-05-22 devnull /* lost a digit */
259 f8955f18 2006-05-22 devnull xfmtexp(s+NSIGNIF, e, 0);
261 91c13e54 2004-02-29 devnull continue;
267 f8955f18 2006-05-22 devnull * play with the decimal to try to simplify.
271 f8955f18 2006-05-22 devnull * bump last few digits up to 9 if we can
273 f8955f18 2006-05-22 devnull for(i=NSIGNIF-1; i>=NSIGNIF-3; i--) {
274 f8955f18 2006-05-22 devnull c = s[i];
275 f8955f18 2006-05-22 devnull if(c != '9') {
276 f8955f18 2006-05-22 devnull s[i] = '9';
277 d17b0403 2009-07-29 rsc g = fmtstrtod(s, nil);
278 f8955f18 2006-05-22 devnull if(g != f) {
279 f8955f18 2006-05-22 devnull s[i] = c;
286 f8955f18 2006-05-22 devnull * add 1 in hopes of turning 9s to 0s
288 f8955f18 2006-05-22 devnull if(s[NSIGNIF-1] == '9') {
289 f8955f18 2006-05-22 devnull strcpy(tmp, s);
291 f8955f18 2006-05-22 devnull if(xadd1(tmp, NSIGNIF)) {
293 f8955f18 2006-05-22 devnull xfmtexp(tmp+NSIGNIF, ee, 0);
295 d17b0403 2009-07-29 rsc g = fmtstrtod(tmp, nil);
296 f8955f18 2006-05-22 devnull if(g == f) {
297 f8955f18 2006-05-22 devnull strcpy(s, tmp);
303 f8955f18 2006-05-22 devnull * bump last few digits down to 0 as we can.
305 f8955f18 2006-05-22 devnull for(i=NSIGNIF-1; i>=NSIGNIF-3; i--) {
306 f8955f18 2006-05-22 devnull c = s[i];
307 f8955f18 2006-05-22 devnull if(c != '0') {
308 f8955f18 2006-05-22 devnull s[i] = '0';
309 d17b0403 2009-07-29 rsc g = fmtstrtod(s, nil);
310 f8955f18 2006-05-22 devnull if(g != f) {
311 f8955f18 2006-05-22 devnull s[i] = c;
318 f8955f18 2006-05-22 devnull * remove trailing zeros.
320 f8955f18 2006-05-22 devnull ndigit = NSIGNIF;
321 f8955f18 2006-05-22 devnull while(ndigit > 1 && s[ndigit-1] == '0'){
323 f8955f18 2006-05-22 devnull --ndigit;
325 f8955f18 2006-05-22 devnull s[ndigit] = 0;
326 f8955f18 2006-05-22 devnull *exp = e;
327 f8955f18 2006-05-22 devnull *ns = ndigit;
328 f8955f18 2006-05-22 devnull errno = oerrno;
331 f8955f18 2006-05-22 devnull #ifdef PLAN9PORT
332 f8955f18 2006-05-22 devnull static char *special[] = { "NaN", "NaN", "+Inf", "+Inf", "-Inf", "-Inf" };
334 f8955f18 2006-05-22 devnull static char *special[] = { "nan", "NAN", "inf", "INF", "-inf", "-INF" };
338 f8955f18 2006-05-22 devnull __efgfmt(Fmt *fmt)
340 f8955f18 2006-05-22 devnull char buf[NSIGNIF+10], *dot, *digits, *p, *s, suf[10], *t;
341 f8955f18 2006-05-22 devnull double f;
342 f8955f18 2006-05-22 devnull int c, chr, dotwid, e, exp, fl, ndigits, neg, newndigits;
343 f8955f18 2006-05-22 devnull int pad, point, prec, realchr, sign, sufwid, ucase, wid, z1, z2;
344 f8955f18 2006-05-22 devnull Rune r, *rs, *rt;
346 56b2179d 2006-06-26 devnull if(fmt->flags&FmtLong)
347 66cf8a39 2006-06-26 devnull f = va_arg(fmt->args, long double);
349 66cf8a39 2006-06-26 devnull f = va_arg(fmt->args, double);
352 f8955f18 2006-05-22 devnull * extract formatting flags
354 f8955f18 2006-05-22 devnull fl = fmt->flags;
355 f8955f18 2006-05-22 devnull fmt->flags = 0;
356 f8955f18 2006-05-22 devnull prec = FDEFLT;
357 f8955f18 2006-05-22 devnull if(fl & FmtPrec)
358 f8955f18 2006-05-22 devnull prec = fmt->prec;
359 f8955f18 2006-05-22 devnull chr = fmt->r;
360 f8955f18 2006-05-22 devnull ucase = 0;
361 f8955f18 2006-05-22 devnull switch(chr) {
362 f8955f18 2006-05-22 devnull case 'A':
363 f8955f18 2006-05-22 devnull case 'E':
364 f8955f18 2006-05-22 devnull case 'F':
365 f8955f18 2006-05-22 devnull case 'G':
366 f8955f18 2006-05-22 devnull chr += 'a'-'A';
367 f8955f18 2006-05-22 devnull ucase = 1;
372 f8955f18 2006-05-22 devnull * pick off special numbers.
374 f8955f18 2006-05-22 devnull if(__isNaN(f)) {
375 f8955f18 2006-05-22 devnull s = special[0+ucase];
376 f8955f18 2006-05-22 devnull special:
377 f8955f18 2006-05-22 devnull fmt->flags = fl & (FmtWidth|FmtLeft);
378 f8955f18 2006-05-22 devnull return __fmtcpy(fmt, s, strlen(s), strlen(s));
380 f8955f18 2006-05-22 devnull if(__isInf(f, 1)) {
381 f8955f18 2006-05-22 devnull s = special[2+ucase];
382 f8955f18 2006-05-22 devnull goto special;
384 f8955f18 2006-05-22 devnull if(__isInf(f, -1)) {
385 f8955f18 2006-05-22 devnull s = special[4+ucase];
386 f8955f18 2006-05-22 devnull goto special;
390 f8955f18 2006-05-22 devnull * get exact representation.
392 f8955f18 2006-05-22 devnull digits = buf;
393 f8955f18 2006-05-22 devnull xdtoa(f, digits, &exp, &neg, &ndigits);
396 f8955f18 2006-05-22 devnull * get locale's decimal point.
398 f8955f18 2006-05-22 devnull dot = fmt->decimal;
399 f8955f18 2006-05-22 devnull if(dot == nil)
400 f8955f18 2006-05-22 devnull dot = ".";
401 f8955f18 2006-05-22 devnull dotwid = utflen(dot);
404 f8955f18 2006-05-22 devnull * now the formatting fun begins.
405 f8955f18 2006-05-22 devnull * compute parameters for actual fmt:
407 f8955f18 2006-05-22 devnull * pad: number of spaces to insert before/after field.
408 f8955f18 2006-05-22 devnull * z1: number of zeros to insert before digits
409 f8955f18 2006-05-22 devnull * z2: number of zeros to insert after digits
410 f8955f18 2006-05-22 devnull * point: number of digits to print before decimal point
411 f8955f18 2006-05-22 devnull * ndigits: number of digits to use from digits[]
412 f8955f18 2006-05-22 devnull * suf: trailing suffix, like "e-5"
414 f8955f18 2006-05-22 devnull realchr = chr;
415 f8955f18 2006-05-22 devnull switch(chr){
416 f8955f18 2006-05-22 devnull case 'g':
418 f8955f18 2006-05-22 devnull * convert to at most prec significant digits. (prec=0 means 1)
420 f8955f18 2006-05-22 devnull if(prec == 0)
421 f8955f18 2006-05-22 devnull prec = 1;
422 f8955f18 2006-05-22 devnull if(ndigits > prec) {
423 f8955f18 2006-05-22 devnull if(digits[prec] >= '5' && xadd1(digits, prec))
425 f8955f18 2006-05-22 devnull exp += ndigits-prec;
426 f8955f18 2006-05-22 devnull ndigits = prec;
430 f8955f18 2006-05-22 devnull * extra rules for %g (implemented below):
431 f8955f18 2006-05-22 devnull * trailing zeros removed after decimal unless FmtSharp.
432 f8955f18 2006-05-22 devnull * decimal point only if digit follows.
435 f8955f18 2006-05-22 devnull /* fall through to %e */
436 f8955f18 2006-05-22 devnull default:
437 f8955f18 2006-05-22 devnull case 'e':
439 f8955f18 2006-05-22 devnull * one significant digit before decimal, no leading zeros.
441 f8955f18 2006-05-22 devnull point = 1;
445 f8955f18 2006-05-22 devnull * decimal point is after ndigits digits right now.
446 f8955f18 2006-05-22 devnull * slide to be after first.
448 f8955f18 2006-05-22 devnull e = exp + (ndigits-1);
451 f8955f18 2006-05-22 devnull * if this is %g, check exponent and convert prec
453 f8955f18 2006-05-22 devnull if(realchr == 'g') {
454 f8955f18 2006-05-22 devnull if(-4 <= e && e < prec)
455 f8955f18 2006-05-22 devnull goto casef;
456 f8955f18 2006-05-22 devnull prec--; /* one digit before decimal; rest after */
460 f8955f18 2006-05-22 devnull * compute trailing zero padding or truncate digits.
462 f8955f18 2006-05-22 devnull if(1+prec >= ndigits)
463 f8955f18 2006-05-22 devnull z2 = 1+prec - ndigits;
466 f8955f18 2006-05-22 devnull * truncate digits
468 f8955f18 2006-05-22 devnull assert(realchr != 'g');
469 f8955f18 2006-05-22 devnull newndigits = 1+prec;
470 f8955f18 2006-05-22 devnull if(digits[newndigits] >= '5' && xadd1(digits, newndigits)) {
472 f8955f18 2006-05-22 devnull * had 999e4, now have 100e5
476 f8955f18 2006-05-22 devnull ndigits = newndigits;
479 f8955f18 2006-05-22 devnull xfmtexp(suf, e, ucase);
480 f8955f18 2006-05-22 devnull sufwid = strlen(suf);
484 f8955f18 2006-05-22 devnull case 'f':
486 f8955f18 2006-05-22 devnull * determine where digits go with respect to decimal point
488 f8955f18 2006-05-22 devnull if(ndigits+exp > 0) {
489 f8955f18 2006-05-22 devnull point = ndigits+exp;
491 f8955f18 2006-05-22 devnull } else {
492 f8955f18 2006-05-22 devnull point = 1;
493 f8955f18 2006-05-22 devnull z1 = 1 + -(ndigits+exp);
497 f8955f18 2006-05-22 devnull * %g specifies prec = number of significant digits
498 f8955f18 2006-05-22 devnull * convert to number of digits after decimal point
500 f8955f18 2006-05-22 devnull if(realchr == 'g')
501 f8955f18 2006-05-22 devnull prec += z1 - point;
504 f8955f18 2006-05-22 devnull * compute trailing zero padding or truncate digits.
506 f8955f18 2006-05-22 devnull if(point+prec >= z1+ndigits)
507 f8955f18 2006-05-22 devnull z2 = point+prec - (z1+ndigits);
510 f8955f18 2006-05-22 devnull * truncate digits
512 f8955f18 2006-05-22 devnull assert(realchr != 'g');
513 f8955f18 2006-05-22 devnull newndigits = point+prec - z1;
514 f8955f18 2006-05-22 devnull if(newndigits < 0) {
515 f8955f18 2006-05-22 devnull z1 += newndigits;
516 f8955f18 2006-05-22 devnull newndigits = 0;
517 f8955f18 2006-05-22 devnull } else if(newndigits == 0) {
518 f8955f18 2006-05-22 devnull /* perhaps round up */
519 f8955f18 2006-05-22 devnull if(digits[0] >= '5'){
520 f8955f18 2006-05-22 devnull digits[0] = '1';
521 f8955f18 2006-05-22 devnull newndigits = 1;
522 f8955f18 2006-05-22 devnull goto newdigit;
524 f8955f18 2006-05-22 devnull } else if(digits[newndigits] >= '5' && xadd1(digits, newndigits)) {
526 f8955f18 2006-05-22 devnull * digits was 999, is now 100; make it 1000
528 f8955f18 2006-05-22 devnull digits[newndigits++] = '0';
529 f8955f18 2006-05-22 devnull newdigit:
531 f8955f18 2006-05-22 devnull * account for new digit
533 f8955f18 2006-05-22 devnull if(z1) /* 0.099 => 0.100 or 0.99 => 1.00*/
535 f8955f18 2006-05-22 devnull else /* 9.99 => 10.00 */
536 f8955f18 2006-05-22 devnull point++;
539 f8955f18 2006-05-22 devnull ndigits = newndigits;
541 f8955f18 2006-05-22 devnull sufwid = 0;
546 f8955f18 2006-05-22 devnull * if %g is given without FmtSharp, remove trailing zeros.
547 f8955f18 2006-05-22 devnull * must do after truncation, so that e.g. print %.3g 1.001
548 f8955f18 2006-05-22 devnull * produces 1, not 1.00. sorry, but them's the rules.
550 f8955f18 2006-05-22 devnull if(realchr == 'g' && !(fl & FmtSharp)) {
551 f8955f18 2006-05-22 devnull if(z1+ndigits+z2 >= point) {
552 f8955f18 2006-05-22 devnull if(z1+ndigits < point)
553 f8955f18 2006-05-22 devnull z2 = point - (z1+ndigits);
556 f8955f18 2006-05-22 devnull while(z1+ndigits > point && digits[ndigits-1] == '0')
557 f8955f18 2006-05-22 devnull ndigits--;
563 f8955f18 2006-05-22 devnull * compute width of all digits and decimal point and suffix if any
565 f8955f18 2006-05-22 devnull wid = z1+ndigits+z2;
566 f8955f18 2006-05-22 devnull if(wid > point)
567 f8955f18 2006-05-22 devnull wid += dotwid;
568 f8955f18 2006-05-22 devnull else if(wid == point){
569 f8955f18 2006-05-22 devnull if(fl & FmtSharp)
570 f8955f18 2006-05-22 devnull wid += dotwid;
572 f8955f18 2006-05-22 devnull point++; /* do not print any decimal point */
574 f8955f18 2006-05-22 devnull wid += sufwid;
577 f8955f18 2006-05-22 devnull * determine sign
579 f8955f18 2006-05-22 devnull sign = 0;
581 f8955f18 2006-05-22 devnull sign = '-';
582 f8955f18 2006-05-22 devnull else if(fl & FmtSign)
583 f8955f18 2006-05-22 devnull sign = '+';
584 f8955f18 2006-05-22 devnull else if(fl & FmtSpace)
585 f8955f18 2006-05-22 devnull sign = ' ';
586 f8955f18 2006-05-22 devnull if(sign)
590 f8955f18 2006-05-22 devnull * compute padding
592 f8955f18 2006-05-22 devnull pad = 0;
593 f8955f18 2006-05-22 devnull if((fl & FmtWidth) && fmt->width > wid)
594 f8955f18 2006-05-22 devnull pad = fmt->width - wid;
595 f8955f18 2006-05-22 devnull if(pad && !(fl & FmtLeft) && (fl & FmtZero)){
596 f8955f18 2006-05-22 devnull z1 += pad;
597 f8955f18 2006-05-22 devnull point += pad;
598 f8955f18 2006-05-22 devnull pad = 0;
602 f8955f18 2006-05-22 devnull * format the actual field. too bad about doing this twice.
604 f8955f18 2006-05-22 devnull if(fmt->runes){
605 f8955f18 2006-05-22 devnull if(pad && !(fl & FmtLeft) && __rfmtpad(fmt, pad) < 0)
606 f8955f18 2006-05-22 devnull return -1;
607 f8955f18 2006-05-22 devnull rt = (Rune*)fmt->to;
608 f8955f18 2006-05-22 devnull rs = (Rune*)fmt->stop;
609 f8955f18 2006-05-22 devnull if(sign)
610 f8955f18 2006-05-22 devnull FMTRCHAR(fmt, rt, rs, sign);
611 f8955f18 2006-05-22 devnull while(z1>0 || ndigits>0 || z2>0) {
612 f8955f18 2006-05-22 devnull if(z1 > 0){
614 f8955f18 2006-05-22 devnull c = '0';
615 f8955f18 2006-05-22 devnull }else if(ndigits > 0){
616 f8955f18 2006-05-22 devnull ndigits--;
617 f8955f18 2006-05-22 devnull c = *digits++;
620 f8955f18 2006-05-22 devnull c = '0';
622 f8955f18 2006-05-22 devnull FMTRCHAR(fmt, rt, rs, c);
623 f8955f18 2006-05-22 devnull if(--point == 0) {
624 f8955f18 2006-05-22 devnull for(p = dot; *p; ){
625 f8955f18 2006-05-22 devnull p += chartorune(&r, p);
626 f8955f18 2006-05-22 devnull FMTRCHAR(fmt, rt, rs, r);
630 f8955f18 2006-05-22 devnull fmt->nfmt += rt - (Rune*)fmt->to;
631 f8955f18 2006-05-22 devnull fmt->to = rt;
632 f8955f18 2006-05-22 devnull if(sufwid && __fmtcpy(fmt, suf, sufwid, sufwid) < 0)
633 f8955f18 2006-05-22 devnull return -1;
634 f8955f18 2006-05-22 devnull if(pad && (fl & FmtLeft) && __rfmtpad(fmt, pad) < 0)
635 f8955f18 2006-05-22 devnull return -1;
637 f8955f18 2006-05-22 devnull if(pad && !(fl & FmtLeft) && __fmtpad(fmt, pad) < 0)
638 f8955f18 2006-05-22 devnull return -1;
639 f8955f18 2006-05-22 devnull t = (char*)fmt->to;
640 f8955f18 2006-05-22 devnull s = (char*)fmt->stop;
641 f8955f18 2006-05-22 devnull if(sign)
642 f8955f18 2006-05-22 devnull FMTCHAR(fmt, t, s, sign);
643 f8955f18 2006-05-22 devnull while(z1>0 || ndigits>0 || z2>0) {
644 f8955f18 2006-05-22 devnull if(z1 > 0){
646 f8955f18 2006-05-22 devnull c = '0';
647 f8955f18 2006-05-22 devnull }else if(ndigits > 0){
648 f8955f18 2006-05-22 devnull ndigits--;
649 f8955f18 2006-05-22 devnull c = *digits++;
652 f8955f18 2006-05-22 devnull c = '0';
654 f8955f18 2006-05-22 devnull FMTCHAR(fmt, t, s, c);
655 f8955f18 2006-05-22 devnull if(--point == 0)
656 f8955f18 2006-05-22 devnull for(p=dot; *p; p++)
657 f8955f18 2006-05-22 devnull FMTCHAR(fmt, t, s, *p);
659 f8955f18 2006-05-22 devnull fmt->nfmt += t - (char*)fmt->to;
660 f8955f18 2006-05-22 devnull fmt->to = t;
661 f8955f18 2006-05-22 devnull if(sufwid && __fmtcpy(fmt, suf, sufwid, sufwid) < 0)
662 f8955f18 2006-05-22 devnull return -1;
663 f8955f18 2006-05-22 devnull if(pad && (fl & FmtLeft) && __fmtpad(fmt, pad) < 0)
664 f8955f18 2006-05-22 devnull return -1;
666 f8955f18 2006-05-22 devnull return 0;