xref: /freebsd/contrib/ntp/libntp/dofptoa.c (revision 61e21613)
1 /*
2  * dofptoa - do the grunge work to convert an fp number to ascii
3  */
4 #include <config.h>
5 #include <stdio.h>
6 
7 #include "ntp_fp.h"
8 #include "lib_strbuf.h"
9 #include "ntp_string.h"
10 #include "ntp_stdlib.h"
11 
12 char *
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 *
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 *
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