xref: /netbsd-src/external/bsd/ntp/dist/libntp/dofptoa.c (revision eabc0478de71e4e011a5b4e0392741e01d491794)
1*eabc0478Schristos /*	$NetBSD: dofptoa.c,v 1.6 2024/08/18 20:47:13 christos Exp $	*/
2abb0f93cSkardel 
3abb0f93cSkardel /*
4abb0f93cSkardel  * dofptoa - do the grunge work to convert an fp number to ascii
5abb0f93cSkardel  */
68585484eSchristos #include <config.h>
7abb0f93cSkardel #include <stdio.h>
8abb0f93cSkardel 
9abb0f93cSkardel #include "ntp_fp.h"
10abb0f93cSkardel #include "ntp_stdlib.h"
11abb0f93cSkardel 
12abb0f93cSkardel char *
13abb0f93cSkardel dofptoa(
14abb0f93cSkardel 	u_fp fpv,
15cdfa2a7eSchristos 	char sign,
16abb0f93cSkardel 	short ndec,
17abb0f93cSkardel 	int msec
18abb0f93cSkardel 	)
19abb0f93cSkardel {
20abb0f93cSkardel 	register u_char *cp, *cpend;
21abb0f93cSkardel 	register u_long val;
22abb0f93cSkardel 	register short dec;
23abb0f93cSkardel 	u_char cbuf[12];
24abb0f93cSkardel 	u_char *cpdec;
25abb0f93cSkardel 	char *buf;
26abb0f93cSkardel 	char *bp;
27abb0f93cSkardel 
28abb0f93cSkardel 	/*
29abb0f93cSkardel 	 * Get a string buffer before starting
30abb0f93cSkardel 	 */
31abb0f93cSkardel 	LIB_GETBUF(buf);
32abb0f93cSkardel 
33abb0f93cSkardel 	/*
34abb0f93cSkardel 	 * Zero out the buffer
35abb0f93cSkardel 	 */
368585484eSchristos 	ZERO(cbuf);
37abb0f93cSkardel 
38abb0f93cSkardel 	/*
39abb0f93cSkardel 	 * Set the pointers to point at the first
40abb0f93cSkardel 	 * decimal place.  Get a local copy of the value.
41abb0f93cSkardel 	 */
42abb0f93cSkardel 	cp = cpend = &cbuf[5];
43abb0f93cSkardel 	val = fpv;
44abb0f93cSkardel 
45abb0f93cSkardel 	/*
46abb0f93cSkardel 	 * If we have to, decode the integral part
47abb0f93cSkardel 	 */
48abb0f93cSkardel 	if (!(val & 0xffff0000))
49abb0f93cSkardel 	    cp--;
50abb0f93cSkardel 	else {
51abb0f93cSkardel 		register u_short sv = (u_short)(val >> 16);
52abb0f93cSkardel 		register u_short tmp;
53abb0f93cSkardel 		register u_short ten = 10;
54abb0f93cSkardel 
55abb0f93cSkardel 		do {
56abb0f93cSkardel 			tmp = sv;
57abb0f93cSkardel 			sv = (u_short) (sv/ten);
58abb0f93cSkardel 			*(--cp) = (u_char)(tmp - ((sv<<3) + (sv<<1)));
59abb0f93cSkardel 		} while (sv != 0);
60abb0f93cSkardel 	}
61abb0f93cSkardel 
62abb0f93cSkardel 	/*
63abb0f93cSkardel 	 * Figure out how much of the fraction to do
64abb0f93cSkardel 	 */
65abb0f93cSkardel 	if (msec) {
66abb0f93cSkardel 		dec = (short)(ndec + 3);
67abb0f93cSkardel 		if (dec < 3)
68abb0f93cSkardel 		    dec = 3;
69abb0f93cSkardel 		cpdec = &cbuf[8];
70abb0f93cSkardel 	} else {
71abb0f93cSkardel 		dec = ndec;
72abb0f93cSkardel 		cpdec = cpend;
73abb0f93cSkardel 	}
74abb0f93cSkardel 
75abb0f93cSkardel 	if (dec > 6)
76abb0f93cSkardel 	    dec = 6;
77abb0f93cSkardel 
78abb0f93cSkardel 	if (dec > 0) {
79abb0f93cSkardel 		do {
80abb0f93cSkardel 			val &= 0xffff;
81abb0f93cSkardel 			val = (val << 3) + (val << 1);
82abb0f93cSkardel 			*cpend++ = (u_char)(val >> 16);
83abb0f93cSkardel 		} while (--dec > 0);
84abb0f93cSkardel 	}
85abb0f93cSkardel 
86abb0f93cSkardel 	if (val & 0x8000) {
87abb0f93cSkardel 		register u_char *tp;
88abb0f93cSkardel 		/*
89abb0f93cSkardel 		 * Round it. Ick.
90abb0f93cSkardel 		 */
91abb0f93cSkardel 		tp = cpend;
92abb0f93cSkardel 		*(--tp) += 1;
93abb0f93cSkardel 		while (*tp >= 10) {
94abb0f93cSkardel 			*tp = 0;
95abb0f93cSkardel 			*(--tp) += 1;
96abb0f93cSkardel 		}
97abb0f93cSkardel 	}
98abb0f93cSkardel 
99abb0f93cSkardel 	/*
100abb0f93cSkardel 	 * Remove leading zeroes if necessary
101abb0f93cSkardel 	 */
102abb0f93cSkardel 	while (cp < (cpdec -1) && *cp == 0)
103abb0f93cSkardel 	    cp++;
104abb0f93cSkardel 
105abb0f93cSkardel 	/*
106abb0f93cSkardel 	 * Copy it into the buffer, asciizing as we go.
107abb0f93cSkardel 	 */
108abb0f93cSkardel 	bp = buf;
109cdfa2a7eSchristos 	if (sign)
110cdfa2a7eSchristos 	    *bp++ = sign;
111abb0f93cSkardel 
112abb0f93cSkardel 	while (cp < cpend) {
113abb0f93cSkardel 		if (cp == cpdec)
114abb0f93cSkardel 		    *bp++ = '.';
115abb0f93cSkardel 		*bp++ = (char)(*cp++ + '0');
116abb0f93cSkardel 	}
117abb0f93cSkardel 	*bp = '\0';
118abb0f93cSkardel 	return buf;
119abb0f93cSkardel }
1208585484eSchristos 
1218585484eSchristos 
1228585484eSchristos char *
1238585484eSchristos fptoa(
1248585484eSchristos 	s_fp	fpv,
1258585484eSchristos 	short	ndec
1268585484eSchristos 	)
1278585484eSchristos {
1288585484eSchristos 	u_fp	plusfp;
1298585484eSchristos 	int	neg;
1308585484eSchristos 
1318585484eSchristos 	neg = (fpv < 0);
1328585484eSchristos 	if (neg) {
1338585484eSchristos 		plusfp = (u_fp)(-fpv);
1348585484eSchristos 	} else {
1358585484eSchristos 		plusfp = (u_fp)fpv;
1368585484eSchristos 	}
1378585484eSchristos 
138cdfa2a7eSchristos 	return dofptoa(plusfp, (neg?'-':0), ndec, FALSE);
1398585484eSchristos }
1408585484eSchristos 
1418585484eSchristos 
1428585484eSchristos char *
1438585484eSchristos fptoms(
1448585484eSchristos 	s_fp	fpv,
1458585484eSchristos 	short	ndec
1468585484eSchristos 	)
1478585484eSchristos {
1488585484eSchristos 	u_fp	plusfp;
1498585484eSchristos 	int	neg;
1508585484eSchristos 
1518585484eSchristos 	neg = (fpv < 0);
1528585484eSchristos 	if (neg) {
1538585484eSchristos 		plusfp = (u_fp)(-fpv);
1548585484eSchristos 	} else {
1558585484eSchristos 		plusfp = (u_fp)fpv;
1568585484eSchristos 	}
1578585484eSchristos 
158cdfa2a7eSchristos 	return dofptoa(plusfp, (neg?'-':0), ndec, TRUE);
1598585484eSchristos }
160