Thread View: gnu.gdb.bug
1 messages
1 total messages
Started by Paul Eggert
Fri, 09 Feb 1990 07:30
problems with GDB 3.5's display of IEEE floating point values
Author: Paul Eggert
Date: Fri, 09 Feb 1990 07:30
Date: Fri, 09 Feb 1990 07:30
225 lines
6450 bytes
6450 bytes
GDB 3.5 has problems displaying IEEE floating point values, particularly NaNs.
* The test for whether a number is a NaN is flawed: the expression highhalf &
0xfffff == 0 in is_nan() should be (highhalf & 0xfffff) == 0.
* The signs of NaNs are not displayed. The fractions of NaNs (which give
machine-dependent information about what generated the NaN) are not displayed.
* Several m-*.h files should #define IEEE_FLOAT but don't, e.g. m-news.h,
m-sun3.h.
* Only 16 digits of a double are printed; the IEEE standard requires 17 digits
for maximum precision.
Patches for these problems are enclosed below. The patches avoid the
IEEE_FLOAT problem by using a simple dynamic test to see whether a number X is
a NaN; if (X!=X), it's a NaN, otherwise it isn't. This trick is documented in
the IEEE floating point standard, so it works for IEEE floating point. If some
non-IEEE floating point format has a value X where X!=X, the ``else if (doub !=
doub) { ... }'' code below needs to be surrounded by ``#ifdef IEEE_FLOAT ...
#endif''; but I suspect that this is not the case, and that IEEE_FLOAT can be
removed from the m-*.h files.
*** old/printcmd.c Fri Jan 19 19:32:54 1990
--- new/printcmd.c Thu Feb 8 22:56:08 1990
***************
*** 63,68 ****
--- 63,69 ----
void do_displays ();
void print_address ();
+ void print_floating ();
void print_scalar_formatted ();
***************
*** 355,377 ****
type = builtin_type_float;
else if (len == sizeof (double))
type = builtin_type_double;
! #ifdef IEEE_FLOAT
! if (is_nan (type, valaddr))
! {
! fprintf_filtered (stream, "Nan");
! break;
! }
! #endif
! {
! double doub;
! int inv;
!
! doub = unpack_double (type, valaddr, &inv);
! if (inv)
! fprintf_filtered (stream, "Invalid float value");
! else
! fprintf_filtered (stream, len > 4 ? "%.16g" : "%.6g", doub);
! }
break;
case 0:
--- 356,362 ----
type = builtin_type_float;
else if (len == sizeof (double))
type = builtin_type_double;
! print_floating(valaddr, type, stream);
break;
case 0:
***************
*** 380,385 ****
--- 365,423 ----
default:
error ("Undefined output format \"%c\".", format);
}
+ }
+
+ /* Print a floating point value of type TYPE, pointed to in GDB by VALADDR,
+ on STREAM. */
+
+ void
+ print_floating(valaddr, type, stream)
+ char *valaddr;
+ struct type *type;
+ FILE *stream;
+ {
+ double doub;
+ int inv;
+ int len = TYPE_LENGTH (type);
+
+ doub = unpack_double (type, valaddr, &inv);
+ if (inv)
+ fprintf_filtered (stream, "Invalid float value");
+ else if (doub != doub)
+ {
+ /* Surely it is an IEEE floating point NaN. */
+
+ long low, high, *arg = (long *)valaddr; /* ASSUMED 32 BITS */
+ int nonneg;
+
+ if (len <= sizeof(float))
+ {
+ /* It's single precision. */
+ low = *arg;
+ nonneg = low >= 0;
+ low &= 0x7fffff;
+ high = 0;
+ }
+ else
+ {
+ /* It's double precision.
+ Get the high and low words of the fraction.
+ Distinguish big and little-endian machines. */
+ #ifdef WORDS_BIG_ENDIAN
+ low = arg[1], high = arg[0];
+ #else
+ low = arg[0], high = arg[1];
+ #endif
+ nonneg = high >= 0;
+ high &= 0xfffff;
+ }
+ if (high)
+ fprintf_filtered (stream, "-NaN(0x%lx%.8lx)" + nonneg, high, low);
+ else
+ fprintf_filtered (stream, "-NaN(0x%lx)" + nonneg, low);
+ }
+ else
+ fprintf_filtered (stream, len <= sizeof(float) ? "%.6g" : "%.17g", doub);
}
/* Specify default address for `x' command.
*** old/valprint.c Thu Feb 1 14:48:29 1990
--- new/valprint.c Thu Feb 8 22:56:12 1990
***************
*** 714,741 ****
case TYPE_CODE_FLT:
if (format)
! {
! print_scalar_formatted (valaddr, type, format, 0, stream);
! break;
! }
! #ifdef IEEE_FLOAT
! if (is_nan ((char *) valaddr, TYPE_LENGTH (type)))
! {
! fprintf_filtered (stream, "NaN");
! break;
! }
! #endif
! {
! double doub;
! int inv;
!
! doub = unpack_double (type, valaddr, &inv);
! if (inv)
! fprintf_filtered (stream, "Invalid float value");
! else
! fprintf_filtered (stream,
! TYPE_LENGTH (type) <= 4? "%.6g": "%.16g", doub);
! }
break;
case TYPE_CODE_VOID:
--- 714,722 ----
case TYPE_CODE_FLT:
if (format)
! print_scalar_formatted (valaddr, type, format, 0, stream);
! else
! print_floating (valaddr, type, stream);
break;
case TYPE_CODE_VOID:
***************
*** 748,796 ****
fflush (stream);
return 0;
}
-
- #ifdef IEEE_FLOAT
-
- /* Nonzero if ARG (a double) is a NAN. */
-
- int
- is_nan (fp, len)
- char *fp;
- int len;
- {
- int lowhalf, highhalf;
- union ieee
- {
- long i[2]; /* ASSUMED 32 BITS */
- float f; /* ASSUMED 32 BITS */
- double d; /* ASSUMED 64 BITS */
- } *arg;
-
- arg = (union ieee *)fp;
-
- /*
- * Single precision float.
- */
- if (len == sizeof(long))
- {
- highhalf = arg->i[0];
- return ((((highhalf >> 23) & 0xFF) == 0xFF)
- && 0 != (highhalf & 0x7FFFFF));
- }
-
- /* Separate the high and low words of the double.
- Distinguish big and little-endian machines. */
- #ifdef WORDS_BIG_ENDIAN
- lowhalf = arg->i[1], highhalf = arg->i[0];
- #else
- lowhalf = arg->i[0], highhalf = arg->i[1];
- #endif
-
- /* Nan: exponent is the maximum possible, and fraction is nonzero. */
- return (((highhalf>>20) & 0x7ff) == 0x7ff
- && ! ((highhalf & 0xfffff == 0) && (lowhalf == 0)));
- }
- #endif
/* Print a description of a type TYPE
in the form of a declaration of a variable named VARSTRING.
--- 729,734 ----
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads