xref: /onnv-gate/usr/src/lib/libast/common/sfio/sfstrtod.c (revision 12068:08a39a083754)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1985-2010 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
78462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
84887Schin *                                                                      *
94887Schin *                A copy of the License is available at                 *
104887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
114887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
124887Schin *                                                                      *
134887Schin *              Information and Software Systems Research               *
144887Schin *                            AT&T Research                             *
154887Schin *                           Florham Park NJ                            *
164887Schin *                                                                      *
174887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
184887Schin *                  David Korn <dgk@research.att.com>                   *
194887Schin *                   Phong Vo <kpv@research.att.com>                    *
204887Schin *                                                                      *
214887Schin ***********************************************************************/
224887Schin #include	"sfhdr.h"
234887Schin 
244887Schin /*	Convert a Sfdouble_t value represented in an ASCII format into
254887Schin **	the internal Sfdouble_t representation.
264887Schin **
274887Schin **	Written by Kiem-Phong Vo.
284887Schin */
294887Schin 
304887Schin #define BATCH	(2*sizeof(int))	/* accumulate this many digits at a time */
314887Schin #define IPART		0	/* doing integer part */
324887Schin #define FPART		1	/* doing fractional part */
334887Schin #define EPART		2	/* doing exponent part */
344887Schin 
354887Schin #if __STD_C
sfpow10(reg int n)364887Schin static Sfdouble_t sfpow10(reg int n)
374887Schin #else
384887Schin static Sfdouble_t sfpow10(n)
394887Schin reg int	n;
404887Schin #endif
414887Schin {
424887Schin 	Sfdouble_t	dval;
434887Schin 
444887Schin 	switch(n)
454887Schin 	{	case -3:	return .001;
464887Schin 		case -2:	return .01;
474887Schin 		case -1:	return .1;
484887Schin 		case  0:	return 1.;
494887Schin 		case  1:	return 10.;
504887Schin 		case  2:	return 100.;
514887Schin 		case  3:	return 1000.;
524887Schin 	}
534887Schin 
544887Schin 	if(n < 0)
554887Schin 	{	dval = .0001;
564887Schin 		for(n += 4; n < 0; n += 1)
574887Schin 			dval /= 10.;
584887Schin 	}
594887Schin 	else
604887Schin 	{	dval = 10000.;
614887Schin 		for(n -= 4; n > 0; n -= 1)
624887Schin 			dval *= 10.;
634887Schin 	}
644887Schin 
654887Schin 	return dval;
664887Schin }
674887Schin 
684887Schin #if __STD_C
_sfstrtod(reg const char * s,char ** retp)694887Schin Sfdouble_t _sfstrtod(reg const char* s, char** retp)
704887Schin #else
714887Schin Sfdouble_t _sfstrtod(s,retp)
724887Schin reg char*	s;	/* string to convert */
734887Schin char**		retp;	/* to return the remainder of string */
744887Schin #endif
754887Schin {
764887Schin 	reg int		n, c, m;
774887Schin 	reg int		mode, fexp, sign, expsign;
784887Schin 	Sfdouble_t	dval;
794887Schin #if _lib_locale
804887Schin 	int		decpoint = 0;
814887Schin 	int		thousand = 0;
824887Schin 	SFSETLOCALE(&decpoint,&thousand);
834887Schin #else
844887Schin #define decpoint	'.'
854887Schin #endif
864887Schin 
874887Schin 	/* skip initial blanks */
884887Schin 	while(isspace(*s))
894887Schin 		++s;
904887Schin 
914887Schin 	/* get the sign */
924887Schin 	if((sign = (*s == '-')) || *s == '+')
934887Schin 		s += 1;
944887Schin 
954887Schin 	mode = IPART;
964887Schin 	fexp = expsign = 0;
974887Schin 	dval = 0.;
984887Schin 	while(*s)
994887Schin 	{	/* accumulate a handful of the digits */
1004887Schin 		for(m = BATCH, n = 0; m > 0; --m, ++s)
1014887Schin 		{	/* get and process a char */
1024887Schin 			c = *s;
1034887Schin 			if(isdigit(c))
1044887Schin 				n = 10*n + (c - '0');
1054887Schin 			else	break;
1064887Schin 		}
1074887Schin 
1084887Schin 		/* number of digits accumulated */
1094887Schin 		m = BATCH-m;
1104887Schin 
1114887Schin 		if(mode == IPART)
1124887Schin 		{	/* doing the integer part */
1134887Schin 			if(dval == 0.)
1144887Schin 				dval = (Sfdouble_t)n;
1154887Schin 			else	dval = dval*sfpow10(m) + (Sfdouble_t)n;
1164887Schin 		}
1174887Schin 		else if(mode == FPART)
1184887Schin 		{	/* doing the fractional part */
1194887Schin 			fexp -= m;
1204887Schin 			if(n > 0)
1214887Schin 				dval += n*sfpow10(fexp);
1224887Schin 		}
1234887Schin 		else if(n)
1244887Schin 		{	/* doing the exponent part */
1254887Schin 			if(expsign)
1264887Schin 				n = -n;
1274887Schin 			dval *= sfpow10(n);
1284887Schin 		}
1294887Schin 
1304887Schin 		if(!c)
1314887Schin 			break;
1324887Schin 
1334887Schin 		if(m < BATCH)
1344887Schin 		{	/* detected a non-digit */
1354887Schin 			if(c == decpoint)
1364887Schin 			{	/* start the fractional part or no match */
1374887Schin 				if(mode != IPART)
1384887Schin 					break;
1394887Schin 				mode = FPART;
1404887Schin 				s += 1;
1414887Schin 			}
1424887Schin 			else if(c == 'e' || c == 'E')
1434887Schin 			{	if(mode == EPART)
1444887Schin 					break;
1454887Schin 				mode = EPART;
1464887Schin 				c = *++s;
1474887Schin 				if((expsign = (c == '-')) || c == '+')
1484887Schin 					s += 1;
1494887Schin 			}
1504887Schin 			else	break;
1514887Schin 		}
1524887Schin 	}
1534887Schin 
1544887Schin 	if(retp)
1554887Schin 		*retp = (char*)s;
1564887Schin 	return sign ? -dval : dval;
1574887Schin }
158