xref: /freebsd/contrib/ntp/libntp/dofptoa.c (revision 1e413cf93298b5b97441a21d9a50fdcd0ee9945e)
1 /*
2  * dofptoa - do the grunge work to convert an fp number to ascii
3  */
4 #include <stdio.h>
5 
6 #include "ntp_fp.h"
7 #include "lib_strbuf.h"
8 #include "ntp_string.h"
9 #include "ntp_stdlib.h"
10 
11 char *
12 dofptoa(
13 	u_fp fpv,
14 	int neg,
15 	short ndec,
16 	int msec
17 	)
18 {
19 	register u_char *cp, *cpend;
20 	register u_long val;
21 	register short dec;
22 	u_char cbuf[12];
23 	u_char *cpdec;
24 	char *buf;
25 	char *bp;
26 
27 	/*
28 	 * Get a string buffer before starting
29 	 */
30 	LIB_GETBUF(buf);
31 
32 	/*
33 	 * Zero out the buffer
34 	 */
35 	memset((char *)cbuf, 0, sizeof cbuf);
36 
37 	/*
38 	 * Set the pointers to point at the first
39 	 * decimal place.  Get a local copy of the value.
40 	 */
41 	cp = cpend = &cbuf[5];
42 	val = fpv;
43 
44 	/*
45 	 * If we have to, decode the integral part
46 	 */
47 	if (!(val & 0xffff0000))
48 	    cp--;
49 	else {
50 		register u_short sv = (u_short)(val >> 16);
51 		register u_short tmp;
52 		register u_short ten = 10;
53 
54 		do {
55 			tmp = sv;
56 			sv = (u_short) (sv/ten);
57 			*(--cp) = (u_char)(tmp - ((sv<<3) + (sv<<1)));
58 		} while (sv != 0);
59 	}
60 
61 	/*
62 	 * Figure out how much of the fraction to do
63 	 */
64 	if (msec) {
65 		dec = (short)(ndec + 3);
66 		if (dec < 3)
67 		    dec = 3;
68 		cpdec = &cbuf[8];
69 	} else {
70 		dec = ndec;
71 		cpdec = cpend;
72 	}
73 
74 	if (dec > 6)
75 	    dec = 6;
76 
77 	if (dec > 0) {
78 		do {
79 			val &= 0xffff;
80 			val = (val << 3) + (val << 1);
81 			*cpend++ = (u_char)(val >> 16);
82 		} while (--dec > 0);
83 	}
84 
85 	if (val & 0x8000) {
86 		register u_char *tp;
87 		/*
88 		 * Round it. Ick.
89 		 */
90 		tp = cpend;
91 		*(--tp) += 1;
92 		while (*tp >= 10) {
93 			*tp = 0;
94 			*(--tp) += 1;
95 		}
96 	}
97 
98 	/*
99 	 * Remove leading zeroes if necessary
100 	 */
101 	while (cp < (cpdec -1) && *cp == 0)
102 	    cp++;
103 
104 	/*
105 	 * Copy it into the buffer, asciizing as we go.
106 	 */
107 	bp = buf;
108 	if (neg)
109 	    *bp++ = '-';
110 
111 	while (cp < cpend) {
112 		if (cp == cpdec)
113 		    *bp++ = '.';
114 		*bp++ = (char)(*cp++ + '0');
115 	}
116 	*bp = '\0';
117 	return buf;
118 }
119