From: Luis Machado Date: Mon, 5 Nov 2007 11:32:31 +0000 (+0000) Subject: * printcmd.c: (printf_command): Add support for new DFP X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1a619819d6cb85f66a81d3ca146a960c679edfa4;p=binutils-gdb.git * 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. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index bcc0b1f7447..df6053477dd 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +2007-11-05 Luis Machado + + * printcmd.c: (printf_command): Add support for new DFP + modifiers %H, %D and %DD. + * configure.ac: Add check for DECFLOAT printf support. + * configure: Regenerated. + 2007-11-02 Ulrich Weigand * gdbtypes.h (struct cplus_struct_type): Remove runtime_ptr member. diff --git a/gdb/configure b/gdb/configure index ea652973bcc..bcd75e9e636 100755 --- a/gdb/configure +++ b/gdb/configure @@ -21362,6 +21362,69 @@ _ACEOF 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 that fail on some systems, diff --git a/gdb/configure.ac b/gdb/configure.ac index eab68b07818..d20329c62d1 100644 --- a/gdb/configure.ac +++ b/gdb/configure.ac @@ -928,6 +928,25 @@ if test $gdb_cv_printf_has_long_long = yes; then [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 that fail on some systems, diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 83d679fe2ac..61aad5a8b25 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,7 @@ +2007-11-05 Luis Machado + + * gdb.texinfo: Update printf command's description. + 2007-10-30 Daniel Jacobowitz * gdb.texinfo (PowerPC): Document "set powerpc vector-abi" and "set diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 83c768098ac..f26393e0f72 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -16557,6 +16557,34 @@ sequences, such as @code{\n}, @samp{\t}, @samp{\\}, @samp{\"}, @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 @code{Decimal32} types. + +@item +@samp{D} for printing @code{Decimal64} types. + +@item +@samp{DD} for printing @code{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 diff --git a/gdb/printcmd.c b/gdb/printcmd.c index 04cfd771877..20957275947 100644 --- a/gdb/printcmd.c +++ b/gdb/printcmd.c @@ -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 @@ printf_command (char *arg, int from_tty) 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 @@ printf_command (char *arg, int from_tty) 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_command (char *arg, int from_tty) 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 diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 97490244f64..290ec1b8633 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2007-11-05 Luis Machado + + * gdb.base/printcmds.exp: New function + test_printf_with_dfp. + 2007-11-02 Doug Evans * gdb.disasm/t01_mov.s: Remove carriage returns. diff --git a/gdb/testsuite/gdb.base/printcmds.exp b/gdb/testsuite/gdb.base/printcmds.exp index a44db01676c..77451160f59 100644 --- a/gdb/testsuite/gdb.base/printcmds.exp +++ b/gdb/testsuite/gdb.base/printcmds.exp @@ -668,6 +668,57 @@ proc test_printf {} { 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 @@ if [set_lang_c] then { test_print_string_constants test_print_array_constants test_printf + test_printf_with_dfp } } else { fail "C print command tests suppressed"