-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathatofloat.c
100 lines (92 loc) · 3.53 KB
/
atofloat.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/****************************************************************************
*
* This code is Public Domain.
*
* ========================================================================
*
* Description: string to float conversion
*
****************************************************************************/
#include <float.h>
#include <math.h>
#include "globals.h"
#include "tbyte.h"
#include "atofloat.h"
#define USESTRTOF 0 /* 0=use strtod() and convert "manually", 1=use strtof() */
extern void myatoi128( const char *, uint_64[], int, int );
/* it's ensured that 'out' points to a buffer with a size of at least 16 */
void atofloat( void *out, const char *inp, unsigned size, bool negative, uint_8 ftype )
/*************************************************************************************/
{
//const char *inp;
double double_value;
float float_value;
/* v2.04: accept and handle 'real number designator' */
if ( ftype ) {
uint_8 *p;
uint_8 *end;
/* convert hex string with float "designator" to float.
* this is supposed to work with real4, real8 and real10.
* v2.11: use myatoi128() for conversion ( this function
* always initializes and reads a 16-byte number ).
* then check that the number fits in the variable.
*/
myatoi128( inp, (uint_64 *)out, 16, strlen( inp ) - 1 );
for ( p = (uint_8 *)out + size, end = (uint_8 *)out + 16; p < end; p++ )
if ( *p != NULLC ) {
EmitErr( INVALID_DATA_INITIALIZER, inp );
break;
}
} else {
switch ( size ) {
case 4:
#if USESTRTOF
errno = 0;
float_value = strtof( inp, NULL );
if ( errno == ERANGE ) {
DebugMsg(("atofloat(%s, 4): magnitude too large\n", inp ));
EmitErr( MAGNITUDE_TOO_LARGE_FOR_SPECIFIED_SIZE );
}
if( negative )
float_value *= -1;
#else
double_value = strtod( inp, NULL );
/* v2.06: check FLT_MAX added */
/* v2.11: check FLT_MIN (min positive value) added */
//if ( double_value > FLT_MAX )
if ( double_value > FLT_MAX || ( double_value < FLT_MIN && double_value != 0 ) ) {
DebugMsg(("atofloat(%s, 4): magnitude too large; FLT_MAX=%e FLT_MIN=%e\n", inp, FLT_MAX, FLT_MIN ));
EmitErr( MAGNITUDE_TOO_LARGE_FOR_SPECIFIED_SIZE );
}
if( negative )
double_value *= -1;
float_value = double_value;
#endif
*(float *)out = float_value;
break;
case 8:
errno = 0; /* v2.11: init errno; errno is set on over- and under-flow */
double_value = strtod( inp, NULL );
/* v2.11: check added */
if ( errno == ERANGE ) {
DebugMsg(("atofloat(%s, 8): magnitude too large\n", inp ));
EmitErr( MAGNITUDE_TOO_LARGE_FOR_SPECIFIED_SIZE );
}
if( negative )
double_value *= -1;
*(double *)out = double_value;
break;
case 10:
strtotb( inp, (struct TB_LD *)out, negative );
break;
default:
/* sizes != 4,8 or 10 aren't accepted.
* Masm ignores silently, JWasm also unless -W4 is set.
*/
if ( Parse_Pass == PASS_1 )
EmitWarn( 4, FP_INITIALIZER_IGNORED );
memset( (char *)out, 0, size );
}
}
return;
}