* doublest.c (convert_floatformat_to_doublest): Use
authorDaniel Jacobowitz <drow@false.org>
Fri, 30 Mar 2007 14:31:44 +0000 (14:31 +0000)
committerDaniel Jacobowitz <drow@false.org>
Fri, 30 Mar 2007 14:31:44 +0000 (14:31 +0000)
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.

gdb/ChangeLog
gdb/doublest.c
gdb/doublest.h
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/infnan.c [new file with mode: 0644]
gdb/testsuite/gdb.base/infnan.exp [new file with mode: 0644]
gdb/valprint.c

index 97171403a23d5e3359c33b88342e938928dc646c..1cb44c71f8f8d11cec6d9b3f4dbc4455f37d845e 100644 (file)
@@ -1,3 +1,15 @@
+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.
index 3b640f5519d0331f29492f9013130ad6d76d6b89..77e7ef9c78376bd44761cbd5190b2f67e9d5ad26 100644 (file)
@@ -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
index 058b4a34e68a307a3547c52482380f29da6873bb..983c7be0af552c0e0b48b2656f24caccbe0666c1 100644 (file)
@@ -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 *);
 
index beea1bcda731d49d23e8384795a04a7931381823..74d754d18d35d65692989045fc22b96c2df54c98 100644 (file)
@@ -1,3 +1,7 @@
+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.
diff --git a/gdb/testsuite/gdb.base/infnan.c b/gdb/testsuite/gdb.base/infnan.c
new file mode 100644 (file)
index 0000000..4973663
--- /dev/null
@@ -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 (file)
index 0000000..b14b6f3
--- /dev/null
@@ -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.*\\)"
index c2663e12e3ba3cb2647be9995d1ef5a686c7dd42..ff6f5d673e365a7a9cc02331bb07e64d1705c24c 100644 (file)
@@ -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()