github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/src/lib9/fmt/charstod.c (about)

     1  /*
     2   * The authors of this software are Rob Pike and Ken Thompson,
     3   * with contributions from Mike Burrows and Sean Dorward.
     4   *
     5   *     Copyright (c) 2002-2006 by Lucent Technologies.
     6   *     Portions Copyright (c) 2004 Google Inc.
     7   * 
     8   * Permission to use, copy, modify, and distribute this software for any
     9   * purpose without fee is hereby granted, provided that this entire notice
    10   * is included in all copies of any software which is or includes a copy
    11   * or modification of this software and in all copies of the supporting
    12   * documentation for such software.
    13   * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
    14   * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 
    15   * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 
    16   * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
    17   */
    18  
    19  #include <u.h>
    20  #include <libc.h>
    21  #include "fmtdef.h"
    22  
    23  /*
    24   * Reads a floating-point number by interpreting successive characters
    25   * returned by (*f)(vp).  The last call it makes to f terminates the
    26   * scan, so is not a character in the number.  It may therefore be
    27   * necessary to back up the input stream up one byte after calling charstod.
    28   */
    29  
    30  double
    31  fmtcharstod(int(*f)(void*), void *vp)
    32  {
    33  	double num, dem;
    34  	int neg, eneg, dig, exp, c;
    35  
    36  	num = 0;
    37  	neg = 0;
    38  	dig = 0;
    39  	exp = 0;
    40  	eneg = 0;
    41  
    42  	c = (*f)(vp);
    43  	while(c == ' ' || c == '\t')
    44  		c = (*f)(vp);
    45  	if(c == '-' || c == '+'){
    46  		if(c == '-')
    47  			neg = 1;
    48  		c = (*f)(vp);
    49  	}
    50  	while(c >= '0' && c <= '9'){
    51  		num = num*10 + c-'0';
    52  		c = (*f)(vp);
    53  	}
    54  	if(c == '.')
    55  		c = (*f)(vp);
    56  	while(c >= '0' && c <= '9'){
    57  		num = num*10 + c-'0';
    58  		dig++;
    59  		c = (*f)(vp);
    60  	}
    61  	if(c == 'e' || c == 'E'){
    62  		c = (*f)(vp);
    63  		if(c == '-' || c == '+'){
    64  			if(c == '-'){
    65  				dig = -dig;
    66  				eneg = 1;
    67  			}
    68  			c = (*f)(vp);
    69  		}
    70  		while(c >= '0' && c <= '9'){
    71  			exp = exp*10 + c-'0';
    72  			c = (*f)(vp);
    73  		}
    74  	}
    75  	exp -= dig;
    76  	if(exp < 0){
    77  		exp = -exp;
    78  		eneg = !eneg;
    79  	}
    80  	dem = __fmtpow10(exp);
    81  	if(eneg)
    82  		num /= dem;
    83  	else
    84  		num *= dem;
    85  	if(neg)
    86  		return -num;
    87  	return num;
    88  }