Mail Archives: djgpp-workers/2008/03/16/08:29:08
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:
<http://sourceware.org/ml/glibc-bugs/2007-06/msg00002.html>
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 <juan DOT guerrero AT gmx DOT de>
* 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;
}
- Raw text -