xref: /freebsd/contrib/ntp/libntp/atolfp.c (revision e0c4386e)
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 }
123