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