X-Authentication-Warning: delorie.com: mail set sender to djgpp-workers-bounces using -f X-Recipient: djgpp-workers AT delorie DOT com X-Authenticated: #27081556 X-Provags-ID: V01U2FsdGVkX1/HLYEWIbbHtZVjDBMUjSKvEOdCaRWs1WBdK+RstI e0BY/XtORH4QGf From: Juan Manuel Guerrero To: djgpp-workers AT delorie DOT com Subject: Retrun string for pseudo-nan and others. Date: Sun, 16 Mar 2008 14:28:48 +0100 User-Agent: KMail/1.9.5 MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline Message-Id: <200803161428.49368.juan.guerrero@gmx.de> X-Y-GMX-Trusted: 0 Reply-To: djgpp-workers AT delorie DOT com Modern configure scripts check what does printf return for Quiet NaN, Signalling NaN, Pseudo-NaN, Pseudo-Infinity, Pseudo-Zero, Pseudo-Denormal and denormalized numbers (unnormal). DJGPP's printf returns "Unnormal" for all except for Quiet NaN and Signalling NaN making the test case fail. According to: all of them shall return nan/NAN. The patch below will fix the issue and make printf a little bit more glibc compatible. Neitherless this will introduce backward compatibility problems because "Unnormal" is no longer issued. Regards, Juan M. Guerrero 2008-03-16 Juan Manuell Guerrero * src/libc/ansi/stdio/doprnt.c: Macro UPPERCASE added to select the appropiate inf and nan representation. (_doprnt): For E, F, G, X set flags to UPPERCASE. (exponentl): Variable flags added to argument list. (isspeciall): Variable flags added to argument list. Use it to select the appropiate inf and nan representation. Return nan/NAN for Quiet NaN, Signalling NaN, Pseudo-NaN, Pseudo-Infinity, Pseudo-Zero, Pseudo-Denormal and denormalized numbers (unnormal) instead of "Unnormal". diff -aprNU3 djgpp.orig/src/libc/ansi/stdio/doprnt.c djgpp/src/libc/ansi/stdio/doprnt.c --- djgpp.orig/src/libc/ansi/stdio/doprnt.c 2008-03-14 22:26:54 +0000 +++ djgpp/src/libc/ansi/stdio/doprnt.c 2008-03-16 14:12:00 +0000 @@ -58,26 +58,26 @@ static __inline__ char tochar(int n) /* have to deal with the negative buffer count kludge */ -#define LONGINT 0x01 /* long integer */ -#define LONGDBL 0x02 /* long double */ -#define SHORTINT 0x04 /* short integer */ -#define CHARINT 0x08 /* char */ -#define ALT 0x10 /* alternate form */ -#define LADJUST 0x20 /* left adjustment */ -#define ZEROPAD 0x40 /* zero (as opposed to blank) pad */ -#define HEXPREFIX 0x80 /* add 0x or 0X prefix */ +#define LONGINT 0x001 /* long integer */ +#define LONGDBL 0x002 /* long double */ +#define SHORTINT 0x004 /* short integer */ +#define CHARINT 0x008 /* char */ +#define ALT 0x010 /* alternate form */ +#define LADJUST 0x020 /* left adjustment */ +#define ZEROPAD 0x040 /* zero (as opposed to blank) pad */ +#define HEXPREFIX 0x080 /* add 0x or 0X prefix */ +#define UPPERCASE 0x100 /* INF/NAN for [AEFG] */ static int cvtl(long double number, int prec, int flags, char *signp, unsigned char fmtch, char *startp, char *endp); static char *doprnt_roundl(long double fract, int *expv, char *start, char *end, char ch, char *signp); -static char *exponentl(char *p, int expv, unsigned char fmtch); +static char *exponentl(char *p, int expv, unsigned char fmtch, int flags); #ifdef __GO32__ -static int isspeciall(long double d, char *bufp); +static int isspeciall(long double d, char *bufp, int flags); #endif static char NULL_REP[] = "(null)"; -static char UNNORMAL_REP[] = "Unnormal"; int _doprnt(const char *fmt0, va_list argp, FILE *fp) @@ -237,11 +237,13 @@ _doprnt(const char *fmt0, va_list argp, } base = 10; goto number; - case 'e': case 'E': + case 'F': + case 'G': + flags |= UPPERCASE; + case 'e': case 'f': case 'g': - case 'G': if (flags & LONGDBL) _ldouble = va_arg(argp, long double); else @@ -377,6 +379,7 @@ _doprnt(const char *fmt0, va_list argp, goto nosign; case 'X': digs = "0123456789ABCDEF"; + flags |= UPPERCASE; /* FALLTHROUGH */ case 'x': ARG(unsigned); @@ -533,7 +536,7 @@ cvtl(long double number, int prec, int f int doingzero=0; /* We're displaying 0.0 */ long double integer, tmp; - if ((expcnt = isspeciall(number, startp))) + if ((expcnt = isspeciall(number, startp, flags))) return(expcnt); dotrim = expcnt = gformat = 0; @@ -723,7 +726,7 @@ cvtl(long double number, int prec, int f --t; ++t; } - t = exponentl(t, expcnt, fmtch); + t = exponentl(t, expcnt, fmtch, flags); break; case 'g': case 'G': @@ -867,7 +870,7 @@ doprnt_roundl(long double fract, int *ex } static char * -exponentl(char *p, int expv, unsigned char fmtch) +exponentl(char *p, int expv, unsigned char fmtch, int flags) { char *t; char expbuf[MAXEXPLD]; @@ -898,44 +901,73 @@ exponentl(char *p, int expv, unsigned ch } static int -isspeciall(long double d, char *bufp) +isspeciall(long double d, char *bufp, int flags) { - typedef struct { - unsigned manl:32; - unsigned manh:32; - unsigned exp:15; - unsigned sign:1; - } IEEExp; - - typedef union { - IEEExp ip; - long double ldouble; /* double and long double precision arguments */ - } ip_union; - - ip_union ip; - - ip.ldouble = d; - - nan_p = 0; /* don't assume the static is 0 (emacs) */ - - /* Unnormals: the MSB of mantissa is non-zero, but the exponent is - not zero either. */ - if ((ip.ip.manh & 0x80000000U) == 0 && ip.ip.exp != 0) - { - if (ip.ip.sign) - *bufp++ = '-'; - strcpy(bufp, UNNORMAL_REP); - return strlen(bufp) + ip.ip.sign; - } - if (ip.ip.exp != 0x7fff) - return(0); - if ((ip.ip.manh & 0x7fffffff) || ip.ip.manl) - { - strcpy(bufp, "NaN"); - nan_p = ip.ip.sign ? -1 : 1; /* kludge: we don't need the sign, it's - not nice, but it should work */ + /* + * For intel's 80 bit floating point number identify + * the following special values: + * + * Supported Floating-Point Encodings (generated by processor as an operation result) + * exp mantissa high mantissa low + * Quiet NaN: 0x7FFF, 11NNNNNNNNNNNNNNNNNNNNNNNNNNNNNN, NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN + * Signalling NaN: 0x7FFF, 10NNNNNNNNNNNNNNNNNNNNNNNNNNNNNN, NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN + * Infinity: 0x7FFF, 10000000000000000000000000000000, 00000000000000000000000000000000 + * Pseudo-Denormal: 0x0000, 1NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN, NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN1 + * + * Unsupported Floating-Point Encodings (not generated by processor as an operation result) + * exp mantissa high mantissa low + * Pseudo-NaN: 0x7FFF, 0NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN, NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN1 + * Pseudo-Infinity: 0x7FFF, 00000000000000000000000000000000, 00000000000000000000000000000000 + * Pseudo-Zero: 0xNNN1, 00000000000000000000000000000000, 00000000000000000000000000000000 + * Unnormal: 0xNNN1, 0NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN, NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN + * + * Patterns of the values according to: + * Intel IA-64 Architecture Software Developer's Manual, Volume 1: + * Application Architecture. + * 5.1.3 "Representation of Values in Floating-Point Registers" + * Table 5-2 "Floating-Point Register Encodings" + * Figure 5-11 "Floating-Point Exception Fault Prioritization" + * + * To be compatible with printf of glibc Quiet NaN, signalling NaN, Pseudo-NaN, + * Pseudo-Infinity, Pseudo-Zero, Pseudo-Denormal and denormalized numbers (unnormal) + * shall all return nan/NAN. + */ + + + static const char inf_representation[2][4] = {"inf", "INF"}; + static const char nan_representation[2][4] = {"nan", "NAN"}; + int style = (flags & UPPERCASE) ? 1 : 0; + _longdouble_union_t ldvalue; + + ldvalue.ld = d; + if (ldvalue.ldt.exponent == 0x7FFF) + { + if (ldvalue.ldt.mantissah == 0x80000000 && ldvalue.ldt.mantissal == 0x00000000) + strcpy(bufp, inf_representation[style]); + else + { + /* Quiet NaN, signalling NaN, Pseudo-NaN and Pseudo-Infinity. */ + strcpy(bufp, nan_representation[style]); + nan_p = ldvalue.ldt.sign ? -1 : 1; /* kludge: we don't need the sign, it's + not nice, but it should work */ + } + return 3; + } + else if (ldvalue.ldt.exponent != 0x0000 && !(ldvalue.ldt.mantissah & 0x80000000)) + { + /* Pseudo-Zero and denormalized numbers (unnormal). */ + strcpy(bufp, nan_representation[style]); + nan_p = ldvalue.ldt.sign ? -1 : 1; /* kludge: we don't need the sign, it's + not nice, but it should work */ + return 3; + } + else if (ldvalue.ldt.exponent == 0x0000 && ldvalue.ldt.mantissah & 0x80000000) + { + /* Pseudo-Denormal. */ + strcpy(bufp, nan_representation[style]); + nan_p = ldvalue.ldt.sign ? -1 : 1; /* kludge: we don't need the sign, it's + not nice, but it should work */ + return 3; } - else - (void)strcpy(bufp, "Inf"); - return(3); + return 0; }