http://bugs.winehq.org/show_bug.cgi?id=4654
------- Additional Comments From focht@gmx.net 2007-28-05 19:42 ------- Hello,
--- quote --- I thought even Wine's declaration of $I10_OUTPUT may be wrong. --- quote ---
Indeed, completely wrong ;-) Following is the likely $I10_OUTPUT prototype and a working test case for you (windows msvcrt.dll). I had to trick M$ VC++ to accept 10-byte long double data (long double is always mapped to 64 bit double).
--- snip sample code --- #include <windows.h> #include <stdio.h>
typedef struct _I10_DATA { unsigned short decimal_point_pos; /* decimal-point position */ char sign; /* sign indicator: "-", " " */ unsigned char digits; /* number of digits returned (excluding NULL term) */ char digit_buf[1]; /* storage to digits string (including NULL terminator) */ } I10_DATA, *PI10_DATA;
/* 10-byte long double is a IEEE754 extended precision float long double: SEEEEEEEEEEEEEEE 1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
double: SEEEEEEEEEEEFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
Where S=sign, E=exp, F=fractional part. The long double exponent is biased by 16383 and the doubles is biased by 1023. */
/* * struct to fool the idiot compiler into not generating floating point * instructions when copying and pushing [long] double values */ typedef struct { unsigned char ldbl[10]; } LONGDOUBLE;
/* "I10_OUTPUT" prototype LONGDOUBLE arg1 = long double value (10 bytes) long arg2 = number of desired digits long arg3 = flag? (0) PI10_DATA arg4 = pointer to result data
returns: 1 if ok, 0 if NAN, INFINITY ... */ typedef long (*PFN_I10_OUTPUT)(LONGDOUBLE, long, long, PI10_DATA);
int main(int argc, char* argv[]) { HMODULE hMod = LoadLibrary( "msvcrt.dll"); PFN_I10_OUTPUT pfn = (PFN_I10_OUTPUT) GetProcAddress( hMod, "$I10_OUTPUT");
int num_digits = 7; PI10_DATA buf = (PI10_STRUCT) HeapAlloc( GetProcessHeap(), 0, sizeof(I10_DATA)+num_digits);
LONGDOUBLE ld; double dblNum = -12.3456789; _asm { fld dblNum; fstp TBYTE PTR [ld]; }
long res = pfn( ld, num_digits, 0, buf);
printf( "digits: %d, decimal point: %d, sign: '%c', digits: '%s'\n", buf->digits, buf->decimal_point_pos, buf->sign, buf->digit_buf);
/* digits: 7, decimal point: 2, sign: '-', digits: '1234568' */
HeapFree( GetProcessHeap(), 0, buf); FreeLibrary( hMod);
return 0; } --- snip sample code ---
If you need more prototypes keep asking ... though that float stuff is not really my preferred domain :-)
Regards