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