1*37da2899SCharles.Forsyth #include "lib9.h"
2*37da2899SCharles.Forsyth #include "mathi.h"
3*37da2899SCharles.Forsyth extern char *dtoa(double, int, int, int *, int *, char **);
4*37da2899SCharles.Forsyth extern void freedtoa(char*);
5*37da2899SCharles.Forsyth extern int _fmtcpy(Fmt*, void*, int, int);
6*37da2899SCharles.Forsyth
7*37da2899SCharles.Forsyth enum
8*37da2899SCharles.Forsyth {
9*37da2899SCharles.Forsyth NONE = -1000,
10*37da2899SCharles.Forsyth FDIGIT = 20,
11*37da2899SCharles.Forsyth FDEFLT = 6,
12*37da2899SCharles.Forsyth NSIGNIF = 17
13*37da2899SCharles.Forsyth };
14*37da2899SCharles.Forsyth
15*37da2899SCharles.Forsyth int
gfltconv(Fmt * f)16*37da2899SCharles.Forsyth gfltconv(Fmt *f)
17*37da2899SCharles.Forsyth {
18*37da2899SCharles.Forsyth int flags = f->flags;
19*37da2899SCharles.Forsyth int precision;
20*37da2899SCharles.Forsyth int fmt = f->r;
21*37da2899SCharles.Forsyth double d;
22*37da2899SCharles.Forsyth int echr, exponent, sign, ndig, nout, i;
23*37da2899SCharles.Forsyth char *digits, *edigits, ebuf[32], *eptr;
24*37da2899SCharles.Forsyth char out[64], *pout;
25*37da2899SCharles.Forsyth
26*37da2899SCharles.Forsyth d = va_arg(f->args, double);
27*37da2899SCharles.Forsyth echr = 'e';
28*37da2899SCharles.Forsyth precision = FDEFLT;
29*37da2899SCharles.Forsyth if(f->flags & FmtPrec)
30*37da2899SCharles.Forsyth precision = f->prec;
31*37da2899SCharles.Forsyth if(precision > FDIGIT)
32*37da2899SCharles.Forsyth precision = FDIGIT;
33*37da2899SCharles.Forsyth switch(fmt){
34*37da2899SCharles.Forsyth case 'f':
35*37da2899SCharles.Forsyth digits = dtoa(d, 3, precision, &exponent, &sign, &edigits);
36*37da2899SCharles.Forsyth break;
37*37da2899SCharles.Forsyth case 0x00c9: /* L'É' */
38*37da2899SCharles.Forsyth case 'E':
39*37da2899SCharles.Forsyth echr = 'E';
40*37da2899SCharles.Forsyth fmt = 'e';
41*37da2899SCharles.Forsyth /* fall through */
42*37da2899SCharles.Forsyth case 'e':
43*37da2899SCharles.Forsyth digits = dtoa(d, 2, 1+precision, &exponent, &sign, &edigits);
44*37da2899SCharles.Forsyth break;
45*37da2899SCharles.Forsyth case 'G':
46*37da2899SCharles.Forsyth echr = 'E';
47*37da2899SCharles.Forsyth /* fall through */
48*37da2899SCharles.Forsyth default:
49*37da2899SCharles.Forsyth case 'g':
50*37da2899SCharles.Forsyth if((flags&(FmtWidth|FmtPrec)) == 0){
51*37da2899SCharles.Forsyth g_fmt(out, d, echr);
52*37da2899SCharles.Forsyth f->flags &= FmtWidth|FmtLeft;
53*37da2899SCharles.Forsyth return _fmtcpy(f, out, strlen(out), strlen(out));
54*37da2899SCharles.Forsyth }
55*37da2899SCharles.Forsyth if (precision > 0)
56*37da2899SCharles.Forsyth digits = dtoa(d, 2, precision, &exponent, &sign, &edigits);
57*37da2899SCharles.Forsyth else {
58*37da2899SCharles.Forsyth digits = dtoa(d, 0, precision, &exponent, &sign, &edigits);
59*37da2899SCharles.Forsyth precision = edigits - digits;
60*37da2899SCharles.Forsyth if (exponent > precision && exponent <= precision + 4)
61*37da2899SCharles.Forsyth precision = exponent;
62*37da2899SCharles.Forsyth }
63*37da2899SCharles.Forsyth if(exponent >= -3 && exponent <= precision){
64*37da2899SCharles.Forsyth fmt = 'f';
65*37da2899SCharles.Forsyth precision -= exponent;
66*37da2899SCharles.Forsyth }else{
67*37da2899SCharles.Forsyth fmt = 'e';
68*37da2899SCharles.Forsyth --precision;
69*37da2899SCharles.Forsyth }
70*37da2899SCharles.Forsyth break;
71*37da2899SCharles.Forsyth }
72*37da2899SCharles.Forsyth if (exponent == 9999) {
73*37da2899SCharles.Forsyth /* Infinity or Nan */
74*37da2899SCharles.Forsyth precision = 0;
75*37da2899SCharles.Forsyth exponent = edigits - digits;
76*37da2899SCharles.Forsyth fmt = 'f';
77*37da2899SCharles.Forsyth }
78*37da2899SCharles.Forsyth ndig = edigits-digits;
79*37da2899SCharles.Forsyth if((f->r=='g' || f->r=='G') && !(flags&FmtSharp)){ /* knock off trailing zeros */
80*37da2899SCharles.Forsyth if(fmt == 'f'){
81*37da2899SCharles.Forsyth if(precision+exponent > ndig) {
82*37da2899SCharles.Forsyth precision = ndig - exponent;
83*37da2899SCharles.Forsyth if(precision < 0)
84*37da2899SCharles.Forsyth precision = 0;
85*37da2899SCharles.Forsyth }
86*37da2899SCharles.Forsyth }
87*37da2899SCharles.Forsyth else{
88*37da2899SCharles.Forsyth if(precision > ndig-1) precision = ndig-1;
89*37da2899SCharles.Forsyth }
90*37da2899SCharles.Forsyth }
91*37da2899SCharles.Forsyth eptr = ebuf;
92*37da2899SCharles.Forsyth if(fmt != 'f'){ /* exponent */
93*37da2899SCharles.Forsyth for(i=exponent<=0?1-exponent:exponent-1; i; i/=10)
94*37da2899SCharles.Forsyth *eptr++ = '0' + i%10;
95*37da2899SCharles.Forsyth while(eptr<ebuf+2) *eptr++ = '0';
96*37da2899SCharles.Forsyth }
97*37da2899SCharles.Forsyth pout = out;
98*37da2899SCharles.Forsyth if(sign) *pout++ = '-';
99*37da2899SCharles.Forsyth else if(flags&FmtSign) *pout++ = '+';
100*37da2899SCharles.Forsyth else if(flags&FmtSpace) *pout++ = ' ';
101*37da2899SCharles.Forsyth if(fmt == 'f'){
102*37da2899SCharles.Forsyth for(i=0; i<exponent; i++) *pout++ = i<ndig?digits[i]:'0';
103*37da2899SCharles.Forsyth if(i == 0) *pout++ = '0';
104*37da2899SCharles.Forsyth if(precision>0 || flags&FmtSharp) *pout++ = '.';
105*37da2899SCharles.Forsyth for(i=0; i!=precision; i++)
106*37da2899SCharles.Forsyth *pout++ = 0<=i+exponent && i+exponent<ndig?digits[i+exponent]:'0';
107*37da2899SCharles.Forsyth }
108*37da2899SCharles.Forsyth else{
109*37da2899SCharles.Forsyth *pout++ = digits[0];
110*37da2899SCharles.Forsyth if(precision>0 || flags&FmtSharp) *pout++ = '.';
111*37da2899SCharles.Forsyth for(i=0; i!=precision; i++) *pout++ = i<ndig-1?digits[i+1]:'0';
112*37da2899SCharles.Forsyth }
113*37da2899SCharles.Forsyth if(fmt != 'f'){
114*37da2899SCharles.Forsyth *pout++ = echr;
115*37da2899SCharles.Forsyth *pout++ = exponent<=0?'-':'+';
116*37da2899SCharles.Forsyth while(eptr>ebuf) *pout++ = *--eptr;
117*37da2899SCharles.Forsyth }
118*37da2899SCharles.Forsyth *pout = 0;
119*37da2899SCharles.Forsyth freedtoa(digits);
120*37da2899SCharles.Forsyth f->flags &= FmtWidth|FmtLeft;
121*37da2899SCharles.Forsyth nout = pout-out;
122*37da2899SCharles.Forsyth return _fmtcpy(f, out, nout, nout);
123*37da2899SCharles.Forsyth }
124