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