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