1*4887Schin /***********************************************************************
2*4887Schin *                                                                      *
3*4887Schin *               This software is part of the ast package               *
4*4887Schin *           Copyright (c) 1985-2007 AT&T Knowledge Ventures            *
5*4887Schin *                      and is licensed under the                       *
6*4887Schin *                  Common Public License, Version 1.0                  *
7*4887Schin *                      by AT&T Knowledge Ventures                      *
8*4887Schin *                                                                      *
9*4887Schin *                A copy of the License is available at                 *
10*4887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
11*4887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12*4887Schin *                                                                      *
13*4887Schin *              Information and Software Systems Research               *
14*4887Schin *                            AT&T Research                             *
15*4887Schin *                           Florham Park NJ                            *
16*4887Schin *                                                                      *
17*4887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
18*4887Schin *                  David Korn <dgk@research.att.com>                   *
19*4887Schin *                   Phong Vo <kpv@research.att.com>                    *
20*4887Schin *                                                                      *
21*4887Schin ***********************************************************************/
22*4887Schin #include	"sfhdr.h"
23*4887Schin 
24*4887Schin /*	Convert a Sfdouble_t value represented in an ASCII format into
25*4887Schin **	the internal Sfdouble_t representation.
26*4887Schin **
27*4887Schin **	Written by Kiem-Phong Vo.
28*4887Schin */
29*4887Schin 
30*4887Schin #define BATCH	(2*sizeof(int))	/* accumulate this many digits at a time */
31*4887Schin #define IPART		0	/* doing integer part */
32*4887Schin #define FPART		1	/* doing fractional part */
33*4887Schin #define EPART		2	/* doing exponent part */
34*4887Schin 
35*4887Schin #if __STD_C
36*4887Schin static Sfdouble_t sfpow10(reg int n)
37*4887Schin #else
38*4887Schin static Sfdouble_t sfpow10(n)
39*4887Schin reg int	n;
40*4887Schin #endif
41*4887Schin {
42*4887Schin 	Sfdouble_t	dval;
43*4887Schin 
44*4887Schin 	switch(n)
45*4887Schin 	{	case -3:	return .001;
46*4887Schin 		case -2:	return .01;
47*4887Schin 		case -1:	return .1;
48*4887Schin 		case  0:	return 1.;
49*4887Schin 		case  1:	return 10.;
50*4887Schin 		case  2:	return 100.;
51*4887Schin 		case  3:	return 1000.;
52*4887Schin 	}
53*4887Schin 
54*4887Schin 	if(n < 0)
55*4887Schin 	{	dval = .0001;
56*4887Schin 		for(n += 4; n < 0; n += 1)
57*4887Schin 			dval /= 10.;
58*4887Schin 	}
59*4887Schin 	else
60*4887Schin 	{	dval = 10000.;
61*4887Schin 		for(n -= 4; n > 0; n -= 1)
62*4887Schin 			dval *= 10.;
63*4887Schin 	}
64*4887Schin 
65*4887Schin 	return dval;
66*4887Schin }
67*4887Schin 
68*4887Schin #if __STD_C
69*4887Schin Sfdouble_t _sfstrtod(reg const char* s, char** retp)
70*4887Schin #else
71*4887Schin Sfdouble_t _sfstrtod(s,retp)
72*4887Schin reg char*	s;	/* string to convert */
73*4887Schin char**		retp;	/* to return the remainder of string */
74*4887Schin #endif
75*4887Schin {
76*4887Schin 	reg int		n, c, m;
77*4887Schin 	reg int		mode, fexp, sign, expsign;
78*4887Schin 	Sfdouble_t	dval;
79*4887Schin #if _lib_locale
80*4887Schin 	int		decpoint = 0;
81*4887Schin 	int		thousand = 0;
82*4887Schin 	SFSETLOCALE(&decpoint,&thousand);
83*4887Schin #else
84*4887Schin #define decpoint	'.'
85*4887Schin #endif
86*4887Schin 
87*4887Schin 	/* skip initial blanks */
88*4887Schin 	while(isspace(*s))
89*4887Schin 		++s;
90*4887Schin 
91*4887Schin 	/* get the sign */
92*4887Schin 	if((sign = (*s == '-')) || *s == '+')
93*4887Schin 		s += 1;
94*4887Schin 
95*4887Schin 	mode = IPART;
96*4887Schin 	fexp = expsign = 0;
97*4887Schin 	dval = 0.;
98*4887Schin 	while(*s)
99*4887Schin 	{	/* accumulate a handful of the digits */
100*4887Schin 		for(m = BATCH, n = 0; m > 0; --m, ++s)
101*4887Schin 		{	/* get and process a char */
102*4887Schin 			c = *s;
103*4887Schin 			if(isdigit(c))
104*4887Schin 				n = 10*n + (c - '0');
105*4887Schin 			else	break;
106*4887Schin 		}
107*4887Schin 
108*4887Schin 		/* number of digits accumulated */
109*4887Schin 		m = BATCH-m;
110*4887Schin 
111*4887Schin 		if(mode == IPART)
112*4887Schin 		{	/* doing the integer part */
113*4887Schin 			if(dval == 0.)
114*4887Schin 				dval = (Sfdouble_t)n;
115*4887Schin 			else	dval = dval*sfpow10(m) + (Sfdouble_t)n;
116*4887Schin 		}
117*4887Schin 		else if(mode == FPART)
118*4887Schin 		{	/* doing the fractional part */
119*4887Schin 			fexp -= m;
120*4887Schin 			if(n > 0)
121*4887Schin 				dval += n*sfpow10(fexp);
122*4887Schin 		}
123*4887Schin 		else if(n)
124*4887Schin 		{	/* doing the exponent part */
125*4887Schin 			if(expsign)
126*4887Schin 				n = -n;
127*4887Schin 			dval *= sfpow10(n);
128*4887Schin 		}
129*4887Schin 
130*4887Schin 		if(!c)
131*4887Schin 			break;
132*4887Schin 
133*4887Schin 		if(m < BATCH)
134*4887Schin 		{	/* detected a non-digit */
135*4887Schin 			if(c == decpoint)
136*4887Schin 			{	/* start the fractional part or no match */
137*4887Schin 				if(mode != IPART)
138*4887Schin 					break;
139*4887Schin 				mode = FPART;
140*4887Schin 				s += 1;
141*4887Schin 			}
142*4887Schin 			else if(c == 'e' || c == 'E')
143*4887Schin 			{	if(mode == EPART)
144*4887Schin 					break;
145*4887Schin 				mode = EPART;
146*4887Schin 				c = *++s;
147*4887Schin 				if((expsign = (c == '-')) || c == '+')
148*4887Schin 					s += 1;
149*4887Schin 			}
150*4887Schin 			else	break;
151*4887Schin 		}
152*4887Schin 	}
153*4887Schin 
154*4887Schin 	if(retp)
155*4887Schin 		*retp = (char*)s;
156*4887Schin 	return sign ? -dval : dval;
157*4887Schin }
158