atolfp.c revision 293893
1216417Sdelphij/*
21590Srgrimes * atolfp - convert an ascii string to an l_fp number
31590Srgrimes */
41590Srgrimes#include <config.h>
51590Srgrimes#include <stdio.h>
61590Srgrimes#include <ctype.h>
71590Srgrimes
81590Srgrimes#include "ntp_fp.h"
91590Srgrimes#include "ntp_string.h"
101590Srgrimes#include "ntp_assert.h"
111590Srgrimes
121590Srgrimes/*
131590Srgrimes * Powers of 10
141590Srgrimes */
151590Srgrimesstatic u_long ten_to_the_n[10] = {
161590Srgrimes	0,
171590Srgrimes	10,
181590Srgrimes	100,
191590Srgrimes	1000,
201590Srgrimes	10000,
211590Srgrimes	100000,
221590Srgrimes	1000000,
231590Srgrimes	10000000,
241590Srgrimes	100000000,
251590Srgrimes	1000000000,
261590Srgrimes};
271590Srgrimes
281590Srgrimes
291590Srgrimesint
30216310Sjillesatolfp(
311590Srgrimes	const char *str,
3220409Ssteve	l_fp *lfp
331590Srgrimes	)
341590Srgrimes{
351590Srgrimes	register const char *cp;
361590Srgrimes	register u_long dec_i;
371590Srgrimes	register u_long dec_f;
381590Srgrimes	char *ind;
3965429Simp	int ndec;
4020409Ssteve	int isneg;
4165429Simp	static const char *digits = "0123456789";
4259435Scracauer
4359435Scracauer	REQUIRE(str != NULL);
441590Srgrimes
451590Srgrimes	isneg = 0;
461590Srgrimes	dec_i = dec_f = 0;
471590Srgrimes	ndec = 0;
481590Srgrimes	cp = str;
491590Srgrimes
50148721Sstefanf	/*
511590Srgrimes	 * We understand numbers of the form:
52216417Sdelphij	 *
531590Srgrimes	 * [spaces][-|+][digits][.][digits][spaces|\n|\0]
541590Srgrimes	 */
551590Srgrimes	while (isspace((unsigned char)*cp))
5627966Ssteve	    cp++;
571590Srgrimes
581590Srgrimes	if (*cp == '-') {
591590Srgrimes		cp++;
6012730Sjoerg		isneg = 1;
6170256Sben	}
62215520Sjilles
6341582Sbde	if (*cp == '+')
6441582Sbde	    cp++;
6541582Sbde
6641582Sbde	if (*cp != '.' && !isdigit((unsigned char)*cp))
671590Srgrimes	    return 0;
681590Srgrimes
6995409Stjr	while (*cp != '\0' && (ind = strchr(digits, *cp)) != NULL) {
7018613Speter		dec_i = (dec_i << 3) + (dec_i << 1);	/* multiply by 10 */
7198424Stjr		dec_i += (u_long)(ind - digits);
7298424Stjr		cp++;
7318613Speter	}
741590Srgrimes
7518613Speter	if (*cp != '\0' && !isspace((unsigned char)*cp)) {
7698424Stjr		if (*cp++ != '.')
7718613Speter		    return 0;
781590Srgrimes
7918613Speter		while (ndec < 9 && *cp != '\0'
8018613Speter		       && (ind = strchr(digits, *cp)) != NULL) {
8118613Speter			ndec++;
8218613Speter			dec_f = (dec_f << 3) + (dec_f << 1);	/* *10 */
8318613Speter			dec_f += (u_long)(ind - digits);
8495409Stjr			cp++;
851590Srgrimes		}
8692921Simp
87215520Sjilles		while (isdigit((unsigned char)*cp))
88145078Sstefanf		    cp++;
8992921Simp
90143906Sdas		if (*cp != '\0' && !isspace((unsigned char)*cp))
9192921Simp		    return 0;
92148721Sstefanf	}
9395409Stjr
9495409Stjr	if (ndec > 0) {
95216418Sdelphij		register u_long tmp;
9692921Simp		register u_long bit;
971590Srgrimes		register u_long ten_fact;
981590Srgrimes
991590Srgrimes		ten_fact = ten_to_the_n[ndec];
1001590Srgrimes
101102944Sdwmalone		tmp = 0;
1021590Srgrimes		bit = 0x80000000;
103145078Sstefanf		while (bit != 0) {
104216447Sdelphij			dec_f <<= 1;
105145061Sstefanf			if (dec_f >= ten_fact) {
1061590Srgrimes				tmp |= bit;
107216310Sjilles				dec_f -= ten_fact;
108216424Sdelphij			}
10972304Sache			bit >>= 1;
110215520Sjilles		}
111215520Sjilles		if ((dec_f << 1) > ten_fact)
112215520Sjilles		    tmp++;
113216447Sdelphij		dec_f = tmp;
114216447Sdelphij	}
115216447Sdelphij
116216447Sdelphij	if (isneg)
117216447Sdelphij	    M_NEG(dec_i, dec_f);
118216447Sdelphij
119216447Sdelphij	lfp->l_ui = dec_i;
120216447Sdelphij	lfp->l_uf = dec_f;
121216447Sdelphij	return 1;
1221590Srgrimes}
1231590Srgrimes