[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