summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Jacobowitz <dan@debian.org>2007-03-30 14:31:44 +0000
committerDaniel Jacobowitz <dan@debian.org>2007-03-30 14:31:44 +0000
commite97e48896e60d92e7628d1efaebfd03817f66d71 (patch)
tree834790db347f3d9c63d9e2100b6560841758a84e
parent43980de7618dd9c5bd3f97c4a6c9f98560e0ad2d (diff)
downloadgdb-e97e48896e60d92e7628d1efaebfd03817f66d71.tar.gz
* doublest.c (convert_floatformat_to_doublest): Use
floatformat_classify. (floatformat_is_nan): Rename to... (floatformat_classify): ...this. Return more information. * doublest.h (enum float_kind): New. (floatformat_is_nan): Replace prototype... (floatformat_classify): ...with this one. * valprint.c (print_floating): Use floatformat_classify. Handle infinity. * gdb.base/infnan.c, gdb.base/infnan.exp: New files.
-rw-r--r--gdb/ChangeLog12
-rw-r--r--gdb/doublest.c58
-rw-r--r--gdb/doublest.h14
-rw-r--r--gdb/testsuite/ChangeLog4
-rw-r--r--gdb/testsuite/gdb.base/infnan.c30
-rw-r--r--gdb/testsuite/gdb.base/infnan.exp36
-rw-r--r--gdb/valprint.c28
7 files changed, 162 insertions, 20 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 97171403a23..1cb44c71f8f 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,17 @@
2007-03-30 Daniel Jacobowitz <dan@codesourcery.com>
+ * doublest.c (convert_floatformat_to_doublest): Use
+ floatformat_classify.
+ (floatformat_is_nan): Rename to...
+ (floatformat_classify): ...this. Return more information.
+ * doublest.h (enum float_kind): New.
+ (floatformat_is_nan): Replace prototype...
+ (floatformat_classify): ...with this one.
+ * valprint.c (print_floating): Use floatformat_classify. Handle
+ infinity.
+
+2007-03-30 Daniel Jacobowitz <dan@codesourcery.com>
+
* README: Mention ISO C library requirement.
2007-03-30 Daniel Jacobowitz <dan@codesourcery.com>
diff --git a/gdb/doublest.c b/gdb/doublest.c
index 3b640f5519d..77e7ef9c783 100644
--- a/gdb/doublest.c
+++ b/gdb/doublest.c
@@ -180,10 +180,23 @@ convert_floatformat_to_doublest (const struct floatformat *fmt,
int special_exponent; /* It's a NaN, denorm or zero */
enum floatformat_byteorders order;
unsigned char newfrom[FLOATFORMAT_LARGEST_BYTES];
+ enum float_kind kind;
gdb_assert (fmt->totalsize
<= FLOATFORMAT_LARGEST_BYTES * FLOATFORMAT_CHAR_BIT);
+ /* For non-numbers, reuse libiberty's logic to find the correct
+ format. We do not lose any precision in this case by passing
+ through a double. */
+ kind = floatformat_classify (fmt, from);
+ if (kind == float_infinite || kind == float_nan)
+ {
+ double dto;
+ floatformat_to_double (fmt, from, &dto);
+ *to = (DOUBLEST) dto;
+ return;
+ }
+
order = floatformat_normalize_byteorder (fmt, ufrom, newfrom);
if (order != fmt->byteorder)
@@ -495,9 +508,9 @@ floatformat_is_negative (const struct floatformat *fmt,
/* Check if VAL is "not a number" (NaN) for FMT. */
-int
-floatformat_is_nan (const struct floatformat *fmt,
- const bfd_byte *uval)
+enum float_kind
+floatformat_classify (const struct floatformat *fmt,
+ const bfd_byte *uval)
{
long exponent;
unsigned long mant;
@@ -505,6 +518,7 @@ floatformat_is_nan (const struct floatformat *fmt,
int mant_bits_left;
enum floatformat_byteorders order;
unsigned char newfrom[FLOATFORMAT_LARGEST_BYTES];
+ int mant_zero;
gdb_assert (fmt != NULL);
gdb_assert (fmt->totalsize
@@ -515,18 +529,13 @@ floatformat_is_nan (const struct floatformat *fmt,
if (order != fmt->byteorder)
uval = newfrom;
- if (! fmt->exp_nan)
- return 0;
-
exponent = get_field (uval, order, fmt->totalsize, fmt->exp_start,
fmt->exp_len);
- if (exponent != fmt->exp_nan)
- return 0;
-
mant_bits_left = fmt->man_len;
mant_off = fmt->man_start;
+ mant_zero = 1;
while (mant_bits_left > 0)
{
mant_bits = min (mant_bits_left, 32);
@@ -539,13 +548,40 @@ floatformat_is_nan (const struct floatformat *fmt,
mant &= ~(1 << (mant_bits - 1));
if (mant)
- return 1;
+ {
+ mant_zero = 0;
+ break;
+ }
mant_off += mant_bits;
mant_bits_left -= mant_bits;
}
- return 0;
+ /* If exp_nan is not set, assume that inf, NaN, and subnormals are not
+ supported. */
+ if (! fmt->exp_nan)
+ {
+ if (mant_zero)
+ return float_zero;
+ else
+ return float_normal;
+ }
+
+ if (exponent == 0 && !mant_zero)
+ return float_subnormal;
+
+ if (exponent == fmt->exp_nan)
+ {
+ if (mant_zero)
+ return float_infinite;
+ else
+ return float_nan;
+ }
+
+ if (mant_zero)
+ return float_zero;
+
+ return float_normal;
}
/* Convert the mantissa of VAL (which is assumed to be a floating
diff --git a/gdb/doublest.h b/gdb/doublest.h
index 058b4a34e68..983c7be0af5 100644
--- a/gdb/doublest.h
+++ b/gdb/doublest.h
@@ -64,6 +64,17 @@ typedef double DOUBLEST;
# undef SCANF_HAS_LONG_DOUBLE
#endif
+/* Different kinds of floatformat numbers recognized by
+ floatformat_classify. To avoid portability issues, we use local
+ values instead of the C99 macros (FP_NAN et cetera). */
+enum float_kind {
+ float_nan,
+ float_infinite,
+ float_zero,
+ float_normal,
+ float_subnormal
+};
+
extern void floatformat_to_doublest (const struct floatformat *,
const void *in, DOUBLEST *out);
extern void floatformat_from_doublest (const struct floatformat *,
@@ -71,7 +82,8 @@ extern void floatformat_from_doublest (const struct floatformat *,
extern int floatformat_is_negative (const struct floatformat *,
const bfd_byte *);
-extern int floatformat_is_nan (const struct floatformat *, const bfd_byte *);
+extern enum float_kind floatformat_classify (const struct floatformat *,
+ const bfd_byte *);
extern const char *floatformat_mantissa (const struct floatformat *,
const bfd_byte *);
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index beea1bcda73..74d754d18d3 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,9 @@
2007-03-30 Daniel Jacobowitz <dan@codesourcery.com>
+ * gdb.base/infnan.c, gdb.base/infnan.exp: New files.
+
+2007-03-30 Daniel Jacobowitz <dan@codesourcery.com>
+
* config/netware.exp: Delete file.
2007-03-29 Joel Brobecker <brobecker@adacore.com>
diff --git a/gdb/testsuite/gdb.base/infnan.c b/gdb/testsuite/gdb.base/infnan.c
new file mode 100644
index 00000000000..49736633af9
--- /dev/null
+++ b/gdb/testsuite/gdb.base/infnan.c
@@ -0,0 +1,30 @@
+/* This test file is part of GDB, the GNU debugger.
+
+ Copyright 2007
+ Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+double a = 1.0/0.0;
+double b = 0.0/0.0;
+double c;
+
+int
+main()
+{
+ c = a + b;
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/infnan.exp b/gdb/testsuite/gdb.base/infnan.exp
new file mode 100644
index 00000000000..b14b6f353a3
--- /dev/null
+++ b/gdb/testsuite/gdb.base/infnan.exp
@@ -0,0 +1,36 @@
+# Copyright 2007 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+# Script to test floating point infinities and NaNs.
+
+set testfile "infnan"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ untested infnan.exp
+ return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+runto_main
+
+gdb_test "print a" "\\\$$decimal = inf"
+gdb_test "print b" "\\\$$decimal = nan\\(0x.*\\)"
diff --git a/gdb/valprint.c b/gdb/valprint.c
index c2663e12e3b..ff6f5d673e3 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -442,19 +442,31 @@ print_floating (const gdb_byte *valaddr, struct type *type,
int inv;
const struct floatformat *fmt = NULL;
unsigned len = TYPE_LENGTH (type);
+ enum float_kind kind;
/* If it is a floating-point, check for obvious problems. */
if (TYPE_CODE (type) == TYPE_CODE_FLT)
fmt = floatformat_from_type (type);
- if (fmt != NULL && floatformat_is_nan (fmt, valaddr))
+ if (fmt != NULL)
{
- if (floatformat_is_negative (fmt, valaddr))
- fprintf_filtered (stream, "-");
- fprintf_filtered (stream, "nan(");
- fputs_filtered ("0x", stream);
- fputs_filtered (floatformat_mantissa (fmt, valaddr), stream);
- fprintf_filtered (stream, ")");
- return;
+ kind = floatformat_classify (fmt, valaddr);
+ if (kind == float_nan)
+ {
+ if (floatformat_is_negative (fmt, valaddr))
+ fprintf_filtered (stream, "-");
+ fprintf_filtered (stream, "nan(");
+ fputs_filtered ("0x", stream);
+ fputs_filtered (floatformat_mantissa (fmt, valaddr), stream);
+ fprintf_filtered (stream, ")");
+ return;
+ }
+ else if (kind == float_infinite)
+ {
+ if (floatformat_is_negative (fmt, valaddr))
+ fputs_filtered ("-", stream);
+ fputs_filtered ("inf", stream);
+ return;
+ }
}
/* NOTE: cagney/2002-01-15: The TYPE passed into print_floating()