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