1 /*        $NetBSD: dofptoa.c,v 1.6 2024/08/18 20:47:13 christos Exp $ */
2 
3 /*
4  * dofptoa - do the grunge work to convert an fp number to ascii
5  */
6 #include <config.h>
7 #include <stdio.h>
8 
9 #include "ntp_fp.h"
10 #include "ntp_stdlib.h"
11 
12 char *
dofptoa(u_fp fpv,char sign,short ndec,int msec)13 dofptoa(
14           u_fp fpv,
15           char sign,
16           short ndec,
17           int msec
18           )
19 {
20           register u_char *cp, *cpend;
21           register u_long val;
22           register short dec;
23           u_char cbuf[12];
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 out the buffer
35            */
36           ZERO(cbuf);
37 
38           /*
39            * Set the pointers to point at the first
40            * decimal place.  Get a local copy of the value.
41            */
42           cp = cpend = &cbuf[5];
43           val = fpv;
44 
45           /*
46            * If we have to, decode the integral part
47            */
48           if (!(val & 0xffff0000))
49               cp--;
50           else {
51                     register u_short sv = (u_short)(val >> 16);
52                     register u_short tmp;
53                     register u_short ten = 10;
54 
55                     do {
56                               tmp = sv;
57                               sv = (u_short) (sv/ten);
58                               *(--cp) = (u_char)(tmp - ((sv<<3) + (sv<<1)));
59                     } while (sv != 0);
60           }
61 
62           /*
63            * Figure out how much of the fraction to do
64            */
65           if (msec) {
66                     dec = (short)(ndec + 3);
67                     if (dec < 3)
68                         dec = 3;
69                     cpdec = &cbuf[8];
70           } else {
71                     dec = ndec;
72                     cpdec = cpend;
73           }
74 
75           if (dec > 6)
76               dec = 6;
77 
78           if (dec > 0) {
79                     do {
80                               val &= 0xffff;
81                               val = (val << 3) + (val << 1);
82                               *cpend++ = (u_char)(val >> 16);
83                     } while (--dec > 0);
84           }
85 
86           if (val & 0x8000) {
87                     register u_char *tp;
88                     /*
89                      * Round it. Ick.
90                      */
91                     tp = cpend;
92                     *(--tp) += 1;
93                     while (*tp >= 10) {
94                               *tp = 0;
95                               *(--tp) += 1;
96                     }
97           }
98 
99           /*
100            * Remove leading zeroes if necessary
101            */
102           while (cp < (cpdec -1) && *cp == 0)
103               cp++;
104 
105           /*
106            * Copy it into the buffer, asciizing as we go.
107            */
108           bp = buf;
109           if (sign)
110               *bp++ = sign;
111 
112           while (cp < cpend) {
113                     if (cp == cpdec)
114                         *bp++ = '.';
115                     *bp++ = (char)(*cp++ + '0');
116           }
117           *bp = '\0';
118           return buf;
119 }
120 
121 
122 char *
fptoa(s_fp fpv,short ndec)123 fptoa(
124           s_fp      fpv,
125           short     ndec
126           )
127 {
128           u_fp      plusfp;
129           int       neg;
130 
131           neg = (fpv < 0);
132           if (neg) {
133                     plusfp = (u_fp)(-fpv);
134           } else {
135                     plusfp = (u_fp)fpv;
136           }
137 
138           return dofptoa(plusfp, (neg?'-':0), ndec, FALSE);
139 }
140 
141 
142 char *
fptoms(s_fp fpv,short ndec)143 fptoms(
144           s_fp      fpv,
145           short     ndec
146           )
147 {
148           u_fp      plusfp;
149           int       neg;
150 
151           neg = (fpv < 0);
152           if (neg) {
153                     plusfp = (u_fp)(-fpv);
154           } else {
155                     plusfp = (u_fp)fpv;
156           }
157 
158           return dofptoa(plusfp, (neg?'-':0), ndec, TRUE);
159 }
160