1 /* 2 * mstolfp - convert an ascii string in milliseconds 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_stdlib.h" 10 11 int 12 mstolfp( 13 const char *str, 14 l_fp *lfp 15 ) 16 { 17 int ch, neg = 0; 18 u_int32 q, r; 19 20 /* 21 * We understand numbers of the form: 22 * 23 * [spaces][-|+][digits][.][digits][spaces|\n|\0] 24 * 25 * This is kinda hack. We use 'atolfp' to do the basic parsing 26 * (after some initial checks) and then divide the result by 27 * 1000. The original implementation avoided that by 28 * hacking up the input string to move the decimal point, but 29 * that needed string manipulations prone to buffer overruns. 30 * To avoid that trouble we do the conversion first and adjust 31 * the result. 32 */ 33 34 while (isspace(ch = *(const unsigned char*)str)) 35 ++str; 36 37 switch (ch) { 38 case '-': neg = TRUE; 39 case '+': ++str; 40 default : break; 41 } 42 43 if (!isdigit(ch = *(const unsigned char*)str) && (ch != '.')) 44 return 0; 45 if (!atolfp(str, lfp)) 46 return 0; 47 48 /* now do a chained/overlapping division by 1000 to get from 49 * seconds to msec. 1000 is small enough to go with temporary 50 * 32bit accus for Q and R. 51 */ 52 q = lfp->l_ui / 1000u; 53 r = lfp->l_ui - (q * 1000u); 54 lfp->l_ui = q; 55 56 r = (r << 16) | (lfp->l_uf >> 16); 57 q = r / 1000u; 58 r = ((r - q * 1000) << 16) | (lfp->l_uf & 0x0FFFFu); 59 lfp->l_uf = q << 16; 60 q = r / 1000; 61 lfp->l_uf |= q; 62 r -= q * 1000u; 63 64 /* fix sign */ 65 if (neg) 66 L_NEG(lfp); 67 /* round */ 68 if (r >= 500) 69 L_ADDF(lfp, (neg ? -1 : 1)); 70 return 1; 71 } 72