]> CyberLeo.Net >> Repos - FreeBSD/releng/9.3.git/blob - contrib/ntp/libntp/atolfp.c
o Fix invalid TCP checksums with pf(4). [EN-16:02.pf]
[FreeBSD/releng/9.3.git] / contrib / ntp / libntp / atolfp.c
1 /*
2  * atolfp - convert an ascii string 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_string.h"
10 #include "ntp_assert.h"
11
12 /*
13  * Powers of 10
14  */
15 static u_long ten_to_the_n[10] = {
16         0,
17         10,
18         100,
19         1000,
20         10000,
21         100000,
22         1000000,
23         10000000,
24         100000000,
25         1000000000,
26 };
27
28
29 int
30 atolfp(
31         const char *str,
32         l_fp *lfp
33         )
34 {
35         register const char *cp;
36         register u_long dec_i;
37         register u_long dec_f;
38         char *ind;
39         int ndec;
40         int isneg;
41         static const char *digits = "0123456789";
42
43         REQUIRE(str != NULL);
44
45         isneg = 0;
46         dec_i = dec_f = 0;
47         ndec = 0;
48         cp = str;
49
50         /*
51          * We understand numbers of the form:
52          *
53          * [spaces][-|+][digits][.][digits][spaces|\n|\0]
54          */
55         while (isspace((unsigned char)*cp))
56             cp++;
57         
58         if (*cp == '-') {
59                 cp++;
60                 isneg = 1;
61         }
62         
63         if (*cp == '+')
64             cp++;
65
66         if (*cp != '.' && !isdigit((unsigned char)*cp))
67             return 0;
68
69         while (*cp != '\0' && (ind = strchr(digits, *cp)) != NULL) {
70                 dec_i = (dec_i << 3) + (dec_i << 1);    /* multiply by 10 */
71                 dec_i += (u_long)(ind - digits);
72                 cp++;
73         }
74
75         if (*cp != '\0' && !isspace((unsigned char)*cp)) {
76                 if (*cp++ != '.')
77                     return 0;
78         
79                 while (ndec < 9 && *cp != '\0'
80                        && (ind = strchr(digits, *cp)) != NULL) {
81                         ndec++;
82                         dec_f = (dec_f << 3) + (dec_f << 1);    /* *10 */
83                         dec_f += (u_long)(ind - digits);
84                         cp++;
85                 }
86
87                 while (isdigit((unsigned char)*cp))
88                     cp++;
89                 
90                 if (*cp != '\0' && !isspace((unsigned char)*cp))
91                     return 0;
92         }
93
94         if (ndec > 0) {
95                 register u_long tmp;
96                 register u_long bit;
97                 register u_long ten_fact;
98
99                 ten_fact = ten_to_the_n[ndec];
100
101                 tmp = 0;
102                 bit = 0x80000000;
103                 while (bit != 0) {
104                         dec_f <<= 1;
105                         if (dec_f >= ten_fact) {
106                                 tmp |= bit;
107                                 dec_f -= ten_fact;
108                         }
109                         bit >>= 1;
110                 }
111                 if ((dec_f << 1) > ten_fact)
112                     tmp++;
113                 dec_f = tmp;
114         }
115
116         if (isneg)
117             M_NEG(dec_i, dec_f);
118         
119         lfp->l_ui = dec_i;
120         lfp->l_uf = dec_f;
121         return 1;
122 }