1*0d601874SDavid du Colombier /* 2*0d601874SDavid du Colombier * The authors of this software are Rob Pike and Ken Thompson. 3*0d601874SDavid du Colombier * Copyright (c) 2002 by Lucent Technologies. 4*0d601874SDavid du Colombier * Permission to use, copy, modify, and distribute this software for any 5*0d601874SDavid du Colombier * purpose without fee is hereby granted, provided that this entire notice 6*0d601874SDavid du Colombier * is included in all copies of any software which is or includes a copy 7*0d601874SDavid du Colombier * or modification of this software and in all copies of the supporting 8*0d601874SDavid du Colombier * documentation for such software. 9*0d601874SDavid du Colombier * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED 10*0d601874SDavid du Colombier * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE 11*0d601874SDavid du Colombier * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY 12*0d601874SDavid du Colombier * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. 13*0d601874SDavid du Colombier */ 148ccd4a63SDavid du Colombier #include <u.h> 158ccd4a63SDavid du Colombier #include <libc.h> 16*0d601874SDavid du Colombier #include "fmtdef.h" 178ccd4a63SDavid du Colombier 188ccd4a63SDavid du Colombier /* 198ccd4a63SDavid du Colombier * Reads a floating-point number by interpreting successive characters 208ccd4a63SDavid du Colombier * returned by (*f)(vp). The last call it makes to f terminates the 218ccd4a63SDavid du Colombier * scan, so is not a character in the number. It may therefore be 228ccd4a63SDavid du Colombier * necessary to back up the input stream up one byte after calling charstod. 238ccd4a63SDavid du Colombier */ 248ccd4a63SDavid du Colombier 258ccd4a63SDavid du Colombier double 26*0d601874SDavid du Colombier fmtcharstod(int(*f)(void*), void *vp) 278ccd4a63SDavid du Colombier { 28*0d601874SDavid du Colombier double num, dem; 29*0d601874SDavid du Colombier int neg, eneg, dig, exp, c; 308ccd4a63SDavid du Colombier 31*0d601874SDavid du Colombier num = 0; 32*0d601874SDavid du Colombier neg = 0; 33*0d601874SDavid du Colombier dig = 0; 34*0d601874SDavid du Colombier exp = 0; 35*0d601874SDavid du Colombier eneg = 0; 36*0d601874SDavid du Colombier 378ccd4a63SDavid du Colombier c = (*f)(vp); 388ccd4a63SDavid du Colombier while(c == ' ' || c == '\t') 398ccd4a63SDavid du Colombier c = (*f)(vp); 408ccd4a63SDavid du Colombier if(c == '-' || c == '+'){ 41*0d601874SDavid du Colombier if(c == '-') 42*0d601874SDavid du Colombier neg = 1; 43*0d601874SDavid du Colombier c = (*f)(vp); 448ccd4a63SDavid du Colombier } 458ccd4a63SDavid du Colombier while(c >= '0' && c <= '9'){ 46*0d601874SDavid du Colombier num = num*10 + c-'0'; 47*0d601874SDavid du Colombier c = (*f)(vp); 488ccd4a63SDavid du Colombier } 49*0d601874SDavid du Colombier if(c == '.') 50*0d601874SDavid du Colombier c = (*f)(vp); 518ccd4a63SDavid du Colombier while(c >= '0' && c <= '9'){ 52*0d601874SDavid du Colombier num = num*10 + c-'0'; 53*0d601874SDavid du Colombier dig++; 54*0d601874SDavid du Colombier c = (*f)(vp); 558ccd4a63SDavid du Colombier } 56*0d601874SDavid du Colombier if(c == 'e' || c == 'E'){ 57*0d601874SDavid du Colombier c = (*f)(vp); 588ccd4a63SDavid du Colombier if(c == '-' || c == '+'){ 59*0d601874SDavid du Colombier if(c == '-'){ 60*0d601874SDavid du Colombier dig = -dig; 61*0d601874SDavid du Colombier eneg = 1; 62*0d601874SDavid du Colombier } 63*0d601874SDavid du Colombier c = (*f)(vp); 648ccd4a63SDavid du Colombier } 658ccd4a63SDavid du Colombier while(c >= '0' && c <= '9'){ 66*0d601874SDavid du Colombier exp = exp*10 + c-'0'; 67*0d601874SDavid du Colombier c = (*f)(vp); 688ccd4a63SDavid du Colombier } 698ccd4a63SDavid du Colombier } 70*0d601874SDavid du Colombier exp -= dig; 71*0d601874SDavid du Colombier if(exp < 0){ 72*0d601874SDavid du Colombier exp = -exp; 73*0d601874SDavid du Colombier eneg = !eneg; 74*0d601874SDavid du Colombier } 75*0d601874SDavid du Colombier dem = __fmtpow10(exp); 76*0d601874SDavid du Colombier if(eneg) 77*0d601874SDavid du Colombier num /= dem; 78*0d601874SDavid du Colombier else 79*0d601874SDavid du Colombier num *= dem; 80*0d601874SDavid du Colombier if(neg) 81*0d601874SDavid du Colombier return -num; 82*0d601874SDavid du Colombier return num; 838ccd4a63SDavid du Colombier } 84