xref: /freebsd/contrib/ntp/libntp/dofptoa.c (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 "ntp_stdlib.h"
9 
10 char *
11 dofptoa(
12 	u_fp fpv,
13 	char sign,
14 	short ndec,
15 	int msec
16 	)
17 {
18 	register u_char *cp, *cpend;
19 	register u_long val;
20 	register short dec;
21 	u_char cbuf[12];
22 	u_char *cpdec;
23 	char *buf;
24 	char *bp;
25 
26 	/*
27 	 * Get a string buffer before starting
28 	 */
29 	LIB_GETBUF(buf);
30 
31 	/*
32 	 * Zero out the buffer
33 	 */
34 	ZERO(cbuf);
35 
36 	/*
37 	 * Set the pointers to point at the first
38 	 * decimal place.  Get a local copy of the value.
39 	 */
40 	cp = cpend = &cbuf[5];
41 	val = fpv;
42 
43 	/*
44 	 * If we have to, decode the integral part
45 	 */
46 	if (!(val & 0xffff0000))
47 	    cp--;
48 	else {
49 		register u_short sv = (u_short)(val >> 16);
50 		register u_short tmp;
51 		register u_short ten = 10;
52 
53 		do {
54 			tmp = sv;
55 			sv = (u_short) (sv/ten);
56 			*(--cp) = (u_char)(tmp - ((sv<<3) + (sv<<1)));
57 		} while (sv != 0);
58 	}
59 
60 	/*
61 	 * Figure out how much of the fraction to do
62 	 */
63 	if (msec) {
64 		dec = (short)(ndec + 3);
65 		if (dec < 3)
66 		    dec = 3;
67 		cpdec = &cbuf[8];
68 	} else {
69 		dec = ndec;
70 		cpdec = cpend;
71 	}
72 
73 	if (dec > 6)
74 	    dec = 6;
75 
76 	if (dec > 0) {
77 		do {
78 			val &= 0xffff;
79 			val = (val << 3) + (val << 1);
80 			*cpend++ = (u_char)(val >> 16);
81 		} while (--dec > 0);
82 	}
83 
84 	if (val & 0x8000) {
85 		register u_char *tp;
86 		/*
87 		 * Round it. Ick.
88 		 */
89 		tp = cpend;
90 		*(--tp) += 1;
91 		while (*tp >= 10) {
92 			*tp = 0;
93 			*(--tp) += 1;
94 		}
95 	}
96 
97 	/*
98 	 * Remove leading zeroes if necessary
99 	 */
100 	while (cp < (cpdec -1) && *cp == 0)
101 	    cp++;
102 
103 	/*
104 	 * Copy it into the buffer, asciizing as we go.
105 	 */
106 	bp = buf;
107 	if (sign)
108 	    *bp++ = sign;
109 
110 	while (cp < cpend) {
111 		if (cp == cpdec)
112 		    *bp++ = '.';
113 		*bp++ = (char)(*cp++ + '0');
114 	}
115 	*bp = '\0';
116 	return buf;
117 }
118 
119 
120 char *
121 fptoa(
122 	s_fp	fpv,
123 	short	ndec
124 	)
125 {
126 	u_fp	plusfp;
127 	int	neg;
128 
129 	neg = (fpv < 0);
130 	if (neg) {
131 		plusfp = (u_fp)(-fpv);
132 	} else {
133 		plusfp = (u_fp)fpv;
134 	}
135 
136 	return dofptoa(plusfp, (neg?'-':0), ndec, FALSE);
137 }
138 
139 
140 char *
141 fptoms(
142 	s_fp	fpv,
143 	short	ndec
144 	)
145 {
146 	u_fp	plusfp;
147 	int	neg;
148 
149 	neg = (fpv < 0);
150 	if (neg) {
151 		plusfp = (u_fp)(-fpv);
152 	} else {
153 		plusfp = (u_fp)fpv;
154 	}
155 
156 	return dofptoa(plusfp, (neg?'-':0), ndec, TRUE);
157 }
158