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 91c13e54 2004-02-29 devnull 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
30 91c13e54 2004-02-29 devnull 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
31 91c13e54 2004-02-29 devnull 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29,
32 91c13e54 2004-02-29 devnull 1e30, 1e31, 1e32, 1e33, 1e34, 1e35, 1e36, 1e37, 1e38, 1e39,
33 91c13e54 2004-02-29 devnull 1e40, 1e41, 1e42, 1e43, 1e44, 1e45, 1e46, 1e47, 1e48, 1e49,
34 91c13e54 2004-02-29 devnull 1e50, 1e51, 1e52, 1e53, 1e54, 1e55, 1e56, 1e57, 1e58, 1e59,
35 91c13e54 2004-02-29 devnull 1e60, 1e61, 1e62, 1e63, 1e64, 1e65, 1e66, 1e67, 1e68, 1e69,
36 91c13e54 2004-02-29 devnull 1e70, 1e71, 1e72, 1e73, 1e74, 1e75, 1e76, 1e77, 1e78, 1e79,
37 91c13e54 2004-02-29 devnull 1e80, 1e81, 1e82, 1e83, 1e84, 1e85, 1e86, 1e87, 1e88, 1e89,
38 91c13e54 2004-02-29 devnull 1e90, 1e91, 1e92, 1e93, 1e94, 1e95, 1e96, 1e97, 1e98, 1e99,
39 91c13e54 2004-02-29 devnull 1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109,
40 91c13e54 2004-02-29 devnull 1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119,
41 91c13e54 2004-02-29 devnull 1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129,
42 91c13e54 2004-02-29 devnull 1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139,
43 91c13e54 2004-02-29 devnull 1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149,
44 91c13e54 2004-02-29 devnull 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){
57 f8955f18 2006-05-22 devnull if(n < DBL_MIN_10_EXP)
58 91c13e54 2004-02-29 devnull return 0.;
61 f8955f18 2006-05-22 devnull }else if(n > DBL_MAX_10_EXP)
62 91c13e54 2004-02-29 devnull return HUGE_VAL;
64 f8955f18 2006-05-22 devnull if(n < npows10)
65 91c13e54 2004-02-29 devnull d = pows10[n];
67 f8955f18 2006-05-22 devnull d = pows10[npows10-1];
69 f8955f18 2006-05-22 devnull n -= npows10 - 1;
70 f8955f18 2006-05-22 devnull if(n < npows10){
71 91c13e54 2004-02-29 devnull d *= pows10[n];
74 f8955f18 2006-05-22 devnull d *= pows10[npows10 - 1];
78 91c13e54 2004-02-29 devnull return 1./d;
79 91c13e54 2004-02-29 devnull return d;
83 f8955f18 2006-05-22 devnull * add 1 to the decimal integer string a of length n.
84 f8955f18 2006-05-22 devnull * if 99999 overflows into 10000, return 1 to tell caller
85 f8955f18 2006-05-22 devnull * to move the virtual decimal point.
87 91c13e54 2004-02-29 devnull static int
88 f8955f18 2006-05-22 devnull xadd1(char *a, int n)
93 f8955f18 2006-05-22 devnull if(n < 0 || n > NSIGNIF)
94 91c13e54 2004-02-29 devnull return 0;
95 f8955f18 2006-05-22 devnull for(b = a+n-1; b >= a; b--) {
96 f8955f18 2006-05-22 devnull c = *b + 1;
97 91c13e54 2004-02-29 devnull if(c <= '9') {
99 91c13e54 2004-02-29 devnull return 0;
101 91c13e54 2004-02-29 devnull *b = '0';
104 f8955f18 2006-05-22 devnull * need to overflow adding digit.
105 f8955f18 2006-05-22 devnull * shift number down and insert 1 at beginning.
106 f8955f18 2006-05-22 devnull * decimal is known to be 0s or we wouldn't
107 f8955f18 2006-05-22 devnull * have gotten this far. (e.g., 99999+1 => 00000)
109 f8955f18 2006-05-22 devnull a[0] = '1';
110 91c13e54 2004-02-29 devnull return 1;
114 f8955f18 2006-05-22 devnull * subtract 1 from the decimal integer string a.
115 f8955f18 2006-05-22 devnull * if 10000 underflows into 09999, make it 99999
116 f8955f18 2006-05-22 devnull * and return 1 to tell caller to move the virtual
117 f8955f18 2006-05-22 devnull * decimal point. this way, xsub1 is inverse of xadd1.
119 91c13e54 2004-02-29 devnull static int
120 f8955f18 2006-05-22 devnull xsub1(char *a, int n)
122 91c13e54 2004-02-29 devnull char *b;
125 f8955f18 2006-05-22 devnull if(n < 0 || n > NSIGNIF)
126 f8955f18 2006-05-22 devnull return 0;
127 f8955f18 2006-05-22 devnull for(b = a+n-1; b >= a; b--) {
128 f8955f18 2006-05-22 devnull c = *b - 1;
129 91c13e54 2004-02-29 devnull if(c >= '0') {
130 f8955f18 2006-05-22 devnull if(c == '0' && b == a) {
132 f8955f18 2006-05-22 devnull * just zeroed the top digit; shift everyone up.
133 f8955f18 2006-05-22 devnull * decimal is known to be 9s or we wouldn't
134 f8955f18 2006-05-22 devnull * have gotten this far. (e.g., 10000-1 => 09999)
136 f8955f18 2006-05-22 devnull *b = '9';
137 f8955f18 2006-05-22 devnull return 1;
140 91c13e54 2004-02-29 devnull return 0;
142 91c13e54 2004-02-29 devnull *b = '9';
145 f8955f18 2006-05-22 devnull * can't get here. the number a is always normalized
146 f8955f18 2006-05-22 devnull * so that it has a nonzero first digit.
148 f8955f18 2006-05-22 devnull abort();
152 f8955f18 2006-05-22 devnull * format exponent like sprintf(p, "e%+02d", e)
154 91c13e54 2004-02-29 devnull static void
155 f8955f18 2006-05-22 devnull xfmtexp(char *p, int e, int ucase)
157 f8955f18 2006-05-22 devnull char se[9];
160 f8955f18 2006-05-22 devnull *p++ = ucase ? 'E' : 'e';
161 f8955f18 2006-05-22 devnull if(e < 0) {
162 f8955f18 2006-05-22 devnull *p++ = '-';
165 f8955f18 2006-05-22 devnull *p++ = '+';
167 f8955f18 2006-05-22 devnull while(e) {
168 f8955f18 2006-05-22 devnull se[i++] = e % 10 + '0';
169 f8955f18 2006-05-22 devnull e /= 10;
171 f8955f18 2006-05-22 devnull while(i < 2)
172 f8955f18 2006-05-22 devnull se[i++] = '0';
173 f8955f18 2006-05-22 devnull while(i > 0)
174 f8955f18 2006-05-22 devnull *p++ = se[--i];
175 f8955f18 2006-05-22 devnull *p++ = '\0';
179 f8955f18 2006-05-22 devnull * compute decimal integer m, exp such that:
180 f8955f18 2006-05-22 devnull * f = m*10^exp
181 f8955f18 2006-05-22 devnull * m is as short as possible with losing exactness
182 f8955f18 2006-05-22 devnull * assumes special cases (NaN, +Inf, -Inf) have been handled.
184 f8955f18 2006-05-22 devnull static void
185 f8955f18 2006-05-22 devnull xdtoa(double f, char *s, int *exp, int *neg, int *ns)
187 f8955f18 2006-05-22 devnull int c, d, e2, e, ee, i, ndigit, oerrno;
188 f8955f18 2006-05-22 devnull char tmp[NSIGNIF+10];
189 f8955f18 2006-05-22 devnull double g;
191 f8955f18 2006-05-22 devnull oerrno = errno; /* in case strtod smashes errno */
194 f8955f18 2006-05-22 devnull * make f non-negative.
196 f8955f18 2006-05-22 devnull *neg = 0;
197 91c13e54 2004-02-29 devnull if(f < 0) {
199 f8955f18 2006-05-22 devnull *neg = 1;
203 f8955f18 2006-05-22 devnull * must handle zero specially.
205 f8955f18 2006-05-22 devnull if(f == 0){
206 f8955f18 2006-05-22 devnull *exp = 0;
207 f8955f18 2006-05-22 devnull s[0] = '0';
208 f8955f18 2006-05-22 devnull s[1] = '\0';
209 f8955f18 2006-05-22 devnull *ns = 1;
214 f8955f18 2006-05-22 devnull * find g,e such that f = g*10^e.
215 f8955f18 2006-05-22 devnull * guess 10-exponent using 2-exponent, then fine tune.
217 f8955f18 2006-05-22 devnull frexp(f, &e2);
218 f8955f18 2006-05-22 devnull e = (int)(e2 * .301029995664);
219 f8955f18 2006-05-22 devnull g = f * pow10(-e);
220 f8955f18 2006-05-22 devnull while(g < 1) {
222 f8955f18 2006-05-22 devnull g = f * pow10(-e);
224 f8955f18 2006-05-22 devnull while(g >= 10) {
226 f8955f18 2006-05-22 devnull g = f * pow10(-e);
230 f8955f18 2006-05-22 devnull * convert NSIGNIF digits as a first approximation.
232 f8955f18 2006-05-22 devnull for(i=0; i<NSIGNIF; i++) {
233 f8955f18 2006-05-22 devnull d = (int)g;
234 f8955f18 2006-05-22 devnull s[i] = d+'0';
235 f8955f18 2006-05-22 devnull g = (g-d) * 10;
237 f8955f18 2006-05-22 devnull s[i] = 0;
240 f8955f18 2006-05-22 devnull * adjust e because s is 314159... not 3.14159...
242 f8955f18 2006-05-22 devnull e -= NSIGNIF-1;
243 f8955f18 2006-05-22 devnull xfmtexp(s+NSIGNIF, e, 0);
246 f8955f18 2006-05-22 devnull * adjust conversion until strtod(s) == f exactly.
248 f8955f18 2006-05-22 devnull for(i=0; i<10; i++) {
249 f8955f18 2006-05-22 devnull g = strtod(s, nil);
250 91c13e54 2004-02-29 devnull if(f > g) {
251 f8955f18 2006-05-22 devnull if(xadd1(s, NSIGNIF)) {
252 f8955f18 2006-05-22 devnull /* gained a digit */
254 f8955f18 2006-05-22 devnull xfmtexp(s+NSIGNIF, e, 0);
256 91c13e54 2004-02-29 devnull continue;
258 91c13e54 2004-02-29 devnull if(f < g) {
259 f8955f18 2006-05-22 devnull if(xsub1(s, NSIGNIF)) {
260 f8955f18 2006-05-22 devnull /* lost a digit */
262 f8955f18 2006-05-22 devnull xfmtexp(s+NSIGNIF, e, 0);
264 91c13e54 2004-02-29 devnull continue;
270 f8955f18 2006-05-22 devnull * play with the decimal to try to simplify.
274 f8955f18 2006-05-22 devnull * bump last few digits up to 9 if we can
276 f8955f18 2006-05-22 devnull for(i=NSIGNIF-1; i>=NSIGNIF-3; i--) {
277 f8955f18 2006-05-22 devnull c = s[i];
278 f8955f18 2006-05-22 devnull if(c != '9') {
279 f8955f18 2006-05-22 devnull s[i] = '9';
280 f8955f18 2006-05-22 devnull g = strtod(s, nil);
281 f8955f18 2006-05-22 devnull if(g != f) {
282 f8955f18 2006-05-22 devnull s[i] = c;
289 f8955f18 2006-05-22 devnull * add 1 in hopes of turning 9s to 0s
291 f8955f18 2006-05-22 devnull if(s[NSIGNIF-1] == '9') {
292 f8955f18 2006-05-22 devnull strcpy(tmp, s);
294 f8955f18 2006-05-22 devnull if(xadd1(tmp, NSIGNIF)) {
296 f8955f18 2006-05-22 devnull xfmtexp(tmp+NSIGNIF, ee, 0);
298 f8955f18 2006-05-22 devnull g = strtod(tmp, nil);
299 f8955f18 2006-05-22 devnull if(g == f) {
300 f8955f18 2006-05-22 devnull strcpy(s, tmp);
306 f8955f18 2006-05-22 devnull * bump last few digits down to 0 as we can.
308 f8955f18 2006-05-22 devnull for(i=NSIGNIF-1; i>=NSIGNIF-3; i--) {
309 f8955f18 2006-05-22 devnull c = s[i];
310 f8955f18 2006-05-22 devnull if(c != '0') {
311 f8955f18 2006-05-22 devnull s[i] = '0';
312 f8955f18 2006-05-22 devnull g = strtod(s, nil);
313 f8955f18 2006-05-22 devnull if(g != f) {
314 f8955f18 2006-05-22 devnull s[i] = c;
321 f8955f18 2006-05-22 devnull * remove trailing zeros.
323 f8955f18 2006-05-22 devnull ndigit = NSIGNIF;
324 f8955f18 2006-05-22 devnull while(ndigit > 1 && s[ndigit-1] == '0'){
326 f8955f18 2006-05-22 devnull --ndigit;
328 f8955f18 2006-05-22 devnull s[ndigit] = 0;
329 f8955f18 2006-05-22 devnull *exp = e;
330 f8955f18 2006-05-22 devnull *ns = ndigit;
331 f8955f18 2006-05-22 devnull errno = oerrno;
334 f8955f18 2006-05-22 devnull #ifdef PLAN9PORT
335 f8955f18 2006-05-22 devnull static char *special[] = { "NaN", "NaN", "+Inf", "+Inf", "-Inf", "-Inf" };
337 f8955f18 2006-05-22 devnull static char *special[] = { "nan", "NAN", "inf", "INF", "-inf", "-INF" };
341 f8955f18 2006-05-22 devnull __efgfmt(Fmt *fmt)
343 f8955f18 2006-05-22 devnull char buf[NSIGNIF+10], *dot, *digits, *p, *s, suf[10], *t;
344 f8955f18 2006-05-22 devnull double f;
345 f8955f18 2006-05-22 devnull int c, chr, dotwid, e, exp, fl, ndigits, neg, newndigits;
346 f8955f18 2006-05-22 devnull int pad, point, prec, realchr, sign, sufwid, ucase, wid, z1, z2;
347 f8955f18 2006-05-22 devnull Rune r, *rs, *rt;
349 f8955f18 2006-05-22 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;