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