1 /* 2 * dolfptoa - do the grunge work of converting an l_fp number to decimal 3 */ 4 #include <config.h> 5 #include <stdio.h> 6 7 #include "ntp_fp.h" 8 #include "ntp_stdlib.h" 9 10 char * 11 dolfptoa( 12 u_int32 fpi, 13 u_int32 fpv, 14 char sign, 15 short ndec, 16 int msec 17 ) 18 { 19 u_char *cp, *cpend, *cpdec; 20 int dec; 21 u_char cbuf[24]; 22 char *buf, *bp; 23 24 /* 25 * Get a string buffer before starting 26 */ 27 LIB_GETBUF(buf); 28 29 /* 30 * Zero the character buffer 31 */ 32 ZERO(cbuf); 33 34 /* 35 * Work on the integral part. This should work reasonable on 36 * all machines with 32 bit arithmetic. Please note that 32 bits 37 * can *always* be represented with at most 10 decimal digits, 38 * including a possible rounding from the fractional part. 39 */ 40 cp = cpend = cpdec = &cbuf[10]; 41 for (dec = (int)(cp - cbuf); dec > 0 && fpi != 0; dec--) { 42 /* can add another digit */ 43 u_int32 digit; 44 45 digit = fpi; 46 fpi /= 10U; 47 digit -= (fpi << 3) + (fpi << 1); /* i*10 */ 48 *--cp = (u_char)digit; 49 } 50 51 /* 52 * Done that, now deal with the problem of the fraction. First 53 * determine the number of decimal places. 54 */ 55 dec = ndec; 56 if (dec < 0) 57 dec = 0; 58 if (msec) { 59 dec += 3; 60 cpdec += 3; 61 } 62 if ((size_t)dec > sizeof(cbuf) - (cpend - cbuf)) 63 dec = (int)(sizeof(cbuf) - (cpend - cbuf)); 64 65 /* 66 * If there's a fraction to deal with, do so. 67 */ 68 for (/*NOP*/; dec > 0 && fpv != 0; dec--) { 69 u_int32 digit, tmph, tmpl; 70 71 /* 72 * The scheme here is to multiply the fraction 73 * (0.1234...) by ten. This moves a junk of BCD into 74 * the units part. record that and iterate. 75 * multiply by shift/add in two dwords. 76 */ 77 digit = 0; 78 M_LSHIFT(digit, fpv); 79 tmph = digit; 80 tmpl = fpv; 81 M_LSHIFT(digit, fpv); 82 M_LSHIFT(digit, fpv); 83 M_ADD(digit, fpv, tmph, tmpl); 84 *cpend++ = (u_char)digit; 85 } 86 87 /* decide whether to round or simply extend by zeros */ 88 if (dec > 0) { 89 /* only '0' digits left -- just reposition end */ 90 cpend += dec; 91 } else { 92 /* some bits remain in 'fpv'; do round */ 93 u_char *tp = cpend; 94 int carry = ((fpv & 0x80000000) != 0); 95 96 for (dec = (int)(tp - cbuf); carry && dec > 0; dec--) { 97 *--tp += 1; 98 if (*tp == 10) 99 *tp = 0; 100 else 101 carry = FALSE; 102 } 103 104 if (tp < cp) /* rounding from 999 to 1000 or similiar? */ 105 cp = tp; 106 } 107 108 /* 109 * We've now got the fraction in cbuf[], with cp pointing at 110 * the first character, cpend pointing past the last, and 111 * cpdec pointing at the first character past the decimal. 112 * Remove leading zeros, then format the number into the 113 * buffer. 114 */ 115 while (cp < cpdec && *cp == 0) 116 cp++; 117 if (cp >= cpdec) 118 cp = cpdec - 1; 119 120 bp = buf; 121 if (sign) 122 *bp++ = sign; 123 while (cp < cpend) { 124 if (cp == cpdec) 125 *bp++ = '.'; 126 *bp++ = (char)(*cp++) + '0'; 127 } 128 *bp = '\0'; 129 130 /* 131 * Done! 132 */ 133 return buf; 134 } 135 136 137 char * 138 mfptoa( 139 u_int32 fpi, 140 u_int32 fpf, 141 short ndec 142 ) 143 { 144 int isneg; 145 146 isneg = M_ISNEG(fpi); 147 if (isneg) { 148 M_NEG(fpi, fpf); 149 } 150 151 return dolfptoa(fpi, fpf, (isneg?'-':'+'), ndec, FALSE); 152 } 153 154 155 char * 156 mfptoms( 157 u_int32 fpi, 158 u_int32 fpf, 159 short ndec 160 ) 161 { 162 int isneg; 163 164 isneg = M_ISNEG(fpi); 165 if (isneg) { 166 M_NEG(fpi, fpf); 167 } 168 169 return dolfptoa(fpi, fpf, (isneg?'-':'+'), ndec, TRUE); 170 } 171 172 173