From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 4593 invoked by alias); 1 Nov 2007 01:18:54 -0000 Received: (qmail 4579 invoked by uid 22791); 1 Nov 2007 01:18:53 -0000 X-Spam-Check-By: sourceware.org Received: from igw2.br.ibm.com (HELO igw2.br.ibm.com) (32.104.18.25) by sourceware.org (qpsmtpd/0.31) with ESMTP; Thu, 01 Nov 2007 01:18:47 +0000 Received: from mailhub3.br.ibm.com (mailhub3 [9.18.232.110]) by igw2.br.ibm.com (Postfix) with ESMTP id 8CF3517F535 for ; Wed, 31 Oct 2007 23:15:50 -0200 (BRDT) Received: from d24av02.br.ibm.com (d24av02.br.ibm.com [9.18.232.47]) by mailhub3.br.ibm.com (8.13.8/8.13.8/NCO v8.5) with ESMTP id lA11Ih6o2486320 for ; Wed, 31 Oct 2007 23:18:43 -0200 Received: from d24av02.br.ibm.com (loopback [127.0.0.1]) by d24av02.br.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id lA11Ih2M002345 for ; Wed, 31 Oct 2007 22:18:43 -0300 Received: from [9.18.202.219] ([9.18.202.219]) by d24av02.br.ibm.com (8.12.11.20060308/8.12.11) with ESMTP id lA11IePD002320; Wed, 31 Oct 2007 22:18:42 -0300 Subject: Re: [PATCH] printf support for DFP values From: Luis Machado Reply-To: luisgpm@linux.vnet.ibm.com To: Eli Zaretskii Cc: gdb-patches@sourceware.org In-Reply-To: References: <1193449497.6950.22.camel@localhost> <1193669215.4800.10.camel@localhost> <20071029201252.GA21583@caradoc.them.org> <1193753649.4283.5.camel@localhost> Content-Type: multipart/mixed; boundary="=-i0azWQ2CWl0ZjVn+Vzct" Date: Thu, 01 Nov 2007 01:18:00 -0000 Message-Id: <1193879919.4994.2.camel@localhost> Mime-Version: 1.0 X-Mailer: Evolution 2.6.1 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-11/txt/msg00001.txt.bz2 --=-i0azWQ2CWl0ZjVn+Vzct Content-Type: text/plain Content-Transfer-Encoding: 7bit Content-length: 282 Eli, > It's okay to commit this one _when_ the documentation is part of the > patch. How does this manual entry look? I tried to make it clear, but if i missed something please let me know. Regards, -- Luis Machado IBM Linux Technology Center e-mail: luisgpm@linux.vnet.ibm.com --=-i0azWQ2CWl0ZjVn+Vzct Content-Disposition: attachment; filename=printf-dfp.diff Content-Type: text/x-patch; name=printf-dfp.diff; charset=UTF-8 Content-Transfer-Encoding: 7bit Content-length: 11822 2007-10-31 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. * 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-10-31 18:12:39.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 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 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-10-31 18:07:01.000000000 -0700 @@ -16539,6 +16539,35 @@ @samp{\a}, and @samp{\f}, that consist of backslash followed by a single character. Octal and hexadecimal escape sequences are not supported. + +Printf also supports conversion specifications for DFP (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. + +Printing DFP types with the conversion letters seen before works as +the example: + +@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" --=-i0azWQ2CWl0ZjVn+Vzct--