OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [ecos-2.0/] [packages/] [language/] [c/] [libc/] [stdlib/] [v2_0/] [src/] [strtod.cxx] - Blame information for rev 1254

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1254 phoenix
//===========================================================================
2
//
3
//      strtod.cxx
4
//
5
//      ISO String to double-precision floating point conversion
6
//
7
//===========================================================================
8
//####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under
14
// the terms of the GNU General Public License as published by the Free
15
// Software Foundation; either version 2 or (at your option) any later version.
16
//
17
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20
// for more details.
21
//
22
// You should have received a copy of the GNU General Public License along
23
// with eCos; if not, write to the Free Software Foundation, Inc.,
24
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25
//
26
// As a special exception, if other files instantiate templates or use macros
27
// or inline functions from this file, or you compile this file and link it
28
// with other works to produce a work based on this file, this file does not
29
// by itself cause the resulting work to be covered by the GNU General Public
30
// License. However the source code for this file must still be made available
31
// in accordance with section (3) of the GNU General Public License.
32
//
33
// This exception does not invalidate any other reasons why a work based on
34
// this file might be covered by the GNU General Public License.
35
//
36
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37
// at http://sources.redhat.com/ecos/ecos-license/
38
// -------------------------------------------
39
//####ECOSGPLCOPYRIGHTEND####
40
//===========================================================================
41
//#####DESCRIPTIONBEGIN####
42
//
43
// Author(s):    jlarmour
44
// Contributors: 
45
// Date:         2000-04-30
46
// Purpose:     
47
// Description: 
48
// Usage:       
49
//
50
//####DESCRIPTIONEND####
51
//
52
//===========================================================================
53
 
54
// CONFIGURATION
55
 
56
#include <pkgconf/libc_stdlib.h>           // Configuration header
57
 
58
// Include strtod()?
59
#if defined(CYGFUN_LIBC_strtod)
60
 
61
// INCLUDES
62
 
63
#include <cyg/infra/cyg_type.h>     // Common type definitions and support
64
#include <cyg/infra/cyg_trac.h>     // Tracing support
65
#include <cyg/infra/cyg_ass.h>      // Assertion support
66
#include <stddef.h>                 // NULL, wchar_t and size_t from compiler
67
#include <stdlib.h>                 // Main header for stdlib functions
68
#include <ctype.h>                  // isspace() and isdigit()
69
#include <float.h>                  // DBL_MIN_10_EXP and DBL_MAX_10_EXP
70
#include <math.h>                   // HUGE_VAL
71
#include <errno.h>                  // errno
72
 
73
// CONSTANTS
74
 
75
#define MAXE (DBL_MAX_10_EXP)
76
#define MINE (DBL_MIN_10_EXP)
77
 
78
// flags
79
#define SIGN    0x01
80
#define ESIGN   0x02
81
#define DECP    0x04
82
 
83
 
84
// MACROS
85
 
86
#define Ise(c)          ((c == 'e') || (c == 'E') || (c == 'd') || (c == 'D'))
87
#define Issign(c)       ((c == '-') || (c == '+'))
88
#define Val(c)          ((c - '0'))
89
 
90
 
91
// FUNCTIONS
92
 
93
/*
94
 * [atw] multiply 64 bit accumulator by 10 and add digit.
95
 * The KA/CA way to do this should be to use
96
 * a 64-bit integer internally and use "adjust" to
97
 * convert it to float at the end of processing.
98
 */
99
static int
100
ten_mul(double *acc, int digit)
101
{
102
    /* [atw] Crude, but effective (at least on a KB)...
103
     */
104
    *acc *= 10;
105
    *acc += digit;
106
 
107
    return 0;     /* no overflow */
108
} // ten_mul()
109
 
110
 
111
/*
112
 * compute 10**x by successive squaring.
113
 */
114
 
115
static const double
116
exp10(unsigned x)
117
{
118
    static double powtab[] = {1.0,
119
                              10.0,
120
                              100.0,
121
                              1000.0,
122
                              10000.0};
123
 
124
    if (x < (sizeof(powtab)/sizeof(double)))
125
        return powtab[x];
126
    else if (x & 1)
127
        return 10.0 * exp10(x-1);
128
    else
129
        return exp10(x/2) * exp10(x/2);
130
} // exp10()
131
 
132
 
133
/*
134
 * return (*acc) scaled by 10**dexp.
135
 */
136
 
137
static double
138
adjust(double *acc, int dexp, int sign)
139
     /* *acc    the 64 bit accumulator */
140
     /* dexp    decimal exponent       */
141
     /* sign    sign flag              */
142
{
143
    double r;
144
 
145
    if (dexp > MAXE)
146
    {
147
        errno = ERANGE;
148
        return (sign) ? -HUGE_VAL : HUGE_VAL;
149
    }
150
    else if (dexp < MINE)
151
    {
152
        errno = ERANGE;
153
        return 0.0;
154
    }
155
 
156
    r = *acc;
157
    if (sign)
158
        r = -r;
159
    if (dexp==0)
160
        return r;
161
 
162
    if (dexp < 0)
163
        return r / exp10(abs(dexp));
164
    else
165
        return r * exp10(dexp);
166
} // adjust()
167
 
168
 
169
externC double
170
strtod( const char *nptr, char **endptr )
171
{
172
    const char *start=nptr;
173
    double accum = 0.0;
174
    int flags = 0;
175
    int texp  = 0;
176
    int e     = 0;
177
    int conv_done = 0;
178
 
179
    double retval;
180
 
181
    CYG_REPORT_FUNCNAMETYPE( "strtod", "returning %f" );
182
 
183
    CYG_CHECK_DATA_PTR( nptr, "nptr is an invalid pointer!" );
184
 
185
    // endptr is allowed to be NULL, but if it isn't, we check it
186
    if (endptr != NULL)
187
        CYG_CHECK_DATA_PTR( endptr, "endptr is an invalid pointer!" );
188
 
189
    while(isspace(*nptr)) nptr++;
190
    if(*nptr == '\0')
191
    {   /* just leading spaces */
192
        if(endptr != NULL) *endptr = (char *)start;
193
        return 0.0;
194
    }
195
 
196
 
197
    if(Issign(*nptr))
198
    {
199
        if(*nptr == '-') flags = SIGN;
200
        if(*++nptr == '\0')
201
        {   /* "+|-" : should be an error ? */
202
            if(endptr != NULL) *endptr = (char *)start;
203
            return 0.0;
204
        }
205
    }
206
 
207
    for(; (isdigit(*nptr) || (*nptr == '.')); nptr++)
208
    {
209
        conv_done = 1;
210
        if(*nptr == '.')
211
            flags |= DECP;
212
        else
213
        {
214
            if( ten_mul(&accum, Val(*nptr)) ) texp++;
215
            if(flags & DECP) texp--;
216
        }
217
    }
218
 
219
    if(Ise(*nptr))
220
    {
221
        conv_done = 1;
222
        if(*++nptr != '\0') /* skip e|E|d|D */
223
        {  /* ! ([nptr]xxx[.[yyy]]e)  */
224
 
225
            while(isspace(*nptr)) nptr++; /* Ansi allows spaces after e */
226
            if(*nptr != '\0')
227
            { /*  ! ([nptr]xxx[.[yyy]]e[space])  */
228
 
229
                if(Issign(*nptr))
230
                    if(*nptr++ == '-') flags |= ESIGN;
231
 
232
                if(*nptr != '\0')
233
                { /*  ! ([nptr]xxx[.[yyy]]e[nptr])  -- error?? */
234
 
235
                    for(; isdigit(*nptr); nptr++)
236
                        if (e < MAXE) /* prevent from grossly overflowing */
237
                            e = e*10 + Val(*nptr);
238
 
239
                    /* dont care what comes after this */
240
                    if(flags & ESIGN)
241
                        texp -= e;
242
                    else
243
                        texp += e;
244
                }
245
            }
246
        }
247
    }
248
 
249
    if(endptr != NULL)
250
        *endptr = (char *)((conv_done) ? nptr : start);
251
 
252
    retval = adjust(&accum, (int)texp, (int)(flags & SIGN));
253
 
254
 
255
    CYG_REPORT_RETVAL( retval );
256
 
257
    return retval;
258
} // strtod()
259
 
260
 
261
#endif // if defined(CYGFUN_LIBC_strtod)
262
 
263
// EOF strtod.cxx

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.