Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
4aee4c7d
Commit
4aee4c7d
authored
May 14, 2010
by
Piotr Caban
Committed by
Alexandre Julliard
May 17, 2010
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
msvcrt: Added $I10_OUTPUT implementation.
parent
aff0eac2
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
186 additions
and
13 deletions
+186
-13
main.c
dlls/msvcrt/main.c
+0
-12
msvcrt.spec
dlls/msvcrt/msvcrt.spec
+1
-1
string.c
dlls/msvcrt/string.c
+96
-0
misc.c
dlls/msvcrt/tests/misc.c
+89
-0
No files found.
dlls/msvcrt/main.c
View file @
4aee4c7d
...
...
@@ -123,15 +123,3 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
}
return
TRUE
;
}
/*********************************************************************
* $I10_OUTPUT (MSVCRT.@)
* Function not really understood but needed to make the DLL work
*/
void
CDECL
MSVCRT_I10_OUTPUT
(
void
)
{
/* FIXME: This is probably data, not a function */
/* no it is a function. I10 is an Int of 10 bytes */
/* also known as 80 bit floating point (long double */
/* for some compilers, not MSVC) */
}
dlls/msvcrt/msvcrt.spec
View file @
4aee4c7d
# msvcrt.dll - MS VC++ Run Time Library
@ cdecl
$I10_OUTPUT(
) MSVCRT_I10_OUTPUT
@ cdecl
-norelay $I10_OUTPUT(double long long long ptr
) MSVCRT_I10_OUTPUT
@ cdecl -i386 -norelay ??0__non_rtti_object@@QAE@ABV0@@Z(ptr) __thiscall_MSVCRT___non_rtti_object_copy_ctor
@ cdecl -i386 -norelay ??0__non_rtti_object@@QAE@PBD@Z(ptr) __thiscall_MSVCRT___non_rtti_object_ctor
@ cdecl -i386 -norelay ??0bad_cast@@AAE@PBQBD@Z(ptr) __thiscall_MSVCRT_bad_cast_ctor
...
...
dlls/msvcrt/string.c
View file @
4aee4c7d
...
...
@@ -26,6 +26,7 @@
#include "wine/port.h"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <limits.h>
#include <errno.h>
...
...
@@ -669,3 +670,98 @@ int CDECL MSVCRT__ui64toa_s(unsigned __int64 value, char *str,
memcpy
(
str
,
pos
,
buffer
-
pos
+
65
);
return
0
;
}
#define I10_OUTPUT_MAX_PREC 21
/* Internal structure used by $I10_OUTPUT */
struct
_I10_OUTPUT_DATA
{
short
pos
;
char
sign
;
BYTE
len
;
char
str
[
I10_OUTPUT_MAX_PREC
+
1
];
/* add space for '\0' */
};
/*********************************************************************
* $I10_OUTPUT (MSVCRT.@)
* ld - long double to be printed to data
* prec - precision of part, we're interested in
* flag - 0 for first prec digits, 1 for fractional part
* data - data to be populated
*
* return value
* 0 if given double is NaN or INF
* 1 otherwise
*
* FIXME
* Native sets last byte of data->str to '0' or '9', I don't know what
* it means. Current implementation sets it always to '0'.
*/
int
CDECL
MSVCRT_I10_OUTPUT
(
MSVCRT__LDOUBLE
ld
,
int
prec
,
int
flag
,
struct
_I10_OUTPUT_DATA
*
data
)
{
static
const
char
inf_str
[]
=
"1#INF"
;
static
const
char
nan_str
[]
=
"1#QNAN"
;
double
d
=
ld
.
x
;
char
format
[
8
];
char
buf
[
I10_OUTPUT_MAX_PREC
+
9
];
/* 9 = strlen("0.e+0000") + '\0' */
char
*
p
;
TRACE
(
"(%lf %d %x %p)
\n
"
,
d
,
prec
,
flag
,
data
);
if
(
d
<
0
)
{
data
->
sign
=
'-'
;
d
=
-
d
;
}
else
data
->
sign
=
' '
;
if
(
isinf
(
d
))
{
data
->
pos
=
1
;
data
->
len
=
5
;
memcpy
(
data
->
str
,
inf_str
,
sizeof
(
inf_str
));
return
0
;
}
if
(
isnan
(
d
))
{
data
->
pos
=
1
;
data
->
len
=
6
;
memcpy
(
data
->
str
,
nan_str
,
sizeof
(
nan_str
));
return
0
;
}
if
(
flag
&
1
)
{
int
exp
=
1
+
floor
(
log10
(
d
));
prec
+=
exp
;
if
(
exp
<
0
)
prec
--
;
}
prec
--
;
if
(
prec
+
1
>
I10_OUTPUT_MAX_PREC
)
prec
=
I10_OUTPUT_MAX_PREC
-
1
;
else
if
(
prec
<
0
)
{
d
=
0
.
0
;
prec
=
0
;
}
sprintf
(
format
,
"%%.%dle"
,
prec
);
sprintf
(
buf
,
format
,
d
);
buf
[
1
]
=
buf
[
0
];
data
->
pos
=
atoi
(
buf
+
prec
+
3
);
if
(
buf
[
1
]
!=
'0'
)
data
->
pos
++
;
for
(
p
=
buf
+
prec
+
1
;
p
>
buf
+
1
&&
*
p
==
'0'
;
p
--
);
data
->
len
=
p
-
buf
;
memcpy
(
data
->
str
,
buf
+
1
,
data
->
len
);
data
->
str
[
data
->
len
]
=
'\0'
;
if
(
buf
[
1
]
!=
'0'
&&
prec
-
data
->
len
+
1
>
0
)
memcpy
(
data
->
str
+
data
->
len
+
1
,
buf
+
data
->
len
+
1
,
prec
-
data
->
len
+
1
);
return
1
;
}
#undef I10_OUTPUT_MAX_PREC
dlls/msvcrt/tests/misc.c
View file @
4aee4c7d
...
...
@@ -24,6 +24,7 @@
static
int
(
__cdecl
*
prand_s
)(
unsigned
int
*
);
static
int
(
__cdecl
*
memcpy_s
)(
void
*
,
MSVCRT_size_t
,
void
*
,
MSVCRT_size_t
);
static
int
(
__cdecl
*
pI10_OUTPUT
)(
long
double
,
int
,
int
,
void
*
);
static
void
init
(
void
)
{
...
...
@@ -31,6 +32,7 @@ static void init(void)
prand_s
=
(
void
*
)
GetProcAddress
(
hmod
,
"rand_s"
);
memcpy_s
=
(
void
*
)
GetProcAddress
(
hmod
,
"memcpy_s"
);
pI10_OUTPUT
=
(
void
*
)
GetProcAddress
(
hmod
,
"$I10_OUTPUT"
);
}
static
void
test_rand_s
(
void
)
...
...
@@ -104,10 +106,97 @@ static void test_memcpy_s(void)
ok
(
dest
[
0
]
==
'\0'
,
"dest[0] !=
\'\\
0
\'\n
"
);
}
typedef
struct
_I10_OUTPUT_data
{
short
pos
;
char
sign
;
BYTE
len
;
char
str
[
100
];
}
I10_OUTPUT_data
;
typedef
struct
_I10_OUTPUT_test
{
long
double
d
;
int
size
;
int
flags
;
I10_OUTPUT_data
out
;
int
ret
;
const
char
*
remain
;
}
I10_OUTPUT_test
;
static
const
I10_OUTPUT_test
I10_OUTPUT_tests
[]
=
{
/* arg3 = 0 */
{
0
.
0
,
10
,
0
,
{
0
,
' '
,
1
,
"0"
},
1
,
""
},
{
1
.
0
,
10
,
0
,
{
1
,
' '
,
1
,
"1"
},
1
,
"000000009"
},
{
-
1
.
0
,
10
,
0
,
{
1
,
'-'
,
1
,
"1"
},
1
,
"000000009"
},
{
1
.
23
,
10
,
0
,
{
1
,
' '
,
3
,
"123"
},
1
,
"0000009"
},
{
1e13
,
10
,
0
,
{
14
,
' '
,
1
,
"1"
},
1
,
"000000009"
},
{
1e30
,
30
,
0
,
{
31
,
' '
,
21
,
"100000000000000001988"
},
1
,
""
},
{
1e-13
,
10
,
0
,
{
-
12
,
' '
,
1
,
"1"
},
1
,
"000000000"
},
{
0
.
25
,
10
,
0
,
{
0
,
' '
,
2
,
"25"
},
1
,
"00000000"
},
{
1
.
0000001
,
10
,
0
,
{
1
,
' '
,
8
,
"10000001"
},
1
,
"00"
},
/* arg3 = 1 */
{
0
.
0
,
10
,
1
,
{
0
,
' '
,
1
,
"0"
},
1
,
""
},
{
1
.
0
,
10
,
1
,
{
1
,
' '
,
1
,
"1"
},
1
,
"0000000009"
},
{
-
1
.
0
,
10
,
1
,
{
1
,
'-'
,
1
,
"1"
},
1
,
"0000000009"
},
{
1
.
23
,
10
,
1
,
{
1
,
' '
,
3
,
"123"
},
1
,
"00000009"
},
{
1e13
,
10
,
1
,
{
14
,
' '
,
1
,
"1"
},
1
,
"00000000000000000009"
},
{
1e30
,
30
,
1
,
{
31
,
' '
,
21
,
"100000000000000001988"
},
1
,
""
},
{
1e-13
,
10
,
1
,
{
0
,
' '
,
1
,
"0"
},
1
,
""
},
{
1e-7
,
10
,
1
,
{
-
6
,
' '
,
1
,
"1"
},
1
,
"09"
},
{
0
.
25
,
10
,
1
,
{
0
,
' '
,
2
,
"25"
},
1
,
"00000000"
},
{
1
.
0000001
,
10
,
1
,
{
1
,
' '
,
8
,
"10000001"
},
1
,
"000"
},
/* too small buffer */
{
0
.
0
,
0
,
0
,
{
0
,
' '
,
1
,
"0"
},
1
,
""
},
{
0
.
0
,
0
,
1
,
{
0
,
' '
,
1
,
"0"
},
1
,
""
},
{
123
.
0
,
2
,
0
,
{
3
,
' '
,
2
,
"12"
},
1
,
""
},
{
123
.
0
,
0
,
0
,
{
0
,
' '
,
1
,
"0"
},
1
,
""
},
{
123
.
0
,
2
,
1
,
{
3
,
' '
,
3
,
"123"
},
1
,
"09"
},
{
0
.
99
,
1
,
0
,
{
1
,
' '
,
1
,
"1"
},
1
,
""
},
{
1264567
.
0
,
2
,
0
,
{
7
,
' '
,
2
,
"13"
},
1
,
""
},
{
1264567
.
0
,
2
,
1
,
{
7
,
' '
,
7
,
"1264567"
},
1
,
"00"
},
{
1234567891
.
0
,
2
,
1
,
{
10
,
' '
,
10
,
"1234567891"
},
1
,
"09"
}
};
static
void
test_I10_OUTPUT
(
void
)
{
I10_OUTPUT_data
out
;
int
i
,
j
,
ret
;
if
(
!
pI10_OUTPUT
)
{
win_skip
(
"I10_OUTPUT not available
\n
"
);
return
;
}
for
(
i
=
0
;
i
<
sizeof
(
I10_OUTPUT_tests
)
/
sizeof
(
I10_OUTPUT_test
);
i
++
)
{
memset
(
out
.
str
,
'#'
,
sizeof
(
out
.
str
));
ret
=
pI10_OUTPUT
(
I10_OUTPUT_tests
[
i
].
d
,
I10_OUTPUT_tests
[
i
].
size
,
I10_OUTPUT_tests
[
i
].
flags
,
&
out
);
ok
(
ret
==
I10_OUTPUT_tests
[
i
].
ret
,
"%d: ret = %d
\n
"
,
i
,
ret
);
ok
(
out
.
pos
==
I10_OUTPUT_tests
[
i
].
out
.
pos
,
"%d: out.pos = %hd
\n
"
,
i
,
out
.
pos
);
ok
(
out
.
sign
==
I10_OUTPUT_tests
[
i
].
out
.
sign
,
"%d: out.size = %c
\n
"
,
i
,
out
.
sign
);
ok
(
out
.
len
==
I10_OUTPUT_tests
[
i
].
out
.
len
,
"%d: out.len = %d
\n
"
,
i
,
(
int
)
out
.
len
);
ok
(
!
strcmp
(
out
.
str
,
I10_OUTPUT_tests
[
i
].
out
.
str
),
"%d: out.str = %s
\n
"
,
i
,
out
.
str
);
j
=
strlen
(
I10_OUTPUT_tests
[
i
].
remain
);
if
(
j
&&
I10_OUTPUT_tests
[
i
].
remain
[
j
-
1
]
==
'9'
)
todo_wine
ok
(
!
strncmp
(
out
.
str
+
out
.
len
+
1
,
I10_OUTPUT_tests
[
i
].
remain
,
j
),
"%d: &out.str[%d] = %.25s...
\n
"
,
i
,
out
.
len
+
1
,
out
.
str
+
out
.
len
+
1
);
else
ok
(
!
strncmp
(
out
.
str
+
out
.
len
+
1
,
I10_OUTPUT_tests
[
i
].
remain
,
j
),
"%d: &out.str[%d] = %.25s...
\n
"
,
i
,
out
.
len
+
1
,
out
.
str
+
out
.
len
+
1
);
for
(
j
=
out
.
len
+
strlen
(
I10_OUTPUT_tests
[
i
].
remain
)
+
1
;
j
<
sizeof
(
out
.
str
);
j
++
)
if
(
out
.
str
[
j
]
!=
'#'
)
ok
(
0
,
"%d: out.str[%d] = %c (expected
\'
#
\'
)
\n
"
,
i
,
j
,
out
.
str
[
j
]);
}
}
START_TEST
(
misc
)
{
init
();
test_rand_s
();
test_memcpy_s
();
test_I10_OUTPUT
();
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment