1 #include <precomp.h> 2 3 #define I10_OUTPUT_MAX_PREC 21 4 /* Internal structure used by $I10_OUTPUT */ 5 struct _I10_OUTPUT_DATA { 6 short pos; 7 char sign; 8 BYTE len; 9 char str[I10_OUTPUT_MAX_PREC+1]; /* add space for '\0' */ 10 }; 11 12 /********************************************************************* 13 * $I10_OUTPUT (MSVCRT.@) 14 * ld80 - long double (Intel 80 bit FP in 12 bytes) to be printed to data 15 * prec - precision of part, we're interested in 16 * flag - 0 for first prec digits, 1 for fractional part 17 * data - data to be populated 18 * 19 * return value 20 * 0 if given double is NaN or INF 21 * 1 otherwise 22 * 23 * FIXME 24 * Native sets last byte of data->str to '0' or '9', I don't know what 25 * it means. Current implementation sets it always to '0'. 26 */ 27 int CDECL MSVCRT_I10_OUTPUT(_LDOUBLE ld80, int prec, int flag, struct _I10_OUTPUT_DATA *data) 28 { 29 static const char inf_str[] = "1#INF"; 30 static const char nan_str[] = "1#QNAN"; 31 32 /* MS' long double type wants 12 bytes for Intel's 80 bit FP format. 33 * Some UNIX have sizeof(long double) == 16, yet only 80 bit are used. 34 * Assume long double uses 80 bit FP, never seen 128 bit FP. */ 35 long double ld = 0; 36 double d; 37 char format[8]; 38 char buf[I10_OUTPUT_MAX_PREC+9]; /* 9 = strlen("0.e+0000") + '\0' */ 39 char *p; 40 41 memcpy(&ld, &ld80, 10); 42 d = ld; 43 TRACE("(%lf %d %x %p)\n", d, prec, flag, data); 44 45 if(d<0) { 46 data->sign = '-'; 47 d = -d; 48 } else 49 data->sign = ' '; 50 51 if(!_finite(d)) { 52 data->pos = 1; 53 data->len = 5; 54 memcpy(data->str, inf_str, sizeof(inf_str)); 55 56 return 0; 57 } 58 59 if(_isnan(d)) { 60 data->pos = 1; 61 data->len = 6; 62 memcpy(data->str, nan_str, sizeof(nan_str)); 63 64 return 0; 65 } 66 67 if(flag&1) { 68 int exp = 1+floor(log10(d)); 69 70 prec += exp; 71 if(exp < 0) 72 prec--; 73 } 74 prec--; 75 76 if(prec+1 > I10_OUTPUT_MAX_PREC) 77 prec = I10_OUTPUT_MAX_PREC-1; 78 else if(prec < 0) { 79 d = 0.0; 80 prec = 0; 81 } 82 83 sprintf_s(format, sizeof(format), "%%.%dle", prec); 84 sprintf_s(buf, sizeof(buf), format, d); 85 86 buf[1] = buf[0]; 87 data->pos = atoi(buf+prec+3); 88 if(buf[1] != '0') 89 data->pos++; 90 91 for(p = buf+prec+1; p>buf+1 && *p=='0'; p--); 92 data->len = p-buf; 93 94 memcpy(data->str, buf+1, data->len); 95 data->str[data->len] = '\0'; 96 97 if(buf[1]!='0' && prec-data->len+1>0) 98 memcpy(data->str+data->len+1, buf+data->len+1, prec-data->len+1); 99 100 return 1; 101 } 102 #undef I10_OUTPUT_MAX_PREC 103 104 105 106