1N/A/***********************************************************************
1N/A* *
1N/A* This software is part of the ast package *
1N/A* Copyright (c) 1985-2011 AT&T Intellectual Property *
1N/A* and is licensed under the *
1N/A* Common Public License, Version 1.0 *
1N/A* by AT&T Intellectual Property *
1N/A* *
1N/A* A copy of the License is available at *
1N/A* http://www.opensource.org/licenses/cpl1.0.txt *
1N/A* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
1N/A* *
1N/A* Information and Software Systems Research *
1N/A* AT&T Research *
1N/A* Florham Park NJ *
1N/A* *
1N/A* Glenn Fowler <gsf@research.att.com> *
1N/A* David Korn <dgk@research.att.com> *
1N/A* Phong Vo <kpv@research.att.com> *
1N/A* *
1N/A***********************************************************************/
1N/A#include "sfhdr.h"
1N/A
1N/A/* Convert a Sfdouble_t value represented in an ASCII format into
1N/A** the internal Sfdouble_t representation.
1N/A**
1N/A** Written by Kiem-Phong Vo.
1N/A*/
1N/A
1N/A#define BATCH (2*sizeof(int)) /* accumulate this many digits at a time */
1N/A#define IPART 0 /* doing integer part */
1N/A#define FPART 1 /* doing fractional part */
1N/A#define EPART 2 /* doing exponent part */
1N/A
1N/A#if __STD_C
1N/Astatic Sfdouble_t sfpow10(reg int n)
1N/A#else
1N/Astatic Sfdouble_t sfpow10(n)
1N/Areg int n;
1N/A#endif
1N/A{
1N/A Sfdouble_t dval;
1N/A
1N/A switch(n)
1N/A { case -3: return .001;
1N/A case -2: return .01;
1N/A case -1: return .1;
1N/A case 0: return 1.;
1N/A case 1: return 10.;
1N/A case 2: return 100.;
1N/A case 3: return 1000.;
1N/A }
1N/A
1N/A if(n < 0)
1N/A { dval = .0001;
1N/A for(n += 4; n < 0; n += 1)
1N/A dval /= 10.;
1N/A }
1N/A else
1N/A { dval = 10000.;
1N/A for(n -= 4; n > 0; n -= 1)
1N/A dval *= 10.;
1N/A }
1N/A
1N/A return dval;
1N/A}
1N/A
1N/A#if __STD_C
1N/ASfdouble_t _sfstrtod(reg const char* s, char** retp)
1N/A#else
1N/ASfdouble_t _sfstrtod(s,retp)
1N/Areg char* s; /* string to convert */
1N/Achar** retp; /* to return the remainder of string */
1N/A#endif
1N/A{
1N/A reg int n, c, m;
1N/A reg int mode, fexp, sign, expsign;
1N/A Sfdouble_t dval;
1N/A#if _lib_locale
1N/A int decpoint = 0;
1N/A int thousand = 0;
1N/A SFSETLOCALE(&decpoint,&thousand);
1N/A#else
1N/A#define decpoint '.'
1N/A#endif
1N/A
1N/A /* skip initial blanks */
1N/A while(isspace(*s))
1N/A ++s;
1N/A
1N/A /* get the sign */
1N/A if((sign = (*s == '-')) || *s == '+')
1N/A s += 1;
1N/A
1N/A mode = IPART;
1N/A fexp = expsign = 0;
1N/A dval = 0.;
1N/A while(*s)
1N/A { /* accumulate a handful of the digits */
1N/A for(m = BATCH, n = 0; m > 0; --m, ++s)
1N/A { /* get and process a char */
1N/A c = *s;
1N/A if(isdigit(c))
1N/A n = 10*n + (c - '0');
1N/A else break;
1N/A }
1N/A
1N/A /* number of digits accumulated */
1N/A m = BATCH-m;
1N/A
1N/A if(mode == IPART)
1N/A { /* doing the integer part */
1N/A if(dval == 0.)
1N/A dval = (Sfdouble_t)n;
1N/A else dval = dval*sfpow10(m) + (Sfdouble_t)n;
1N/A }
1N/A else if(mode == FPART)
1N/A { /* doing the fractional part */
1N/A fexp -= m;
1N/A if(n > 0)
1N/A dval += n*sfpow10(fexp);
1N/A }
1N/A else if(n)
1N/A { /* doing the exponent part */
1N/A if(expsign)
1N/A n = -n;
1N/A dval *= sfpow10(n);
1N/A }
1N/A
1N/A if(!c)
1N/A break;
1N/A
1N/A if(m < BATCH)
1N/A { /* detected a non-digit */
1N/A if(c == decpoint)
1N/A { /* start the fractional part or no match */
1N/A if(mode != IPART)
1N/A break;
1N/A mode = FPART;
1N/A s += 1;
1N/A }
1N/A else if(c == 'e' || c == 'E')
1N/A { if(mode == EPART)
1N/A break;
1N/A mode = EPART;
1N/A c = *++s;
1N/A if((expsign = (c == '-')) || c == '+')
1N/A s += 1;
1N/A }
1N/A else break;
1N/A }
1N/A }
1N/A
1N/A if(retp)
1N/A *retp = (char*)s;
1N/A return sign ? -dval : dval;
1N/A}