1c0b746e5SOllivier Robert /*
2c0b746e5SOllivier Robert * atolfp - convert an ascii string to an l_fp number
3c0b746e5SOllivier Robert */
42b15cb3dSCy Schubert #include <config.h>
5c0b746e5SOllivier Robert #include <stdio.h>
6c0b746e5SOllivier Robert #include <ctype.h>
7c0b746e5SOllivier Robert
8c0b746e5SOllivier Robert #include "ntp_fp.h"
9c0b746e5SOllivier Robert #include "ntp_string.h"
102b15cb3dSCy Schubert #include "ntp_assert.h"
11c0b746e5SOllivier Robert
12c0b746e5SOllivier Robert /*
13c0b746e5SOllivier Robert * Powers of 10
14c0b746e5SOllivier Robert */
15c0b746e5SOllivier Robert static u_long ten_to_the_n[10] = {
16c0b746e5SOllivier Robert 0,
17c0b746e5SOllivier Robert 10,
18c0b746e5SOllivier Robert 100,
19c0b746e5SOllivier Robert 1000,
20c0b746e5SOllivier Robert 10000,
21c0b746e5SOllivier Robert 100000,
22c0b746e5SOllivier Robert 1000000,
23c0b746e5SOllivier Robert 10000000,
24c0b746e5SOllivier Robert 100000000,
25c0b746e5SOllivier Robert 1000000000,
26c0b746e5SOllivier Robert };
27c0b746e5SOllivier Robert
28c0b746e5SOllivier Robert
29c0b746e5SOllivier Robert int
atolfp(const char * str,l_fp * lfp)30c0b746e5SOllivier Robert atolfp(
31c0b746e5SOllivier Robert const char *str,
32c0b746e5SOllivier Robert l_fp *lfp
33c0b746e5SOllivier Robert )
34c0b746e5SOllivier Robert {
35c0b746e5SOllivier Robert register const char *cp;
36c0b746e5SOllivier Robert register u_long dec_i;
37c0b746e5SOllivier Robert register u_long dec_f;
38c0b746e5SOllivier Robert char *ind;
39c0b746e5SOllivier Robert int ndec;
40c0b746e5SOllivier Robert int isneg;
41c0b746e5SOllivier Robert static const char *digits = "0123456789";
42c0b746e5SOllivier Robert
439034852cSGleb Smirnoff REQUIRE(str != NULL);
442b15cb3dSCy Schubert
45c0b746e5SOllivier Robert isneg = 0;
46c0b746e5SOllivier Robert dec_i = dec_f = 0;
47c0b746e5SOllivier Robert ndec = 0;
48c0b746e5SOllivier Robert cp = str;
49c0b746e5SOllivier Robert
50c0b746e5SOllivier Robert /*
51c0b746e5SOllivier Robert * We understand numbers of the form:
52c0b746e5SOllivier Robert *
53c0b746e5SOllivier Robert * [spaces][-|+][digits][.][digits][spaces|\n|\0]
54c0b746e5SOllivier Robert */
552b15cb3dSCy Schubert while (isspace((unsigned char)*cp))
56c0b746e5SOllivier Robert cp++;
57c0b746e5SOllivier Robert
58c0b746e5SOllivier Robert if (*cp == '-') {
59c0b746e5SOllivier Robert cp++;
60c0b746e5SOllivier Robert isneg = 1;
61c0b746e5SOllivier Robert }
62c0b746e5SOllivier Robert
63c0b746e5SOllivier Robert if (*cp == '+')
64c0b746e5SOllivier Robert cp++;
65c0b746e5SOllivier Robert
662b15cb3dSCy Schubert if (*cp != '.' && !isdigit((unsigned char)*cp))
67c0b746e5SOllivier Robert return 0;
68c0b746e5SOllivier Robert
69c0b746e5SOllivier Robert while (*cp != '\0' && (ind = strchr(digits, *cp)) != NULL) {
70c0b746e5SOllivier Robert dec_i = (dec_i << 3) + (dec_i << 1); /* multiply by 10 */
71*3311ff84SXin LI dec_i += (u_long)(ind - digits);
72c0b746e5SOllivier Robert cp++;
73c0b746e5SOllivier Robert }
74c0b746e5SOllivier Robert
752b15cb3dSCy Schubert if (*cp != '\0' && !isspace((unsigned char)*cp)) {
76c0b746e5SOllivier Robert if (*cp++ != '.')
77c0b746e5SOllivier Robert return 0;
78c0b746e5SOllivier Robert
79c0b746e5SOllivier Robert while (ndec < 9 && *cp != '\0'
80c0b746e5SOllivier Robert && (ind = strchr(digits, *cp)) != NULL) {
81c0b746e5SOllivier Robert ndec++;
82c0b746e5SOllivier Robert dec_f = (dec_f << 3) + (dec_f << 1); /* *10 */
83*3311ff84SXin LI dec_f += (u_long)(ind - digits);
84c0b746e5SOllivier Robert cp++;
85c0b746e5SOllivier Robert }
86c0b746e5SOllivier Robert
872b15cb3dSCy Schubert while (isdigit((unsigned char)*cp))
88c0b746e5SOllivier Robert cp++;
89c0b746e5SOllivier Robert
902b15cb3dSCy Schubert if (*cp != '\0' && !isspace((unsigned char)*cp))
91c0b746e5SOllivier Robert return 0;
92c0b746e5SOllivier Robert }
93c0b746e5SOllivier Robert
94c0b746e5SOllivier Robert if (ndec > 0) {
95c0b746e5SOllivier Robert register u_long tmp;
96c0b746e5SOllivier Robert register u_long bit;
97c0b746e5SOllivier Robert register u_long ten_fact;
98c0b746e5SOllivier Robert
99c0b746e5SOllivier Robert ten_fact = ten_to_the_n[ndec];
100c0b746e5SOllivier Robert
101c0b746e5SOllivier Robert tmp = 0;
102c0b746e5SOllivier Robert bit = 0x80000000;
103c0b746e5SOllivier Robert while (bit != 0) {
104c0b746e5SOllivier Robert dec_f <<= 1;
105c0b746e5SOllivier Robert if (dec_f >= ten_fact) {
106c0b746e5SOllivier Robert tmp |= bit;
107c0b746e5SOllivier Robert dec_f -= ten_fact;
108c0b746e5SOllivier Robert }
109c0b746e5SOllivier Robert bit >>= 1;
110c0b746e5SOllivier Robert }
111c0b746e5SOllivier Robert if ((dec_f << 1) > ten_fact)
112c0b746e5SOllivier Robert tmp++;
113c0b746e5SOllivier Robert dec_f = tmp;
114c0b746e5SOllivier Robert }
115c0b746e5SOllivier Robert
116c0b746e5SOllivier Robert if (isneg)
117c0b746e5SOllivier Robert M_NEG(dec_i, dec_f);
118c0b746e5SOllivier Robert
119c0b746e5SOllivier Robert lfp->l_ui = dec_i;
120c0b746e5SOllivier Robert lfp->l_uf = dec_f;
121c0b746e5SOllivier Robert return 1;
122c0b746e5SOllivier Robert }
123