[RFC] print/x of a float/double should printf ("%a")

Jan Kratochvil jan.kratochvil@redhat.com
Sun Feb 18 15:37:00 GMT 2007


Hi,

currently "print/x (float) a" does an integer "print/x (long) a".

Ulrich Drepper requested to use instead printf ("%a") (man excerpt below):

Implemented as:
(gdb) print/x $xmm5
$1 = {v4_float = {0x5, 0x5, 0x5, 0x5}, v2_double = {0xc00, 0x1800}, v16_int8
->
(gdb) print/x $xmm5
$1 = {v4_float = {0x1.400000000p+2, 0x1.500000000p+2, 0x1.600000000p+2,
    0x1.700000000p+2}, v2_double = { 0x1.8000040a000000000p+11,
    0x1.8000040b000000000p+12}, v16_int8 = {0x0, 0x0, 0xa0, 0x40, 0x0, 0x0,

With the original value:
(gdb) print $xmm5
$1 = {v4_float = {5, 5.25, 5.5, 5.75}, v2_double = {3072.0004930496216,
    6144.0009870529175}, v16_int8 = {0 '\0', 0 '\0', -96 '?', 64 '@', 0 '\0',


Implementation attached.  Systems not supporting "%a" will print the value as
	print (float) a
which differs from the current way there:
	print/x (long) a



Regards,
Jan


a,A	(C99; not in SUSv2) For a conversion, the double argument is converted
	to hexadecimal notation (using the letters abcdef) in the style
	[-]0xh.hhhhp±d; for A conversion the prefix 0X, the letters ABCDEF, and
	the exponent separator P is used. There is one hexadecimal digit before
	the decimal point, and the number of digits after it is equal to the
	precision. The default precision suffices for an exact representation
	of the value if an exact representation in base 2 exists and otherwise
	is sufficiently large to distinguish values of type double. The digit
	before the decimal point is unspecified for non-normalized numbers, and
	non-zero but otherwise unspecified for normalized numbers.
-------------- next part --------------
2007-02-18  Jan Kratochvil <jan.kratochvil@redhat.com>

	* configure.ac (PRINTF_HAS_HEX_DOUBLE): Test for printf ("%a").
	* ada-valprint.c (ada_print_floating): Callers changed.
	* c-valprint.c (c_val_print): Likewise.
	* f-valprint.c (f_val_print): Likewise.
	* m2-valprint.c (m2_val_print): Likewise.
	* p-valprint.c (pascal_val_print): Likewise.
	* printcmd.c (print_scalar_formatted): Print TYPE_CODE_FLT/x by
	print_floating (format='x').
	* valprint.c (print_floating): Add FORMAT parameter.
	* value.h (print_floating): Update prototype.
	* configure, config.in: Regenerate.

2007-02-18  Jan Kratochvil <jan.kratochvil@redhat.com>

	* gdb.arch/i386-sse.exp: Check $xmm.v4_float and $xmm.v2_double
	printing in hexadecimal format.
	* gdb.base/gdb1821.exp: Update the DOUBLE/x print check.


Index: gdb/configure.ac
===================================================================
RCS file: /cvs/src/src/gdb/configure.ac,v
retrieving revision 1.42
diff -u -p -r1.42 configure.ac
--- gdb/configure.ac	2 Feb 2007 22:54:09 -0000	1.42
+++ gdb/configure.ac	18 Feb 2007 04:35:38 -0000
@@ -955,6 +955,23 @@ aix*)
   ;;
 esac
 
+# Check if the compiler and runtime support printing doubles in hex.
+
+AC_CACHE_CHECK([for hex double support in printf],
+               gdb_cv_printf_has_hex_double,
+               [AC_RUN_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT],
+[[char buf[16];
+  double f = 3.141592653;
+  sprintf (buf, "%a", f);
+  return (strncmp ("0x1.921fb", buf, 9));]])],
+                              gdb_cv_printf_has_hex_double=yes,
+                              gdb_cv_printf_has_hex_double=no,
+                              gdb_cv_printf_has_hex_double=no)])
+if test $gdb_cv_printf_has_hex_double = yes; then
+  AC_DEFINE(PRINTF_HAS_HEX_DOUBLE, 1,
+            [Define to 1 if the "%a" format works to print doubles in hex.])
+fi
+
 
 dnl For certain native configurations, we need to check whether thread
 dnl support can be built in or not.
Index: gdb/ada-valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/ada-valprint.c,v
retrieving revision 1.30
diff -u -p -r1.30 ada-valprint.c
--- gdb/ada-valprint.c	9 Jan 2007 17:58:49 -0000	1.30
+++ gdb/ada-valprint.c	18 Feb 2007 04:35:32 -0000
@@ -308,7 +308,7 @@ ada_print_floating (const gdb_byte *vala
   struct ui_file *tmp_stream = mem_fileopen ();
   struct cleanup *cleanups = make_cleanup_ui_file_delete (tmp_stream);
 
-  print_floating (valaddr, type, tmp_stream);
+  print_floating (valaddr, type, tmp_stream, 0);
   ui_file_put (tmp_stream, ui_memcpy, buffer);
   do_cleanups (cleanups);
 
Index: gdb/c-valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/c-valprint.c,v
retrieving revision 1.42
diff -u -p -r1.42 c-valprint.c
--- gdb/c-valprint.c	26 Jan 2007 20:54:16 -0000	1.42
+++ gdb/c-valprint.c	18 Feb 2007 04:35:32 -0000
@@ -432,7 +432,7 @@ c_val_print (struct type *type, const gd
 	}
       else
 	{
-	  print_floating (valaddr + embedded_offset, type, stream);
+	  print_floating (valaddr + embedded_offset, type, stream, 0);
 	}
       break;
 
@@ -458,7 +458,7 @@ c_val_print (struct type *type, const gd
 				format, 0, stream);
       else
 	print_floating (valaddr + embedded_offset, TYPE_TARGET_TYPE (type),
-			stream);
+			stream, 0);
       fprintf_filtered (stream, " + ");
       if (format)
 	print_scalar_formatted (valaddr + embedded_offset
@@ -469,7 +469,7 @@ c_val_print (struct type *type, const gd
 	print_floating (valaddr + embedded_offset
 			+ TYPE_LENGTH (TYPE_TARGET_TYPE (type)),
 			TYPE_TARGET_TYPE (type),
-			stream);
+			stream, 0);
       fprintf_filtered (stream, " * I");
       break;
 
Index: gdb/f-valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/f-valprint.c,v
retrieving revision 1.34
diff -u -p -r1.34 f-valprint.c
--- gdb/f-valprint.c	9 Jan 2007 17:58:50 -0000	1.34
+++ gdb/f-valprint.c	18 Feb 2007 04:35:38 -0000
@@ -495,7 +495,7 @@ f_val_print (struct type *type, const gd
       if (format)
 	print_scalar_formatted (valaddr, type, format, 0, stream);
       else
-	print_floating (valaddr, type, stream);
+	print_floating (valaddr, type, stream, 0);
       break;
 
     case TYPE_CODE_VOID:
@@ -571,9 +571,9 @@ f_val_print (struct type *type, const gd
 	  error (_("Cannot print out complex*%d variables"), TYPE_LENGTH (type));
 	}
       fputs_filtered ("(", stream);
-      print_floating (valaddr, type, stream);
+      print_floating (valaddr, type, stream, 0);
       fputs_filtered (",", stream);
-      print_floating (valaddr + TYPE_LENGTH (type), type, stream);
+      print_floating (valaddr + TYPE_LENGTH (type), type, stream, 0);
       fputs_filtered (")", stream);
       break;
 
Index: gdb/m2-valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/m2-valprint.c,v
retrieving revision 1.12
diff -u -p -r1.12 m2-valprint.c
--- gdb/m2-valprint.c	9 Jan 2007 17:58:51 -0000	1.12
+++ gdb/m2-valprint.c	18 Feb 2007 04:35:38 -0000
@@ -479,7 +479,7 @@ m2_val_print (struct type *type, const g
 	print_scalar_formatted (valaddr + embedded_offset, type,
 				format, 0, stream);
       else
-	print_floating (valaddr + embedded_offset, type, stream);
+	print_floating (valaddr + embedded_offset, type, stream, 0);
       break;
 
     case TYPE_CODE_METHOD:
Index: gdb/p-valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/p-valprint.c,v
retrieving revision 1.47
diff -u -p -r1.47 p-valprint.c
--- gdb/p-valprint.c	8 Feb 2007 14:20:56 -0000	1.47
+++ gdb/p-valprint.c	18 Feb 2007 04:35:38 -0000
@@ -426,7 +426,7 @@ pascal_val_print (struct type *type, con
 	}
       else
 	{
-	  print_floating (valaddr + embedded_offset, type, stream);
+	  print_floating (valaddr + embedded_offset, type, stream, 0);
 	}
       break;
 
Index: gdb/printcmd.c
===================================================================
RCS file: /cvs/src/src/gdb/printcmd.c,v
retrieving revision 1.100
diff -u -p -r1.100 printcmd.c
--- gdb/printcmd.c	9 Jan 2007 17:58:56 -0000	1.100
+++ gdb/printcmd.c	18 Feb 2007 04:35:38 -0000
@@ -362,23 +362,36 @@ print_scalar_formatted (const void *vala
   switch (format)
     {
     case 'x':
-      if (!size)
-	{
-	  /* No size specified, like in print.  Print varying # of digits.  */
-	  print_longest (stream, 'x', 1, val_long);
-	}
-      else
-	switch (size)
-	  {
-	  case 'b':
-	  case 'h':
-	  case 'w':
-	  case 'g':
-	    print_longest (stream, size, 1, val_long);
-	    break;
-	  default:
-	    error (_("Undefined output size \"%c\"."), size);
-	  }
+      /* TYPE_CODE_FLT gets printed in hex by print_floating() below.  */
+      if (TYPE_CODE (type) != TYPE_CODE_FLT)
+        {
+	  if (!size)
+	    {
+	      /* No size specified, like in print.  Print varying # of digits.  */
+	      print_longest (stream, 'x', 1, val_long);
+	    }
+	  else
+	    switch (size)
+	      {
+	      case 'b':
+	      case 'h':
+	      case 'w':
+	      case 'g':
+		print_longest (stream, size, 1, val_long);
+		break;
+	      default:
+		error (_("Undefined output size \"%c\"."), size);
+	      }
+	  break;
+        }
+    case 'f':
+      if (len == TYPE_LENGTH (builtin_type_float))
+        type = builtin_type_float;
+      else if (len == TYPE_LENGTH (builtin_type_double))
+        type = builtin_type_double;
+      else if (len == TYPE_LENGTH (builtin_type_long_double))
+        type = builtin_type_long_double;
+      print_floating (valaddr, type, stream, format);
       break;
 
     case 'd':
@@ -408,16 +421,6 @@ print_scalar_formatted (const void *vala
 		   stream, 0, Val_pretty_default);
       break;
 
-    case 'f':
-      if (len == TYPE_LENGTH (builtin_type_float))
-        type = builtin_type_float;
-      else if (len == TYPE_LENGTH (builtin_type_double))
-        type = builtin_type_double;
-      else if (len == TYPE_LENGTH (builtin_type_long_double))
-        type = builtin_type_long_double;
-      print_floating (valaddr, type, stream);
-      break;
-
     case 0:
       internal_error (__FILE__, __LINE__,
 		      _("failed internal consistency check"));
Index: gdb/valprint.c
===================================================================
RCS file: /cvs/src/src/gdb/valprint.c,v
retrieving revision 1.64
diff -u -p -r1.64 valprint.c
--- gdb/valprint.c	9 Jan 2007 17:58:59 -0000	1.64
+++ gdb/valprint.c	18 Feb 2007 04:35:45 -0000
@@ -432,16 +432,18 @@ longest_to_int (LONGEST arg)
 }
 
 /* Print a floating point value of type TYPE (not always a
-   TYPE_CODE_FLT), pointed to in GDB by VALADDR, on STREAM.  */
+   TYPE_CODE_FLT), pointed to in GDB by VALADDR, on STREAM.
+   Print in hex if supported on host and requested by FORMAT 'x'.  */
 
 void
 print_floating (const gdb_byte *valaddr, struct type *type,
-		struct ui_file *stream)
+		struct ui_file *stream, int format)
 {
   DOUBLEST doub;
   int inv;
   const struct floatformat *fmt = NULL;
   unsigned len = TYPE_LENGTH (type);
+  const char *format_string;
 
   /* If it is a floating-point, check for obvious problems.  */
   if (TYPE_CODE (type) == TYPE_CODE_FLT)
@@ -481,17 +483,32 @@ print_floating (const gdb_byte *valaddr,
      instead uses the type's length to determine the precision of the
      floating-point value being printed.  */
 
+  /* Do not use a format string variable to permit arguments checking.  */
+#define FORMAT_PREFIX "%.*"
+#ifdef PRINTF_HAS_LONG_DOUBLE
+# define FORMAT_LONG FORMAT_PREFIX "L"
+#else
+# define FORMAT_LONG FORMAT_PREFIX
+#endif
+#ifdef PRINTF_HAS_HEX_DOUBLE
+# define FORMAT_MAY_HEX (format == 'x' ? FORMAT_PREFIX "a" : FORMAT_PREFIX "g")
+# define FORMAT_LONG_MAY_HEX (format == 'x' ? FORMAT_LONG "a" : FORMAT_LONG "g")
+#else
+# define FORMAT_MAY_HEX FORMAT_PREFIX "g"
+# define FORMAT_LONG_MAY_HEX FORMAT_LONG "g"
+#endif
+
   if (len < sizeof (double))
-      fprintf_filtered (stream, "%.9g", (double) doub);
+      fprintf_filtered (stream, FORMAT_MAY_HEX, 9, (double) doub);
   else if (len == sizeof (double))
-      fprintf_filtered (stream, "%.17g", (double) doub);
+      fprintf_filtered (stream, FORMAT_MAY_HEX, 17, (double) doub);
   else
 #ifdef PRINTF_HAS_LONG_DOUBLE
-    fprintf_filtered (stream, "%.35Lg", doub);
+    fprintf_filtered (stream, FORMAT_LONG_MAY_HEX, 35, doub);
 #else
     /* This at least wins with values that are representable as
        doubles.  */
-    fprintf_filtered (stream, "%.17g", (double) doub);
+    fprintf_filtered (stream, FORMAT_MAY_HEX, 17, (double) doub);
 #endif
 }
 
Index: gdb/value.h
===================================================================
RCS file: /cvs/src/src/gdb/value.h,v
retrieving revision 1.96
diff -u -p -r1.96 value.h
--- gdb/value.h	9 Jan 2007 17:58:59 -0000	1.96
+++ gdb/value.h	18 Feb 2007 04:35:45 -0000
@@ -480,7 +480,7 @@ extern void print_longest (struct ui_fil
 			   int use_local, LONGEST val);
 
 extern void print_floating (const gdb_byte *valaddr, struct type *type,
-			    struct ui_file *stream);
+			    struct ui_file *stream, int format);
 
 extern int value_print (struct value *val, struct ui_file *stream, int format,
 			enum val_prettyprint pretty);
Index: gdb/testsuite/gdb.arch/i386-sse.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.arch/i386-sse.exp,v
retrieving revision 1.6
diff -u -p -r1.6 i386-sse.exp
--- gdb/testsuite/gdb.arch/i386-sse.exp	26 Jan 2007 20:53:15 -0000	1.6
+++ gdb/testsuite/gdb.arch/i386-sse.exp	18 Feb 2007 04:35:45 -0000
@@ -87,6 +87,12 @@ foreach r {0 1 2 3 4 5 6 7} {
     gdb_test "print \$xmm$r.v16_int8" \
         ".. = \\{(-?\[0-9\]+ '.*', ){15}-?\[0-9\]+ '.*'\\}.*" \
         "check int8 contents of %xmm$r"
+    gdb_test "print/x \$xmm$r.v4_float" \
+        ".. = \\{(-?0x\[0-9a-f\]+\[.\]\[0-9a-f\]+p\[+-\]\[0-9\]+, ){3}-?0x\[0-9a-f\]+\[.\]\[0-9a-f\]+p\[+-\]\[0-9\]+\\}.*" \
+        "check hex float contents of %xmm$r"
+    gdb_test "print/x \$xmm$r.v2_double" \
+        ".. = \\{-?0x\[0-9a-f\]+\[.\]\[0-9a-f\]+p\[+-\]\[0-9\]+, -?0x\[0-9a-f\]+\[.\]\[0-9a-f\]+p\[+-\]\[0-9\]+\\}.*" \
+        "check hex double contents of %xmm$r"
 }
 
 foreach r {0 1 2 3 4 5 6 7} {
Index: gdb/testsuite/gdb.base/gdb1821.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/gdb1821.exp,v
retrieving revision 1.2
diff -u -p -r1.2 gdb1821.exp
--- gdb/testsuite/gdb.base/gdb1821.exp	9 Jan 2007 17:59:11 -0000	1.2
+++ gdb/testsuite/gdb.base/gdb1821.exp	18 Feb 2007 13:04:13 -0000
@@ -39,5 +39,4 @@ if ![runto_main] then {
     perror "couldn't run to breakpoint"
     continue
 } 
-gdb_test "print /x bar" "{x__0 = 0x0, y__0 = 0x0, z__1 = 0x0}" 
-
+gdb_test "print /x bar" "{x__0 = 0x0.0+p\\+0, y__0 = 0x0.0+p\\+0, z__1 = 0x0.0+p\\+0}"
Index: gdb/configure
===================================================================
RCS file: /cvs/src/src/gdb/configure,v
retrieving revision 1.221
diff -u -p -r1.221 configure
--- gdb/configure	2 Feb 2007 22:55:54 -0000	1.221
+++ gdb/configure	18 Feb 2007 12:52:56 -0000
@@ -20858,6 +20858,67 @@ echo "${ECHO_T}$gdb_cv_bigtoc" >&6
   ;;
 esac
 
+# Check if the compiler and runtime support printing doubles in hex.
+
+echo "$as_me:$LINENO: checking for hex double support in printf" >&5
+echo $ECHO_N "checking for hex double support in printf... $ECHO_C" >&6
+if test "${gdb_cv_printf_has_hex_double+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  if test "$cross_compiling" = yes; then
+  gdb_cv_printf_has_hex_double=no
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+char buf[16];
+  double f = 3.141592653;
+  sprintf (buf, "%a", f);
+  return (strncmp ("0x1.921fb", buf, 9));
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  gdb_cv_printf_has_hex_double=yes
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+gdb_cv_printf_has_hex_double=no
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $gdb_cv_printf_has_hex_double" >&5
+echo "${ECHO_T}$gdb_cv_printf_has_hex_double" >&6
+if test $gdb_cv_printf_has_hex_double = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define PRINTF_HAS_HEX_DOUBLE 1
+_ACEOF
+
+fi
+
 
 
 if test ${build} = ${host} -a ${host} = ${target} ; then
Index: gdb/config.in
===================================================================
RCS file: /cvs/src/src/gdb/config.in,v
retrieving revision 1.88
diff -u -p -r1.88 config.in
--- gdb/config.in	2 Feb 2007 22:54:46 -0000	1.88
+++ gdb/config.in	18 Feb 2007 04:35:33 -0000
@@ -497,6 +497,9 @@
 /* Define if the prfpregset_t type is broken. */
 #undef PRFPREGSET_T_BROKEN
 
+/* Define to 1 if the "%a" format works to print doubles in hex. */
+#undef PRINTF_HAS_HEX_DOUBLE
+
 /* Define to 1 if the "%Lg" format works to print long doubles. */
 #undef PRINTF_HAS_LONG_DOUBLE
 


More information about the Gdb-patches mailing list