Initial import from FreeBSD RELENG_4:
[dragonfly.git] / contrib / ntp / libntp / dofptoa.c
1 /*
2  * dofptoa - do the grunge work to convert an fp number to ascii
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 dofptoa(
13         u_fp fpv,
14         int neg,
15         int ndec,
16         int msec
17         )
18 {
19         register u_char *cp, *cpend;
20         register u_long val;
21         register short dec;
22         u_char cbuf[12];
23         u_char *cpdec;
24         char *buf;
25         char *bp;
26
27         /*
28          * Get a string buffer before starting
29          */
30         LIB_GETBUF(buf);
31
32         /*
33          * Zero out the buffer
34          */
35         memset((char *)cbuf, 0, sizeof cbuf);
36
37         /*
38          * Set the pointers to point at the first
39          * decimal place.  Get a local copy of the value.
40          */
41         cp = cpend = &cbuf[5];
42         val = fpv;
43
44         /*
45          * If we have to, decode the integral part
46          */
47         if (!(val & 0xffff0000))
48             cp--;
49         else {
50                 register u_short sv = (u_short)(val >> 16);
51                 register u_short tmp;
52                 register u_short ten = 10;
53
54                 do {
55                         tmp = sv;
56                         sv /= ten;
57                         *(--cp) = tmp - ((sv<<3) + (sv<<1));
58                 } while (sv != 0);
59         }
60
61         /*
62          * Figure out how much of the fraction to do
63          */
64         if (msec) {
65                 dec = ndec + 3;
66                 if (dec < 3)
67                     dec = 3;
68                 cpdec = &cbuf[8];
69         } else {
70                 dec = ndec;
71                 cpdec = cpend;
72         }
73
74         if (dec > 6)
75             dec = 6;
76         
77         if (dec > 0) {
78                 do {
79                         val &= 0xffff;
80                         val = (val << 3) + (val << 1);
81                         *cpend++ = (u_char)(val >> 16);
82                 } while (--dec > 0);
83         }
84
85         if (val & 0x8000) {
86                 register u_char *tp;
87                 /*
88                  * Round it. Ick.
89                  */
90                 tp = cpend;
91                 *(--tp) += 1;
92                 while (*tp >= 10) {
93                         *tp = 0;
94                         *(--tp) += 1;
95                 }
96         }
97
98         /*
99          * Remove leading zeroes if necessary
100          */
101         while (cp < (cpdec -1) && *cp == 0)
102             cp++;
103         
104         /*
105          * Copy it into the buffer, asciizing as we go.
106          */
107         bp = buf;
108         if (neg)
109             *bp++ = '-';
110         
111         while (cp < cpend) {
112                 if (cp == cpdec)
113                     *bp++ = '.';
114                 *bp++ = (char)(*cp++ + '0');
115         }
116         *bp = '\0';
117         return buf;
118 }