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 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 43*9034852cSGleb 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 */ 71c0b746e5SOllivier Robert dec_i += (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 */ 83c0b746e5SOllivier Robert dec_f += (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