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