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
14char *
15dofptoa(
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
124char *
125fptoa(
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
144char *
145fptoms(
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