1/* $NetBSD: mstolfp.c,v 1.8 2020/05/25 20:47:24 christos Exp $ */ 2 3/* 4 * mstolfp - convert an ascii string in milliseconds to an l_fp number 5 */ 6#include <config.h> 7#include <stdio.h> 8#include <ctype.h> 9 10#include "ntp_fp.h" 11#include "ntp_stdlib.h" 12 13int 14mstolfp( 15 const char *str, 16 l_fp *lfp 17 ) 18{ 19 register const char *cp; 20 register char *bp; 21 register const char *cpdec; 22 char buf[100]; 23 24 /* 25 * We understand numbers of the form: 26 * 27 * [spaces][-|+][digits][.][digits][spaces|\n|\0] 28 * 29 * This is one enormous hack. Since I didn't feel like 30 * rewriting the decoding routine for milliseconds, what 31 * is essentially done here is to make a copy of the string 32 * with the decimal moved over three places so the seconds 33 * decoding routine can be used. 34 */ 35 bp = buf; 36 cp = str; 37 while (isspace((unsigned char)*cp)) 38 cp++; 39 40 if (*cp == '-' || *cp == '+') { 41 *bp++ = *cp++; 42 } 43 44 if (*cp != '.' && !isdigit((unsigned char)*cp)) 45 return 0; 46 47 48 /* 49 * Search forward for the decimal point or the end of the string. 50 */ 51 cpdec = cp; 52 while (isdigit((unsigned char)*cpdec)) 53 cpdec++; 54 55 /* 56 * Found something. If we have more than three digits copy the 57 * excess over, else insert a leading 0. 58 */ 59 if ((cpdec - cp) > 3) { 60 do { 61 *bp++ = (char)*cp++; 62 } while ((cpdec - cp) > 3); 63 } else { 64 *bp++ = '0'; 65 } 66 67 /* 68 * Stick the decimal in. If we've got less than three digits in 69 * front of the millisecond decimal we insert the appropriate number 70 * of zeros. 71 */ 72 *bp++ = '.'; 73 if ((cpdec - cp) < 3) { 74 size_t i = 3 - (cpdec - cp); 75 do { 76 *bp++ = '0'; 77 } while (--i > 0); 78 } 79 80 /* 81 * Copy the remainder up to the millisecond decimal. If cpdec 82 * is pointing at a decimal point, copy in the trailing number too. 83 */ 84 while (cp < cpdec) 85 *bp++ = (char)*cp++; 86 87 if (*cp == '.') { 88 cp++; 89 while (isdigit((unsigned char)*cp)) 90 *bp++ = (char)*cp++; 91 } 92 *bp = '\0'; 93 94 /* 95 * Check to make sure the string is properly terminated. If 96 * so, give the buffer to the decoding routine. 97 */ 98 if (*cp != '\0' && !isspace((unsigned char)*cp)) 99 return 0; 100 return atolfp(buf, lfp); 101} 102