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