153913Sarchie/*
253913Sarchie * dofptoa - do the grunge work to convert an fp number to ascii
353913Sarchie */
453913Sarchie#include <config.h>
553913Sarchie#include <stdio.h>
653913Sarchie
753913Sarchie#include "ntp_fp.h"
853913Sarchie#include "ntp_stdlib.h"
953913Sarchie
1053913Sarchiechar *
1153913Sarchiedofptoa(
1253913Sarchie	u_fp fpv,
1353913Sarchie	char sign,
1453913Sarchie	short ndec,
1553913Sarchie	int msec
1653913Sarchie	)
1753913Sarchie{
1853913Sarchie	register u_char *cp, *cpend;
1953913Sarchie	register u_long val;
2053913Sarchie	register short dec;
2153913Sarchie	u_char cbuf[12];
2253913Sarchie	u_char *cpdec;
2353913Sarchie	char *buf;
2453913Sarchie	char *bp;
2553913Sarchie
2653913Sarchie	/*
2753913Sarchie	 * Get a string buffer before starting
2853913Sarchie	 */
2953913Sarchie	LIB_GETBUF(buf);
3053913Sarchie
3153913Sarchie	/*
3253913Sarchie	 * Zero out the buffer
3353913Sarchie	 */
3453913Sarchie	ZERO(cbuf);
3553913Sarchie
3653913Sarchie	/*
3753913Sarchie	 * Set the pointers to point at the first
3853913Sarchie	 * decimal place.  Get a local copy of the value.
3953913Sarchie	 */
4053913Sarchie	cp = cpend = &cbuf[5];
4153913Sarchie	val = fpv;
4253913Sarchie
4353913Sarchie	/*
4453913Sarchie	 * If we have to, decode the integral part
4553913Sarchie	 */
4653913Sarchie	if (!(val & 0xffff0000))
4753913Sarchie	    cp--;
4853913Sarchie	else {
4953913Sarchie		register u_short sv = (u_short)(val >> 16);
5053913Sarchie		register u_short tmp;
5153913Sarchie		register u_short ten = 10;
5253913Sarchie
5353913Sarchie		do {
5458018Sarchie			tmp = sv;
5553913Sarchie			sv = (u_short) (sv/ten);
5653913Sarchie			*(--cp) = (u_char)(tmp - ((sv<<3) + (sv<<1)));
5753913Sarchie		} while (sv != 0);
5853913Sarchie	}
5953913Sarchie
6053913Sarchie	/*
6153913Sarchie	 * Figure out how much of the fraction to do
6253913Sarchie	 */
6353913Sarchie	if (msec) {
6453913Sarchie		dec = (short)(ndec + 3);
6553913Sarchie		if (dec < 3)
6653913Sarchie		    dec = 3;
6753913Sarchie		cpdec = &cbuf[8];
6853913Sarchie	} else {
6953913Sarchie		dec = ndec;
7053913Sarchie		cpdec = cpend;
7153913Sarchie	}
7253913Sarchie
7353913Sarchie	if (dec > 6)
7453913Sarchie	    dec = 6;
7553913Sarchie
7653913Sarchie	if (dec > 0) {
7753913Sarchie		do {
7853913Sarchie			val &= 0xffff;
7953913Sarchie			val = (val << 3) + (val << 1);
8053913Sarchie			*cpend++ = (u_char)(val >> 16);
8153913Sarchie		} while (--dec > 0);
8253913Sarchie	}
8353913Sarchie
8453913Sarchie	if (val & 0x8000) {
8553913Sarchie		register u_char *tp;
8653913Sarchie		/*
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
120char *
121fptoa(
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
140char *
141fptoms(
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