/*	@(#)atof.c	2.1 	*/
/*	3.0 SID #	1.2	*/
/*LINTLIBRARY*/
/*
 *	C library - ascii to floating
 */

#include <ctype.h>
#include <values.h>

extern double ldexp();

double
atof(p)
register char *p;
{
	register int c, eexp, exp, neg, negexp, bexp;
	double fl, flexp, exp5;

	neg = 1;
	while(isspace(*p))
		++p;
	if(*p == '-') {
		++p;
		neg = -1;
	}
	else if(*p == '+')
		++p;

	exp = 0;
	fl = 0;
	while((c = *p++), isdigit(c))
		if(fl < 2.0 * MAXPOWTWO)
			fl = 10*fl + (c-'0');
		else
			exp++;

	if(c == '.')
		while((c = *p++), isdigit(c))
			if(fl < 2.0 * MAXPOWTWO) {
				fl = 10*fl + (c-'0');
				exp--;
			}

	negexp = 1;
	eexp = 0;
	if((c == 'E') || (c == 'e')) {
		if((c = *p++) == '+')
			;
		else if(c == '-')
			negexp = -1;
		     else
			--p;

		while((c = *p++), isdigit(c))
			eexp = 10*eexp + (c-'0');

		if(negexp < 0)
			eexp = -eexp;
		exp = exp + eexp;
	}

	negexp = 1;
	if(exp < 0) {
		negexp = -1;
		exp = -exp;
	}

	/*
	 * The following computation is done in two stages,
	 * first accumulating powers of 5, then jamming powers of 2,
	 * to avoid underflow in situations like the following (for
	 * the DEC representation): 1.2345678901234567890e-37,
	 * where exp would be about (-37 + -18) = -55, and the
	 * value 10^(-55) can't be represented, but 5^(-55) can
	 * be represented, and then 2^(-55) jammed via ldexp().
	 */
	flexp = 1;
	exp5 = 5;
	bexp = exp;
	while(1) {
		if(exp&01)
			flexp *= exp5;
		exp >>= 1;
		if(exp == 0)
			break;
		exp5 *= exp5;
	}
	if(negexp < 0)
		fl /= flexp;
	else
		fl *= flexp;
	fl = ldexp(fl, negexp*bexp);
	if(neg < 0)
		fl = -fl;
	return(fl);
}
