This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [PATCH] printf support for DFP values
- From: Luis Machado <luisgpm at linux dot vnet dot ibm dot com>
- To: Daniel Jacobowitz <drow at false dot org>
- Cc: Eli Zaretskii <eliz at gnu dot org>, gdb-patches at sourceware dot org
- Date: Thu, 01 Nov 2007 12:59:51 -0300
- Subject: Re: [PATCH] printf support for DFP values
- References: <1193449497.6950.22.camel@localhost> <ubqaksyin.fsf@gnu.org> <1193669215.4800.10.camel@localhost> <ur6jdr8iy.fsf@gnu.org> <20071029201252.GA21583@caradoc.them.org> <upryxqmb5.fsf@gnu.org> <ulk9lqlmm.fsf@gnu.org> <1193753649.4283.5.camel@localhost> <uir4oqs3w.fsf@gnu.org> <1193879919.4994.2.camel@localhost> <20071101153418.GA19992@caradoc.them.org>
- Reply-to: luisgpm at linux dot vnet dot ibm dot com
Hi,
This should be the final version then.
> Here and a couple of other places in the patch, please remember the
> space before a left parenthesis.
Fixed.
Thanks.
Luis
2007-11-01 Luis Machado <luisgpm@br.ibm.com>
* printcmd.c: (printf_command): Add support for new DFP
modifiers %H, %D and %DD.
* configure.ac: Add check for DECFLOAT printf support.
* configure: Regenerated.
* doc/gdb.texinfo: Update printf command's description.
* testsuite/gdb.base/printcmds.exp: New function
test_printf_with_dfp.
Index: git/gdb/printcmd.c
===================================================================
--- git.orig/gdb/printcmd.c 2007-10-31 15:17:33.000000000 -0700
+++ git/gdb/printcmd.c 2007-11-01 08:50:44.000000000 -0700
@@ -41,6 +41,7 @@
#include "gdb_assert.h"
#include "block.h"
#include "disasm.h"
+#include "dfp.h"
#ifdef TUI
#include "tui/tui.h" /* For tui_active et.al. */
@@ -1819,7 +1820,7 @@
enum argclass
{
int_arg, long_arg, long_long_arg, ptr_arg, string_arg,
- double_arg, long_double_arg
+ double_arg, long_double_arg, decfloat_arg
};
enum argclass *argclass;
enum argclass this_argclass;
@@ -1928,6 +1929,34 @@
bad = 1;
break;
+ /* DFP Decimal32 types. */
+ case 'H':
+ this_argclass = decfloat_arg;
+
+#ifndef PRINTF_HAS_DECFLOAT
+ if (lcount || seen_h || seen_big_l)
+ bad = 1;
+ if (seen_prec || seen_zero || seen_space || seen_plus)
+ bad = 1;
+#endif
+ break;
+
+ /* DFP Decimal64 and Decimal128 types. */
+ case 'D':
+ this_argclass = decfloat_arg;
+
+#ifndef PRINTF_HAS_DECFLOAT
+ if (lcount || seen_h || seen_big_l)
+ bad = 1;
+ if (seen_prec || seen_zero || seen_space || seen_plus)
+ bad = 1;
+#endif
+ /* Check for a Decimal128. */
+ if (*(f + 1) == 'D')
+ f++;
+
+ break;
+
case 'c':
this_argclass = int_arg;
if (lcount || seen_h || seen_big_l)
@@ -2094,6 +2123,55 @@
printf_filtered (current_substring, val);
break;
}
+
+ /* Handles decimal floating point values. */
+ case decfloat_arg:
+ {
+ char *eos;
+ char decstr[128];
+ unsigned int dfp_len = TYPE_LENGTH (value_type (val_args[i]));
+ unsigned char *dfp_value_ptr = (unsigned char *) value_contents_all (val_args[i])
+ + value_offset (val_args[i]);
+
+#if defined (PRINTF_HAS_DECFLOAT)
+ printf_filtered (current_substring, dfp_value_ptr);
+#else
+ if (TYPE_CODE (value_type (val_args[i])) != TYPE_CODE_DECFLOAT)
+ error (_("Cannot convert parameter to decfloat."));
+
+ /* As a workaround until vasprintf has native support for DFP
+ we convert the DFP values to string and print them using
+ the %s format specifier. */
+ decimal_to_string (dfp_value_ptr, dfp_len, decstr);
+
+ /* Points to the end of the string so that we can go back
+ and check for DFP format specifiers. */
+ eos = current_substring + strlen (current_substring);
+
+ /* Replace %H, %D and %DD with %s's. */
+ while (*--eos != '%')
+ if (*eos == 'D' && *(eos - 1) == 'D')
+ {
+ *(eos - 1) = 's';
+
+ /* If we've found a %DD format specifier we need to go
+ through the whole string pulling back one character
+ since this format specifier has two chars. */
+ while (eos < last_arg)
+ {
+ *eos = *(eos + 1);
+ eos++;
+ }
+ }
+ else if (*eos == 'D' || *eos == 'H')
+ *eos = 's';
+
+ /* Print the DFP value. */
+ printf_filtered (current_substring, decstr);
+ break;
+#endif
+ }
+
case ptr_arg:
{
/* We avoid the host's %p because pointers are too
Index: git/gdb/configure.ac
===================================================================
--- git.orig/gdb/configure.ac 2007-10-31 15:17:33.000000000 -0700
+++ git/gdb/configure.ac 2007-10-31 15:17:37.000000000 -0700
@@ -928,6 +928,25 @@
[Define to 1 if the "%ll" format works to print long longs.])
fi
+# Check if the compiler and runtime support printing decfloats.
+
+AC_CACHE_CHECK([for decfloat support in printf],
+ gdb_cv_printf_has_decfloat,
+ [AC_RUN_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT],
+[[char buf[64];
+ _Decimal32 d32 = 1.2345df;
+ _Decimal64 d64 = 1.2345dd;
+ _Decimal128 d128 = 1.2345dl;
+ sprintf (buf, "Decimal32: %H\nDecimal64: %D\nDecimal128: %DD", d32, d64, d128);
+ return (strcmp ("Decimal32: 1.2345\nDecimal64: 1.2345\nDecimal128: 1.2345", buf));]])],
+ gdb_cv_printf_has_decfloat=yes,
+ gdb_cv_printf_has_decfloat=no,
+ gdb_cv_printf_has_decfloat=no)])
+if test $gdb_cv_printf_has_decfloat = yes; then
+ AC_DEFINE(PRINTF_HAS_DECFLOAT, 1,
+ [Define to 1 if the "%H, %D and %DD" formats work to print decfloats.])
+fi
+
# Check if the compiler supports the `long double' type. We can't use
# AC_C_LONG_DOUBLE because that one does additional checks on the
# constants defined in <float.h> that fail on some systems,
Index: git/gdb/configure
===================================================================
--- git.orig/gdb/configure 2007-10-31 15:17:33.000000000 -0700
+++ git/gdb/configure 2007-10-31 15:17:37.000000000 -0700
@@ -21362,6 +21362,69 @@
fi
+# Check if the compiler and runtime support printing decfloats.
+
+echo "$as_me:$LINENO: checking for decfloat support in printf" >&5
+echo $ECHO_N "checking for decfloat support in printf... $ECHO_C" >&6
+if test "${gdb_cv_printf_has_decfloat+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ gdb_cv_printf_has_decfloat=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[64];
+ _Decimal32 d32 = 1.2345df;
+ _Decimal64 d64 = 1.2345dd;
+ _Decimal128 d128 = 1.2345dl;
+ sprintf (buf, "Decimal32: %H\nDecimal64: %D\nDecimal128: %DD", d32, d64, d128);
+ return (strcmp ("Decimal32: 1.2345\nDecimal64: 1.2345\nDecimal128: 1.2345", buf));
+ ;
+ 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_decfloat=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_decfloat=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_decfloat" >&5
+echo "${ECHO_T}$gdb_cv_printf_has_decfloat" >&6
+if test $gdb_cv_printf_has_decfloat = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define PRINTF_HAS_DECFLOAT 1
+_ACEOF
+
+fi
+
# Check if the compiler supports the `long double' type. We can't use
# AC_C_LONG_DOUBLE because that one does additional checks on the
# constants defined in <float.h> that fail on some systems,
Index: git/gdb/doc/gdb.texinfo
===================================================================
--- git.orig/gdb/doc/gdb.texinfo 2007-10-25 12:48:45.000000000 -0700
+++ git/gdb/doc/gdb.texinfo 2007-11-01 04:50:27.000000000 -0700
@@ -16539,6 +16539,34 @@
@samp{\a}, and @samp{\f}, that consist of backslash followed by a
single character. Octal and hexadecimal escape sequences are not
supported.
+
+Additionally, @code{printf} supports conversion specifications for DFP
+(@dfn{Decimal Floating Point}) types using the following conversion
+letters:
+
+@itemize @bullet
+@item
+@samp{H} for printing Decimal32 types.
+
+@item
+@samp{D} for printing Decimal64 types.
+
+@item
+@samp{DD} for printing Decimal128 types.
+@end itemize
+
+If the underlying @code{C} implementation used to build @value{GDBN} has
+support for the three conversion letters for DFP types, other modifiers
+such as width and precision will also be available for @value{GDB} to use.
+
+In case there is no such @code{C} support, no additional modifiers will be
+available and the value will be printed in the standard way.
+
+Here's an example of printing DFP types using the above conversion letters:
+@smallexample
+printf "D32: %H - D64: %D - D128: %DD\n",1.2345df,1.2E10dd,1.2E1dl
+@end smallexample
+
@end table
@node Interpreters
Index: git/gdb/testsuite/gdb.base/printcmds.exp
===================================================================
--- git.orig/gdb/testsuite/gdb.base/printcmds.exp 2007-10-31 17:46:12.000000000 -0700
+++ git/gdb/testsuite/gdb.base/printcmds.exp 2007-10-31 18:08:39.000000000 -0700
@@ -668,6 +668,57 @@
0xfeedface, 0xdeadbeef, 5.0" "bad -99.54\[0-9\]+, z feedface, deadbeef, 5.0+"
}
+#Test printing DFP values with printf
+proc test_printf_with_dfp {} {
+
+ # Test various dfp values, covering 32-bit, 64-bit and 128-bit ones
+
+ # _Decimal32 constants, which can support up to 7 digits
+ gdb_test "printf \"%H\\n\",1.2df" "1.2"
+ gdb_test "printf \"%H\\n\",-1.2df" "-1.2"
+ gdb_test "printf \"%H\\n\",1.234567df" "1.234567"
+ gdb_test "printf \"%H\\n\",-1.234567df" "-1.234567"
+ gdb_test "printf \"%H\\n\",1234567.df" "1234567"
+ gdb_test "printf \"%H\\n\",-1234567.df" "-1234567"
+
+ gdb_test "printf \"%H\\n\",1.2E1df" "12"
+ gdb_test "printf \"%H\\n\",1.2E10df" "1.2E\\+10"
+ gdb_test "printf \"%H\\n\",1.2E-10df" "1.2E-10"
+
+ # The largest exponent for 32-bit dfp value is 96.
+ gdb_test "printf \"%H\\n\",1.2E96df" "1.200000E\\+96"
+
+ # _Decimal64 constants, which can support up to 16 digits
+ gdb_test "printf \"%D\\n\",1.2dd" "1.2"
+ gdb_test "printf \"%D\\n\",-1.2dd" "-1.2"
+ gdb_test "printf \"%D\\n\",1.234567890123456dd" "1.234567890123456"
+ gdb_test "printf \"%D\\n\",-1.234567890123456dd" "-1.234567890123456"
+ gdb_test "printf \"%D\\n\",1234567890123456.dd" "1234567890123456"
+ gdb_test "printf \"%D\\n\",-1234567890123456.dd" "-1234567890123456"
+
+ gdb_test "printf \"%D\\n\",1.2E1dd" "12"
+ gdb_test "printf \"%D\\n\",1.2E10dd" "1.2E\\+10"
+ gdb_test "printf \"%D\\n\",1.2E-10dd" "1.2E-10"
+
+ # The largest exponent for 64-bit dfp value is 384.
+ gdb_test "printf \"%D\\n\",1.2E384dd" "1.200000000000000E\\+384"
+
+ # _Decimal128 constants, which can support up to 34 digits
+ gdb_test "printf \"%DD\\n\",1.2dl" "1.2"
+ gdb_test "printf \"%DD\\n\",-1.2dl" "-1.2"
+ gdb_test "printf \"%DD\\n\",1.234567890123456789012345678901234dl" "1.234567890123456789012345678901234"
+ gdb_test "printf \"%DD\\n\",-1.234567890123456789012345678901234dl" "-1.234567890123456789012345678901234"
+ gdb_test "printf \"%DD\\n\",1234567890123456789012345678901234.dl" "1234567890123456789012345678901234"
+ gdb_test "printf \"%DD\\n\",-1234567890123456789012345678901234.dl" "-1234567890123456789012345678901234"
+
+ gdb_test "printf \"%DD\\n\",1.2E1dl" "12"
+ gdb_test "printf \"%DD\\n\",1.2E10dl" "1.2E\\+10"
+ gdb_test "printf \"%DD\\n\",1.2E-10dl" "1.2E-10"
+
+ # The largest exponent for 128-bit dfp value is 6144.
+ gdb_test "printf \"%DD\\n\",1.2E6144dl" "1.200000000000000000000000000000000E\\+6144"
+}
+
# Escape a left curly brace to prevent it from being interpreted as
# the beginning of a bound
proc gdb_test_escape_braces { args } {
@@ -711,6 +762,7 @@
test_print_string_constants
test_print_array_constants
test_printf
+ test_printf_with_dfp
}
} else {
fail "C print command tests suppressed"