]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/ntp/libntp/mstolfp.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / ntp / libntp / mstolfp.c
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 }