xref: /freebsd/contrib/ntp/libntp/dofptoa.c (revision 2d4e511ca269f1908d27f4e5779c53475527391d)
1c0b746e5SOllivier Robert /*
2c0b746e5SOllivier Robert  * dofptoa - do the grunge work to convert an fp number to ascii
3c0b746e5SOllivier Robert  */
42b15cb3dSCy Schubert #include <config.h>
5c0b746e5SOllivier Robert #include <stdio.h>
6c0b746e5SOllivier Robert 
7c0b746e5SOllivier Robert #include "ntp_fp.h"
8c0b746e5SOllivier Robert #include "lib_strbuf.h"
9c0b746e5SOllivier Robert #include "ntp_string.h"
10c0b746e5SOllivier Robert #include "ntp_stdlib.h"
11c0b746e5SOllivier Robert 
12c0b746e5SOllivier Robert char *
13c0b746e5SOllivier Robert dofptoa(
14c0b746e5SOllivier Robert 	u_fp fpv,
15*2d4e511cSCy Schubert 	char sign,
169c2daa00SOllivier Robert 	short ndec,
17c0b746e5SOllivier Robert 	int msec
18c0b746e5SOllivier Robert 	)
19c0b746e5SOllivier Robert {
20c0b746e5SOllivier Robert 	register u_char *cp, *cpend;
21c0b746e5SOllivier Robert 	register u_long val;
22c0b746e5SOllivier Robert 	register short dec;
23c0b746e5SOllivier Robert 	u_char cbuf[12];
24c0b746e5SOllivier Robert 	u_char *cpdec;
25c0b746e5SOllivier Robert 	char *buf;
26c0b746e5SOllivier Robert 	char *bp;
27c0b746e5SOllivier Robert 
28c0b746e5SOllivier Robert 	/*
29c0b746e5SOllivier Robert 	 * Get a string buffer before starting
30c0b746e5SOllivier Robert 	 */
31c0b746e5SOllivier Robert 	LIB_GETBUF(buf);
32c0b746e5SOllivier Robert 
33c0b746e5SOllivier Robert 	/*
34c0b746e5SOllivier Robert 	 * Zero out the buffer
35c0b746e5SOllivier Robert 	 */
362b15cb3dSCy Schubert 	ZERO(cbuf);
37c0b746e5SOllivier Robert 
38c0b746e5SOllivier Robert 	/*
39c0b746e5SOllivier Robert 	 * Set the pointers to point at the first
40c0b746e5SOllivier Robert 	 * decimal place.  Get a local copy of the value.
41c0b746e5SOllivier Robert 	 */
42c0b746e5SOllivier Robert 	cp = cpend = &cbuf[5];
43c0b746e5SOllivier Robert 	val = fpv;
44c0b746e5SOllivier Robert 
45c0b746e5SOllivier Robert 	/*
46c0b746e5SOllivier Robert 	 * If we have to, decode the integral part
47c0b746e5SOllivier Robert 	 */
48c0b746e5SOllivier Robert 	if (!(val & 0xffff0000))
49c0b746e5SOllivier Robert 	    cp--;
50c0b746e5SOllivier Robert 	else {
51c0b746e5SOllivier Robert 		register u_short sv = (u_short)(val >> 16);
52c0b746e5SOllivier Robert 		register u_short tmp;
53c0b746e5SOllivier Robert 		register u_short ten = 10;
54c0b746e5SOllivier Robert 
55c0b746e5SOllivier Robert 		do {
56c0b746e5SOllivier Robert 			tmp = sv;
579c2daa00SOllivier Robert 			sv = (u_short) (sv/ten);
589c2daa00SOllivier Robert 			*(--cp) = (u_char)(tmp - ((sv<<3) + (sv<<1)));
59c0b746e5SOllivier Robert 		} while (sv != 0);
60c0b746e5SOllivier Robert 	}
61c0b746e5SOllivier Robert 
62c0b746e5SOllivier Robert 	/*
63c0b746e5SOllivier Robert 	 * Figure out how much of the fraction to do
64c0b746e5SOllivier Robert 	 */
65c0b746e5SOllivier Robert 	if (msec) {
669c2daa00SOllivier Robert 		dec = (short)(ndec + 3);
67c0b746e5SOllivier Robert 		if (dec < 3)
68c0b746e5SOllivier Robert 		    dec = 3;
69c0b746e5SOllivier Robert 		cpdec = &cbuf[8];
70c0b746e5SOllivier Robert 	} else {
71c0b746e5SOllivier Robert 		dec = ndec;
72c0b746e5SOllivier Robert 		cpdec = cpend;
73c0b746e5SOllivier Robert 	}
74c0b746e5SOllivier Robert 
75c0b746e5SOllivier Robert 	if (dec > 6)
76c0b746e5SOllivier Robert 	    dec = 6;
77c0b746e5SOllivier Robert 
78c0b746e5SOllivier Robert 	if (dec > 0) {
79c0b746e5SOllivier Robert 		do {
80c0b746e5SOllivier Robert 			val &= 0xffff;
81c0b746e5SOllivier Robert 			val = (val << 3) + (val << 1);
82c0b746e5SOllivier Robert 			*cpend++ = (u_char)(val >> 16);
83c0b746e5SOllivier Robert 		} while (--dec > 0);
84c0b746e5SOllivier Robert 	}
85c0b746e5SOllivier Robert 
86c0b746e5SOllivier Robert 	if (val & 0x8000) {
87c0b746e5SOllivier Robert 		register u_char *tp;
88c0b746e5SOllivier Robert 		/*
89c0b746e5SOllivier Robert 		 * Round it. Ick.
90c0b746e5SOllivier Robert 		 */
91c0b746e5SOllivier Robert 		tp = cpend;
92c0b746e5SOllivier Robert 		*(--tp) += 1;
93c0b746e5SOllivier Robert 		while (*tp >= 10) {
94c0b746e5SOllivier Robert 			*tp = 0;
95c0b746e5SOllivier Robert 			*(--tp) += 1;
96c0b746e5SOllivier Robert 		}
97c0b746e5SOllivier Robert 	}
98c0b746e5SOllivier Robert 
99c0b746e5SOllivier Robert 	/*
100c0b746e5SOllivier Robert 	 * Remove leading zeroes if necessary
101c0b746e5SOllivier Robert 	 */
102c0b746e5SOllivier Robert 	while (cp < (cpdec -1) && *cp == 0)
103c0b746e5SOllivier Robert 	    cp++;
104c0b746e5SOllivier Robert 
105c0b746e5SOllivier Robert 	/*
106c0b746e5SOllivier Robert 	 * Copy it into the buffer, asciizing as we go.
107c0b746e5SOllivier Robert 	 */
108c0b746e5SOllivier Robert 	bp = buf;
109*2d4e511cSCy Schubert 	if (sign)
110*2d4e511cSCy Schubert 	    *bp++ = sign;
111c0b746e5SOllivier Robert 
112c0b746e5SOllivier Robert 	while (cp < cpend) {
113c0b746e5SOllivier Robert 		if (cp == cpdec)
114c0b746e5SOllivier Robert 		    *bp++ = '.';
115c0b746e5SOllivier Robert 		*bp++ = (char)(*cp++ + '0');
116c0b746e5SOllivier Robert 	}
117c0b746e5SOllivier Robert 	*bp = '\0';
118c0b746e5SOllivier Robert 	return buf;
119c0b746e5SOllivier Robert }
1202b15cb3dSCy Schubert 
1212b15cb3dSCy Schubert 
1222b15cb3dSCy Schubert char *
1232b15cb3dSCy Schubert fptoa(
1242b15cb3dSCy Schubert 	s_fp	fpv,
1252b15cb3dSCy Schubert 	short	ndec
1262b15cb3dSCy Schubert 	)
1272b15cb3dSCy Schubert {
1282b15cb3dSCy Schubert 	u_fp	plusfp;
1292b15cb3dSCy Schubert 	int	neg;
1302b15cb3dSCy Schubert 
1312b15cb3dSCy Schubert 	neg = (fpv < 0);
1322b15cb3dSCy Schubert 	if (neg) {
1332b15cb3dSCy Schubert 		plusfp = (u_fp)(-fpv);
1342b15cb3dSCy Schubert 	} else {
1352b15cb3dSCy Schubert 		plusfp = (u_fp)fpv;
1362b15cb3dSCy Schubert 	}
1372b15cb3dSCy Schubert 
138*2d4e511cSCy Schubert 	return dofptoa(plusfp, (neg?'-':0), ndec, FALSE);
1392b15cb3dSCy Schubert }
1402b15cb3dSCy Schubert 
1412b15cb3dSCy Schubert 
1422b15cb3dSCy Schubert char *
1432b15cb3dSCy Schubert fptoms(
1442b15cb3dSCy Schubert 	s_fp	fpv,
1452b15cb3dSCy Schubert 	short	ndec
1462b15cb3dSCy Schubert 	)
1472b15cb3dSCy Schubert {
1482b15cb3dSCy Schubert 	u_fp	plusfp;
1492b15cb3dSCy Schubert 	int	neg;
1502b15cb3dSCy Schubert 
1512b15cb3dSCy Schubert 	neg = (fpv < 0);
1522b15cb3dSCy Schubert 	if (neg) {
1532b15cb3dSCy Schubert 		plusfp = (u_fp)(-fpv);
1542b15cb3dSCy Schubert 	} else {
1552b15cb3dSCy Schubert 		plusfp = (u_fp)fpv;
1562b15cb3dSCy Schubert 	}
1572b15cb3dSCy Schubert 
158*2d4e511cSCy Schubert 	return dofptoa(plusfp, (neg?'-':0), ndec, TRUE);
1592b15cb3dSCy Schubert }
160