add missing macros and declarations
[mw/micromonitor-lm32.git] / umon_main / target / glib / strtod.c
1 //
2 // strtod.c
3 //
4 // Convert string to double 
5 //
6 // Copyright (C) 2002 Michael Ringgaard. All rights reserved.
7 //
8 // Redistribution and use in source and binary forms, with or without
9 // modification, are permitted provided that the following conditions
10 // are met:
11 // 
12 // 1. Redistributions of source code must retain the above copyright 
13 //    notice, this list of conditions and the following disclaimer.  
14 // 2. Redistributions in binary form must reproduce the above copyright
15 //    notice, this list of conditions and the following disclaimer in the
16 //    documentation and/or other materials provided with the distribution.  
17 // 3. Neither the name of the project nor the names of its contributors
18 //    may be used to endorse or promote products derived from this software
19 //    without specific prior written permission. 
20 // 
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 // ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
25 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
31 // SUCH DAMAGE.
32 // 
33
34 #include <ctype.h>
35 #include <float.h>
36 #include "genlib.h"
37
38 double strtod(const char *str, char **endptr)
39 {
40   double number;
41   int exponent;
42   int negative;
43   char *p = (char *) str;
44   double p10;
45   int n;
46   int num_digits;
47   int num_decimals;
48
49   // Skip leading whitespace
50   while (isspace(*p)) p++;
51
52   // Handle optional sign
53   negative = 0;
54   switch (*p) 
55   {             
56     case '-': negative = 1; // Fall through to increment position
57     case '+': p++;
58   }
59
60   number = 0.;
61   exponent = 0;
62   num_digits = 0;
63   num_decimals = 0;
64
65   // Process string of digits
66   while (isdigit(*p))
67   {
68     number = number * 10. + (*p - '0');
69     p++;
70     num_digits++;
71   }
72
73   // Process decimal part
74   if (*p == '.') 
75   {
76     p++;
77
78     while (isdigit(*p))
79     {
80       number = number * 10. + (*p - '0');
81       p++;
82       num_digits++;
83       num_decimals++;
84     }
85
86     exponent -= num_decimals;
87   }
88
89   if (num_digits == 0)
90   {
91     //errno = ERANGE;
92     return 0.0;
93   }
94
95   // Correct for sign
96   if (negative) number = -number;
97
98   // Process an exponent string
99   if (*p == 'e' || *p == 'E') 
100   {
101     // Handle optional sign
102     negative = 0;
103     switch(*++p) 
104     {   
105       case '-': negative = 1;   // Fall through to increment pos
106       case '+': p++;
107     }
108
109     // Process string of digits
110     n = 0;
111     while (isdigit(*p)) 
112     {   
113       n = n * 10 + (*p - '0');
114       p++;
115     }
116
117     if (negative) 
118       exponent -= n;
119     else
120       exponent += n;
121   }
122
123   if (exponent < DBL_MIN_EXP  || exponent > DBL_MAX_EXP)
124   {
125     //errno = ERANGE;
126     return HUGE_VAL;
127   }
128
129   // Scale the result
130   p10 = 10.;
131   n = exponent;
132   if (n < 0) n = -n;
133   while (n) 
134   {
135     if (n & 1) 
136     {
137       if (exponent < 0)
138         number /= p10;
139       else
140         number *= p10;
141     }
142     n >>= 1;
143     p10 *= p10;
144   }
145
146   //if (number == HUGE_VAL) errno = ERANGE;
147   if (endptr) *endptr = p;
148
149   return number;
150 }
151
152 double atof(const char *str)
153 {
154   return strtod(str, NULL);
155 }
156