msvcrt: Add _atoflt and _atoflt_l implementations.
This commit is contained in:
parent
9771ad8ca7
commit
ad6bc94491
|
@ -505,8 +505,8 @@
|
||||||
@ stub _atodbl
|
@ stub _atodbl
|
||||||
@ stub _atodbl_l
|
@ stub _atodbl_l
|
||||||
@ cdecl _atof_l(str ptr) msvcrt._atof_l
|
@ cdecl _atof_l(str ptr) msvcrt._atof_l
|
||||||
@ stub _atoflt
|
@ cdecl _atoflt(ptr str) msvcr90._atoflt
|
||||||
@ stub _atoflt_l
|
@ cdecl _atoflt_l(ptr str ptr) msvcrt._atoflt_l
|
||||||
@ cdecl -ret64 _atoi64(str) msvcrt._atoi64
|
@ cdecl -ret64 _atoi64(str) msvcrt._atoi64
|
||||||
@ stub _atoi64_l
|
@ stub _atoi64_l
|
||||||
@ stub _atoi_l
|
@ stub _atoi_l
|
||||||
|
|
|
@ -344,8 +344,8 @@
|
||||||
@ stub _atodbl
|
@ stub _atodbl
|
||||||
@ stub _atodbl_l
|
@ stub _atodbl_l
|
||||||
@ cdecl _atof_l(str ptr) msvcrt._atof_l
|
@ cdecl _atof_l(str ptr) msvcrt._atof_l
|
||||||
@ stub _atoflt
|
@ cdecl _atoflt(ptr str) msvcr90._atoflt
|
||||||
@ stub _atoflt_l
|
@ cdecl _atoflt_l(ptr str ptr) msvcrt._atoflt_l
|
||||||
@ cdecl -ret64 _atoi64(str) msvcrt._atoi64
|
@ cdecl -ret64 _atoi64(str) msvcrt._atoi64
|
||||||
@ stub _atoi64_l
|
@ stub _atoi64_l
|
||||||
@ stub _atoi_l
|
@ stub _atoi_l
|
||||||
|
|
|
@ -192,3 +192,11 @@ int CDECL _wstat64i32(const wchar_t *path, struct _stat64i32 *buf)
|
||||||
msvcrt_stat64_to_stat64i32(&buf64, buf);
|
msvcrt_stat64_to_stat64i32(&buf64, buf);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* _atoflt (MSVCR90.@)
|
||||||
|
*/
|
||||||
|
int CDECL _atoflt( _CRT_FLOAT *value, char *str )
|
||||||
|
{
|
||||||
|
return _atoflt_l( value, str, NULL );
|
||||||
|
}
|
||||||
|
|
|
@ -336,8 +336,8 @@
|
||||||
@ stub _atodbl
|
@ stub _atodbl
|
||||||
@ stub _atodbl_l
|
@ stub _atodbl_l
|
||||||
@ cdecl _atof_l(str ptr) msvcrt._atof_l
|
@ cdecl _atof_l(str ptr) msvcrt._atof_l
|
||||||
@ stub _atoflt
|
@ cdecl _atoflt(ptr str)
|
||||||
@ stub _atoflt_l
|
@ cdecl _atoflt_l(ptr str ptr) msvcrt._atoflt_l
|
||||||
@ cdecl -ret64 _atoi64(str) msvcrt._atoi64
|
@ cdecl -ret64 _atoi64(str) msvcrt._atoi64
|
||||||
@ stub _atoi64_l
|
@ stub _atoi64_l
|
||||||
@ stub _atoi_l
|
@ stub _atoi_l
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#include <windef.h>
|
#include <windef.h>
|
||||||
#include <winbase.h>
|
#include <winbase.h>
|
||||||
|
@ -67,12 +68,18 @@ static errno_t (__cdecl *p_itoa_s)(int,char*,size_t,int);
|
||||||
static int (__cdecl *p_wcsncat_s)(wchar_t *dst, size_t elem, const wchar_t *src, size_t count);
|
static int (__cdecl *p_wcsncat_s)(wchar_t *dst, size_t elem, const wchar_t *src, size_t count);
|
||||||
static void (__cdecl *p_qsort_s)(void *, size_t, size_t, int (__cdecl *)(void *, const void *, const void *), void *);
|
static void (__cdecl *p_qsort_s)(void *, size_t, size_t, int (__cdecl *)(void *, const void *, const void *), void *);
|
||||||
static int (__cdecl *p_controlfp_s)(unsigned int *, unsigned int, unsigned int);
|
static int (__cdecl *p_controlfp_s)(unsigned int *, unsigned int, unsigned int);
|
||||||
|
static int (__cdecl *p_atoflt)(_CRT_FLOAT *, char *);
|
||||||
|
|
||||||
static void* (WINAPI *pEncodePointer)(void *);
|
static void* (WINAPI *pEncodePointer)(void *);
|
||||||
|
|
||||||
static int cb_called[4];
|
static int cb_called[4];
|
||||||
static int g_qsort_s_context_counter;
|
static int g_qsort_s_context_counter;
|
||||||
|
|
||||||
|
static inline int almost_equal_f(float f1, float f2)
|
||||||
|
{
|
||||||
|
return f1-f2 > -1e-30 && f1-f2 < 1e-30;
|
||||||
|
}
|
||||||
|
|
||||||
/* ########## */
|
/* ########## */
|
||||||
|
|
||||||
static void __cdecl test_invalid_parameter_handler(const wchar_t *expression,
|
static void __cdecl test_invalid_parameter_handler(const wchar_t *expression,
|
||||||
|
@ -617,6 +624,62 @@ static void test_controlfp_s(void)
|
||||||
ok( cur != 0xdeadbeef, "value not set\n" );
|
ok( cur != 0xdeadbeef, "value not set\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const char *str;
|
||||||
|
float flt;
|
||||||
|
int ret;
|
||||||
|
} _atoflt_test;
|
||||||
|
|
||||||
|
static const _atoflt_test _atoflt_testdata[] = {
|
||||||
|
{ "12.1", 12.1, 0 },
|
||||||
|
{ "-13.721", -13.721, 0 },
|
||||||
|
{ "INF", 0.0, 0 },
|
||||||
|
{ ".21e12", 0.21e12, 0 },
|
||||||
|
{ "214353e-3", 214.353, 0 },
|
||||||
|
{ "1d9999999999999999999", 0.0, _OVERFLOW },
|
||||||
|
{ " d10", 0.0, 0 },
|
||||||
|
/* more significant digits */
|
||||||
|
{ "1.23456789", 1.23456789, 0 },
|
||||||
|
{ "1.23456789e1", 12.3456789, 0 },
|
||||||
|
{ "1e39", 0.0, _OVERFLOW },
|
||||||
|
{ "1e-39", 0.0, _UNDERFLOW },
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static void test__atoflt(void)
|
||||||
|
{
|
||||||
|
_CRT_FLOAT flt;
|
||||||
|
int ret, i = 0;
|
||||||
|
|
||||||
|
if (!p_atoflt)
|
||||||
|
{
|
||||||
|
win_skip("_atoflt not found\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0)
|
||||||
|
{
|
||||||
|
/* crashes on native */
|
||||||
|
ret = p_atoflt(NULL, NULL);
|
||||||
|
ret = p_atoflt(NULL, (char*)_atoflt_testdata[0].str);
|
||||||
|
ret = p_atoflt(&flt, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (_atoflt_testdata[i].str)
|
||||||
|
{
|
||||||
|
ret = p_atoflt(&flt, (char*)_atoflt_testdata[i].str);
|
||||||
|
ok(ret == _atoflt_testdata[i].ret, "got ret %d, expected ret %d, for %s\n", ret,
|
||||||
|
_atoflt_testdata[i].ret, _atoflt_testdata[i].str);
|
||||||
|
|
||||||
|
if (ret == 0)
|
||||||
|
ok(almost_equal_f(flt.f, _atoflt_testdata[i].flt), "got %f, expected %f, for %s\n", flt.f,
|
||||||
|
_atoflt_testdata[i].flt, _atoflt_testdata[i].str);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
START_TEST(msvcr90)
|
START_TEST(msvcr90)
|
||||||
{
|
{
|
||||||
HMODULE hcrt;
|
HMODULE hcrt;
|
||||||
|
@ -648,6 +711,7 @@ START_TEST(msvcr90)
|
||||||
p_wcsncat_s = (void *)GetProcAddress( hcrt,"wcsncat_s" );
|
p_wcsncat_s = (void *)GetProcAddress( hcrt,"wcsncat_s" );
|
||||||
p_qsort_s = (void *) GetProcAddress(hcrt, "qsort_s");
|
p_qsort_s = (void *) GetProcAddress(hcrt, "qsort_s");
|
||||||
p_controlfp_s = (void *) GetProcAddress(hcrt, "_controlfp_s");
|
p_controlfp_s = (void *) GetProcAddress(hcrt, "_controlfp_s");
|
||||||
|
p_atoflt = (void* )GetProcAddress(hcrt, "_atoflt");
|
||||||
|
|
||||||
hkernel32 = GetModuleHandleA("kernel32.dll");
|
hkernel32 = GetModuleHandleA("kernel32.dll");
|
||||||
pEncodePointer = (void *) GetProcAddress(hkernel32, "EncodePointer");
|
pEncodePointer = (void *) GetProcAddress(hkernel32, "EncodePointer");
|
||||||
|
@ -660,4 +724,5 @@ START_TEST(msvcr90)
|
||||||
test_wcsncat_s();
|
test_wcsncat_s();
|
||||||
test_qsort_s();
|
test_qsort_s();
|
||||||
test_controlfp_s();
|
test_controlfp_s();
|
||||||
|
test__atoflt();
|
||||||
}
|
}
|
||||||
|
|
|
@ -890,4 +890,12 @@ typedef struct pf_output_t
|
||||||
int pf_vsnprintf( pf_output *out, const WCHAR *format,
|
int pf_vsnprintf( pf_output *out, const WCHAR *format,
|
||||||
MSVCRT__locale_t locale, BOOL valid, __ms_va_list valist );
|
MSVCRT__locale_t locale, BOOL valid, __ms_va_list valist );
|
||||||
|
|
||||||
|
#define MSVCRT__OVERFLOW 3
|
||||||
|
#define MSVCRT__UNDERFLOW 4
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
float f;
|
||||||
|
} MSVCRT__CRT_FLOAT;
|
||||||
|
|
||||||
#endif /* __WINE_MSVCRT_H */
|
#endif /* __WINE_MSVCRT_H */
|
||||||
|
|
|
@ -303,7 +303,7 @@
|
||||||
@ stub _atodbl #(ptr str)
|
@ stub _atodbl #(ptr str)
|
||||||
# stub _atodbl_l
|
# stub _atodbl_l
|
||||||
@ cdecl _atof_l(str ptr) MSVCRT__atof_l
|
@ cdecl _atof_l(str ptr) MSVCRT__atof_l
|
||||||
# stub _atoflt_l
|
@ cdecl _atoflt_l(ptr str ptr) MSVCRT__atoflt_l
|
||||||
@ cdecl -ret64 _atoi64(str) ntdll._atoi64
|
@ cdecl -ret64 _atoi64(str) ntdll._atoi64
|
||||||
# stub _atoi64_l
|
# stub _atoi64_l
|
||||||
# stub _atoi_l
|
# stub _atoi_l
|
||||||
|
|
|
@ -332,6 +332,111 @@ double CDECL MSVCRT__atof_l( const char *str, MSVCRT__locale_t locale)
|
||||||
return MSVCRT_strtod_l(str, NULL, locale);
|
return MSVCRT_strtod_l(str, NULL, locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
* _atoflt_l (MSVCRT.@)
|
||||||
|
*/
|
||||||
|
int CDECL MSVCRT__atoflt_l( MSVCRT__CRT_FLOAT *value, char *str, MSVCRT__locale_t locale)
|
||||||
|
{
|
||||||
|
unsigned __int64 d=0, hlp;
|
||||||
|
unsigned fpcontrol;
|
||||||
|
int exp=0, sign=1;
|
||||||
|
const char *p;
|
||||||
|
int ret=0;
|
||||||
|
BOOL found_digit = FALSE;
|
||||||
|
|
||||||
|
if(!locale)
|
||||||
|
locale = get_locale();
|
||||||
|
|
||||||
|
/* FIXME: use *_l functions */
|
||||||
|
p = str;
|
||||||
|
while(isspace(*p))
|
||||||
|
p++;
|
||||||
|
|
||||||
|
if(*p == '-') {
|
||||||
|
sign = -1;
|
||||||
|
p++;
|
||||||
|
} else if(*p == '+')
|
||||||
|
p++;
|
||||||
|
|
||||||
|
while(isdigit(*p)) {
|
||||||
|
found_digit = TRUE;
|
||||||
|
hlp = d*10+*(p++)-'0';
|
||||||
|
if(d>MSVCRT_UI64_MAX/10 || hlp<d) {
|
||||||
|
exp++;
|
||||||
|
break;
|
||||||
|
} else
|
||||||
|
d = hlp;
|
||||||
|
}
|
||||||
|
while(isdigit(*p)) {
|
||||||
|
exp++;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*p == *locale->locinfo->lconv->decimal_point)
|
||||||
|
p++;
|
||||||
|
|
||||||
|
while(isdigit(*p)) {
|
||||||
|
found_digit = TRUE;
|
||||||
|
hlp = d*10+*(p++)-'0';
|
||||||
|
if(d>MSVCRT_UI64_MAX/10 || hlp<d)
|
||||||
|
break;
|
||||||
|
|
||||||
|
d = hlp;
|
||||||
|
exp--;
|
||||||
|
}
|
||||||
|
while(isdigit(*p))
|
||||||
|
p++;
|
||||||
|
|
||||||
|
if(!found_digit) {
|
||||||
|
value->f = 0.0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*p=='e' || *p=='E' || *p=='d' || *p=='D') {
|
||||||
|
int e=0, s=1;
|
||||||
|
|
||||||
|
p++;
|
||||||
|
if(*p == '-') {
|
||||||
|
s = -1;
|
||||||
|
p++;
|
||||||
|
} else if(*p == '+')
|
||||||
|
p++;
|
||||||
|
|
||||||
|
if(isdigit(*p)) {
|
||||||
|
while(isdigit(*p)) {
|
||||||
|
if(e>INT_MAX/10 || (e=e*10+*p-'0')<0)
|
||||||
|
e = INT_MAX;
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
e *= s;
|
||||||
|
|
||||||
|
if(exp<0 && e<0 && exp+e>=0) exp = INT_MIN;
|
||||||
|
else if(exp>0 && e>0 && exp+e<0) exp = INT_MAX;
|
||||||
|
else exp += e;
|
||||||
|
} else {
|
||||||
|
if(*p=='-' || *p=='+')
|
||||||
|
p--;
|
||||||
|
p--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fpcontrol = _control87(0, 0);
|
||||||
|
_control87(MSVCRT__EM_DENORMAL|MSVCRT__EM_INVALID|MSVCRT__EM_ZERODIVIDE
|
||||||
|
|MSVCRT__EM_OVERFLOW|MSVCRT__EM_UNDERFLOW|MSVCRT__EM_INEXACT, 0xffffffff);
|
||||||
|
|
||||||
|
if(exp>0)
|
||||||
|
value->f = (float)sign*d*powf(10, exp);
|
||||||
|
else
|
||||||
|
value->f = (float)sign*d/powf(10, -exp);
|
||||||
|
|
||||||
|
_control87(fpcontrol, 0xffffffff);
|
||||||
|
|
||||||
|
if((d && value->f==0.0) || isinf(value->f))
|
||||||
|
ret = exp > 0 ? MSVCRT__OVERFLOW : MSVCRT__UNDERFLOW;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
* strcoll (MSVCRT.@)
|
* strcoll (MSVCRT.@)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -260,6 +260,7 @@ static void test_structs(void)
|
||||||
CHECK_FIELD(_stat64, st_atime);
|
CHECK_FIELD(_stat64, st_atime);
|
||||||
CHECK_FIELD(_stat64, st_mtime);
|
CHECK_FIELD(_stat64, st_mtime);
|
||||||
CHECK_FIELD(_stat64, st_ctime);
|
CHECK_FIELD(_stat64, st_ctime);
|
||||||
|
CHECK_SIZE(_CRT_FLOAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************* Checking defines ***************/
|
/************* Checking defines ***************/
|
||||||
|
@ -450,6 +451,8 @@ static void test_defines(void)
|
||||||
CHECK_DEF(_DN_FLUSH_OPERANDS_SAVE_RESULTS);
|
CHECK_DEF(_DN_FLUSH_OPERANDS_SAVE_RESULTS);
|
||||||
CHECK_DEF(_DN_SAVE_OPERANDS_FLUSH_RESULTS);
|
CHECK_DEF(_DN_SAVE_OPERANDS_FLUSH_RESULTS);
|
||||||
CHECK_DEF(_EM_AMBIGUOUS);
|
CHECK_DEF(_EM_AMBIGUOUS);
|
||||||
|
CHECK_DEF(_OVERFLOW);
|
||||||
|
CHECK_DEF(_UNDERFLOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __WINE_USE_MSVCRT */
|
#endif /* __WINE_USE_MSVCRT */
|
||||||
|
|
|
@ -18,6 +18,9 @@
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef __WINE_CRTDEFS_H
|
||||||
|
#define __WINE_CRTDEFS_H
|
||||||
|
|
||||||
#ifndef __WINE_USE_MSVCRT
|
#ifndef __WINE_USE_MSVCRT
|
||||||
#define __WINE_USE_MSVCRT
|
#define __WINE_USE_MSVCRT
|
||||||
#endif
|
#endif
|
||||||
|
@ -181,3 +184,54 @@ typedef unsigned short wctype_t;
|
||||||
typedef int errno_t;
|
typedef int errno_t;
|
||||||
#define _ERRNO_T_DEFINED
|
#define _ERRNO_T_DEFINED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct threadlocaleinfostruct;
|
||||||
|
struct threadmbcinfostruct;
|
||||||
|
typedef struct threadlocaleinfostruct *pthreadlocinfo;
|
||||||
|
typedef struct threadmbcinfostruct *pthreadmbcinfo;
|
||||||
|
|
||||||
|
typedef struct localeinfo_struct
|
||||||
|
{
|
||||||
|
pthreadlocinfo locinfo;
|
||||||
|
pthreadmbcinfo mbcinfo;
|
||||||
|
} _locale_tstruct, *_locale_t;
|
||||||
|
|
||||||
|
#ifndef _TAGLC_ID_DEFINED
|
||||||
|
typedef struct tagLC_ID {
|
||||||
|
unsigned short wLanguage;
|
||||||
|
unsigned short wCountry;
|
||||||
|
unsigned short wCodePage;
|
||||||
|
} LC_ID, *LPLC_ID;
|
||||||
|
#define _TAGLC_ID_DEFINED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _THREADLOCALEINFO
|
||||||
|
typedef struct threadlocaleinfostruct {
|
||||||
|
int refcount;
|
||||||
|
unsigned int lc_codepage;
|
||||||
|
unsigned int lc_collate_cp;
|
||||||
|
unsigned long lc_handle[6];
|
||||||
|
LC_ID lc_id[6];
|
||||||
|
struct {
|
||||||
|
char *locale;
|
||||||
|
wchar_t *wlocale;
|
||||||
|
int *refcount;
|
||||||
|
int *wrefcount;
|
||||||
|
} lc_category[6];
|
||||||
|
int lc_clike;
|
||||||
|
int mb_cur_max;
|
||||||
|
int *lconv_intl_refcount;
|
||||||
|
int *lconv_num_refcount;
|
||||||
|
int *lconv_mon_refcount;
|
||||||
|
struct lconv *lconv;
|
||||||
|
int *ctype1_refcount;
|
||||||
|
unsigned short *ctype1;
|
||||||
|
const unsigned short *pctype;
|
||||||
|
const unsigned char *pclmap;
|
||||||
|
const unsigned char *pcumap;
|
||||||
|
struct __lc_time_data *lc_time_curr;
|
||||||
|
} threadlocinfo;
|
||||||
|
#define _THREADLOCALEINFO
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __WINE_CRTDEFS_H */
|
||||||
|
|
|
@ -138,6 +138,7 @@ typedef int (__cdecl *_onexit_t)(void);
|
||||||
|
|
||||||
int __cdecl _atodbl(_CRT_DOUBLE*,char*);
|
int __cdecl _atodbl(_CRT_DOUBLE*,char*);
|
||||||
int __cdecl _atoflt(_CRT_FLOAT*,char*);
|
int __cdecl _atoflt(_CRT_FLOAT*,char*);
|
||||||
|
int __cdecl _atoflt_l(_CRT_FLOAT*,char*,_locale_t);
|
||||||
__int64 __cdecl _atoi64(const char*);
|
__int64 __cdecl _atoi64(const char*);
|
||||||
long double __cdecl _atold(const char*);
|
long double __cdecl _atold(const char*);
|
||||||
int __cdecl _atoldbl(_LDOUBLE*,char*);
|
int __cdecl _atoldbl(_LDOUBLE*,char*);
|
||||||
|
|
Loading…
Reference in New Issue