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