xref: /freebsd/contrib/ntp/libntp/mstolfp.c (revision 93e779a26c651610ac6e7986d67ecc9ed2cadcbf)
1 /*
2  * mstolfp - convert an ascii string in milliseconds to an l_fp number
3  */
4 #include <config.h>
5 #include <stdio.h>
6 #include <ctype.h>
7 
8 #include "ntp_fp.h"
9 #include "ntp_stdlib.h"
10 
11 int
12 mstolfp(
13 	const char *str,
14 	l_fp *lfp
15 	)
16 {
17 	register const char *cp;
18 	register char *bp;
19 	register const char *cpdec;
20 	char buf[100];
21 
22 	/*
23 	 * We understand numbers of the form:
24 	 *
25 	 * [spaces][-][digits][.][digits][spaces|\n|\0]
26 	 *
27 	 * This is one enormous hack.  Since I didn't feel like
28 	 * rewriting the decoding routine for milliseconds, what
29 	 * is essentially done here is to make a copy of the string
30 	 * with the decimal moved over three places so the seconds
31 	 * decoding routine can be used.
32 	 */
33 	bp = buf;
34 	cp = str;
35 	while (isspace((unsigned char)*cp))
36 	    cp++;
37 
38 	if (*cp == '-') {
39 		*bp++ = '-';
40 		cp++;
41 	}
42 
43 	if (*cp != '.' && !isdigit((unsigned char)*cp))
44 	    return 0;
45 
46 
47 	/*
48 	 * Search forward for the decimal point or the end of the string.
49 	 */
50 	cpdec = cp;
51 	while (isdigit((unsigned char)*cpdec))
52 	    cpdec++;
53 
54 	/*
55 	 * Found something.  If we have more than three digits copy the
56 	 * excess over, else insert a leading 0.
57 	 */
58 	if ((cpdec - cp) > 3) {
59 		do {
60 			*bp++ = (char)*cp++;
61 		} while ((cpdec - cp) > 3);
62 	} else {
63 		*bp++ = '0';
64 	}
65 
66 	/*
67 	 * Stick the decimal in.  If we've got less than three digits in
68 	 * front of the millisecond decimal we insert the appropriate number
69 	 * of zeros.
70 	 */
71 	*bp++ = '.';
72 	if ((cpdec - cp) < 3) {
73 		register int i = 3 - (cpdec - cp);
74 
75 		do {
76 			*bp++ = '0';
77 		} while (--i > 0);
78 	}
79 
80 	/*
81 	 * Copy the remainder up to the millisecond decimal.  If cpdec
82 	 * is pointing at a decimal point, copy in the trailing number too.
83 	 */
84 	while (cp < cpdec)
85 	    *bp++ = (char)*cp++;
86 
87 	if (*cp == '.') {
88 		cp++;
89 		while (isdigit((unsigned char)*cp))
90 		    *bp++ = (char)*cp++;
91 	}
92 	*bp = '\0';
93 
94 	/*
95 	 * Check to make sure the string is properly terminated.  If
96 	 * so, give the buffer to the decoding routine.
97 	 */
98 	if (*cp != '\0' && !isspace((unsigned char)*cp))
99 	    return 0;
100 	return atolfp(buf, lfp);
101 }
102