]> CyberLeo.Net >> Repos - FreeBSD/releng/9.3.git/blob - contrib/ntp/libntp/mstolfp.c
o Fix invalid TCP checksums with pf(4). [EN-16:02.pf]
[FreeBSD/releng/9.3.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                 size_t i = 3 - (cpdec - cp);
74                 do {
75                         *bp++ = '0';
76                 } while (--i > 0);
77         }
78
79         /*
80          * Copy the remainder up to the millisecond decimal.  If cpdec
81          * is pointing at a decimal point, copy in the trailing number too.
82          */
83         while (cp < cpdec)
84             *bp++ = (char)*cp++;
85         
86         if (*cp == '.') {
87                 cp++;
88                 while (isdigit((unsigned char)*cp))
89                     *bp++ = (char)*cp++;
90         }
91         *bp = '\0';
92
93         /*
94          * Check to make sure the string is properly terminated.  If
95          * so, give the buffer to the decoding routine.
96          */
97         if (*cp != '\0' && !isspace((unsigned char)*cp))
98             return 0;
99         return atolfp(buf, lfp);
100 }