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