1 /* 2 * dolfptoa - do the grunge work of converting an l_fp number to decimal 3 */ 4 #include <stdio.h> 5 6 #include "ntp_fp.h" 7 #include "lib_strbuf.h" 8 #include "ntp_string.h" 9 #include "ntp_stdlib.h" 10 11 char * 12 dolfptoa( 13 u_long fpi, 14 u_long fpv, 15 int neg, 16 short ndec, 17 int msec 18 ) 19 { 20 register u_char *cp, *cpend; 21 register u_long lwork; 22 register int dec; 23 u_char cbuf[24]; 24 u_char *cpdec; 25 char *buf; 26 char *bp; 27 28 /* 29 * Get a string buffer before starting 30 */ 31 LIB_GETBUF(buf); 32 33 /* 34 * Zero the character buffer 35 */ 36 memset((char *) cbuf, 0, sizeof(cbuf)); 37 38 /* 39 * Work on the integral part. This is biased by what I know 40 * compiles fairly well for a 68000. 41 */ 42 cp = cpend = &cbuf[10]; 43 lwork = fpi; 44 if (lwork & 0xffff0000) { 45 register u_long lten = 10; 46 register u_long ltmp; 47 48 do { 49 ltmp = lwork; 50 lwork /= lten; 51 ltmp -= (lwork << 3) + (lwork << 1); 52 *--cp = (u_char)ltmp; 53 } while (lwork & 0xffff0000); 54 } 55 if (lwork != 0) { 56 register u_short sten = 10; 57 register u_short stmp; 58 register u_short swork = (u_short)lwork; 59 60 do { 61 stmp = swork; 62 swork = (u_short) (swork/sten); 63 stmp = (u_short)(stmp - ((swork<<3) + (swork<<1))); 64 *--cp = (u_char)stmp; 65 } while (swork != 0); 66 } 67 68 /* 69 * Done that, now deal with the problem of the fraction. First 70 * determine the number of decimal places. 71 */ 72 if (msec) { 73 dec = ndec + 3; 74 if (dec < 3) 75 dec = 3; 76 cpdec = &cbuf[13]; 77 } else { 78 dec = ndec; 79 if (dec < 0) 80 dec = 0; 81 cpdec = &cbuf[10]; 82 } 83 if (dec > 12) 84 dec = 12; 85 86 /* 87 * If there's a fraction to deal with, do so. 88 */ 89 if (fpv != 0) { 90 l_fp work; 91 92 work.l_ui = 0; 93 work.l_uf = fpv; 94 while (dec > 0) { 95 l_fp ftmp; 96 97 dec--; 98 /* 99 * The scheme here is to multiply the 100 * fraction (0.1234...) by ten. This moves 101 * a junk of BCD into the units part. 102 * record that and iterate. 103 */ 104 work.l_ui = 0; 105 L_LSHIFT(&work); 106 ftmp = work; 107 L_LSHIFT(&work); 108 L_LSHIFT(&work); 109 L_ADD(&work, &ftmp); 110 *cpend++ = (u_char)work.l_ui; 111 if (work.l_uf == 0) 112 break; 113 } 114 115 /* 116 * Rounding is rotten 117 */ 118 if (work.l_uf & 0x80000000) { 119 register u_char *tp = cpend; 120 121 *(--tp) += 1; 122 while (*tp >= 10) { 123 *tp = 0; 124 *(--tp) += 1; 125 }; 126 if (tp < cp) 127 cp = tp; 128 } 129 } 130 cpend += dec; 131 132 133 /* 134 * We've now got the fraction in cbuf[], with cp pointing at 135 * the first character, cpend pointing past the last, and 136 * cpdec pointing at the first character past the decimal. 137 * Remove leading zeros, then format the number into the 138 * buffer. 139 */ 140 while (cp < cpdec) { 141 if (*cp != 0) 142 break; 143 cp++; 144 } 145 if (cp == cpdec) 146 --cp; 147 148 bp = buf; 149 if (neg) 150 *bp++ = '-'; 151 while (cp < cpend) { 152 if (cp == cpdec) 153 *bp++ = '.'; 154 *bp++ = (char)(*cp++ + '0'); /* ascii dependent? */ 155 } 156 *bp = '\0'; 157 158 /* 159 * Done! 160 */ 161 return buf; 162 } 163