From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 2294 invoked by alias); 18 Feb 2007 15:37:25 -0000 Received: (qmail 2283 invoked by uid 22791); 18 Feb 2007 15:37:23 -0000 X-Spam-Check-By: sourceware.org Received: from 195.22.55.53.adsl.nextra.cz (HELO host0.dyn.jankratochvil.net) (195.22.55.53) by sourceware.org (qpsmtpd/0.31) with ESMTP; Sun, 18 Feb 2007 15:37:13 +0000 Received: from host0.dyn.jankratochvil.net (localhost [127.0.0.1]) by host0.dyn.jankratochvil.net (8.14.0/8.13.8) with ESMTP id l1IFb9LI011557 for ; Sun, 18 Feb 2007 16:37:09 +0100 Received: (from jkratoch@localhost) by host0.dyn.jankratochvil.net (8.14.0/8.14.0/Submit) id l1IFb6AT011554 for gdb-patches@sourceware.org; Sun, 18 Feb 2007 16:37:06 +0100 Date: Sun, 18 Feb 2007 15:37:00 -0000 From: Jan Kratochvil To: gdb-patches@sourceware.org Subject: [RFC] print/x of a float/double should printf ("%a") Message-ID: <20070218153705.GA25940@host0.dyn.jankratochvil.net> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="7AUc2qLy4jB3hD7Z" Content-Disposition: inline User-Agent: Mutt/1.5.13 (2007-02-12) X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2007-02/txt/msg00222.txt.bz2 --7AUc2qLy4jB3hD7Z Content-Type: text/plain; charset=iso-2022-jp Content-Disposition: inline Content-length: 1575 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. --7AUc2qLy4jB3hD7Z Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=patch Content-length: 15586 2007-02-18 Jan Kratochvil * 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 * 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 --7AUc2qLy4jB3hD7Z--