/*
 * strtod.c
 *
 * Stupid version of System V strtod(3) library routine.
 * Does no overflow/underflow checking.
 *
 * A real number is defined to be
 *	optional leading white space
 *	optional sign
 *	string of digits with optional decimal point
 *	optional 'e' or 'E'
 *		followed by optional sign or space
 *		followed by an integer
 *
 * if ptr is not NULL a pointer to the character terminating the
 * scan is returned in *ptr.  If no number formed, *ptr is set to str
 * and 0 is returned.
 *
 * For speed, we don't do the conversion ourselves.  Instead, we find
 * the end of the number and then call atof() to do the dirty work.
 * This bought us a 10% speedup on a sample program at uunet.uu.net.
 */

#if 0
#include <ctype.h>
#endif

extern double atof();

double
strtod(s, ptr)
register char *s;
register char **ptr;
{
	double ret = 0.0;
	char *start = s;
	char *begin = NULL;
	int success = 0;

	/* optional white space */
	while (isspace(*s))
		s++;

	/* optional sign */
	if (*s == '+' || *s == '-') {
		s++;
		if (*(s-1) == '-')
			begin = s - 1;
		else
			begin = s;
	}

	/* string of digits with optional decimal point */
	if (isdigit(*s) && ! begin)
		begin = s;

	while (isdigit(*s)) {
		s++;
		success++;
	}

	if (*s == '.') {
		if (! begin)
			begin = s;
		s++;
		while (isdigit(*s))
			s++;
		success++;
	}

	if (s == start || success == 0)		/* nothing there */
		goto out;

	/*
 	 *	optional 'e' or 'E'
	 *		followed by optional sign or space
	 *		followed by an integer
	 */

	if (*s == 'e' || *s == 'E') {
		s++;

		/* XXX - atof probably doesn't allow spaces here */
		while (isspace(*s))
			s++;

		if (*s == '+' || *s == '-')
			s++;

		while (isdigit(*s))
			s++;
	}

	/* go for it */
	ret = atof(begin);

out:
	if (! success)
		s = start;	/* in case all we did was skip whitespace */

	if (ptr)
		*ptr = s;

	return ret;
}

#ifdef TEST
int
main(argc, argv)
int argc;
char **argv;
{
	double d;
	char *p;

	for (argc--, argv++; argc; argc--, argv++) {
		d = strtod (*argv, & p);
		printf ("%lf [%s]\n", d, p);
	}

	return 0;
}
#endif
