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