From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 23695 invoked by alias); 9 Jan 2008 00:04:17 -0000 Received: (qmail 23684 invoked by uid 22791); 9 Jan 2008 00:04:15 -0000 X-Spam-Check-By: sourceware.org Received: from igw3.br.ibm.com (HELO igw3.br.ibm.com) (32.104.18.26) by sourceware.org (qpsmtpd/0.31) with ESMTP; Wed, 09 Jan 2008 00:03:52 +0000 Received: from mailhub3.br.ibm.com (unknown [9.18.232.110]) by igw3.br.ibm.com (Postfix) with ESMTP id 6829E390206 for ; Tue, 8 Jan 2008 21:56:00 -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.7) with ESMTP id m0903nxw3764416 for ; Tue, 8 Jan 2008 22:03:49 -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 m0903mOG007131 for ; Tue, 8 Jan 2008 22:03:48 -0200 Received: from [9.8.14.212] ([9.8.14.212]) by d24av02.br.ibm.com (8.12.11.20060308/8.12.11) with ESMTP id m0903lhd007111 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Tue, 8 Jan 2008 22:03:47 -0200 Subject: Re: [PATCH] Improve printf DFP support From: Luis Machado Reply-To: luisgpm@linux.vnet.ibm.com To: Eli Zaretskii Cc: gdb-patches@sourceware.org In-Reply-To: References: <1199798856.22083.9.camel@gargoyle> Content-Type: multipart/mixed; boundary="=-AMwOjcngerw/42+Lcjje" Date: Wed, 09 Jan 2008 00:04:00 -0000 Message-Id: <1199837025.22083.13.camel@gargoyle> Mime-Version: 1.0 X-Mailer: Evolution 2.12.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: 2008-01/txt/msg00169.txt.bz2 --=-AMwOjcngerw/42+Lcjje Content-Type: text/plain Content-Transfer-Encoding: 7bit Content-length: 272 > Thanks. The documentation part of the patch is approved, but please > include in the ChangeLog entry the name of the node where you make the > change, as if it were a function. Thanks. Like so? Regards, -- Luis Machado Software Engineer IBM Linux Technology Center --=-AMwOjcngerw/42+Lcjje Content-Disposition: attachment; filename=dfp-printf.diff Content-Type: text/x-patch; name=dfp-printf.diff; charset=utf-8 Content-Transfer-Encoding: 7bit Content-length: 13369 2008-08-01 Luis Machado * printcmd.c (printf_command): Add seen_big_h, seen_big_d and seen_double_big_d, treat the new H, D, and DD modifiers as length modifiers. * doc/gdb.texinfo (Output): Update documentation on using printf with DFP types. * testsuite/gdb.base/printcmds.exp (test_printf_with_dfp): Update printf calls with required float modifiers. Index: gdb/printcmd.c =================================================================== --- gdb.orig/printcmd.c 2008-01-08 07:03:19.000000000 -0800 +++ gdb/printcmd.c 2008-01-08 07:26:28.000000000 -0800 @@ -1837,7 +1837,8 @@ { int seen_hash = 0, seen_zero = 0, lcount = 0, seen_prec = 0; int seen_space = 0, seen_plus = 0; - int seen_big_l = 0, seen_h = 0; + int seen_big_l = 0, seen_h = 0, seen_big_h = 0; + int seen_big_d = 0, seen_double_big_d = 0; int bad = 0; /* Check the validity of the format specifier, and work @@ -1901,6 +1902,26 @@ seen_big_l = 1; f++; } + /* Decimal32 modifier. */ + else if (*f == 'H') + { + seen_big_h = 1; + f++; + } + /* Decimal64 and Decimal128 modifiers. */ + else if (*f == 'D') + { + f++; + + /* Check for a Decimal128. */ + if (*f == 'D') + { + f++; + seen_double_big_d = 1; + } + else + seen_big_d = 1; + } switch (*f) { @@ -1929,34 +1950,6 @@ 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) @@ -1986,7 +1979,9 @@ case 'g': case 'E': case 'G': - if (seen_big_l) + if (seen_big_h || seen_big_d || seen_double_big_d) + this_argclass = decfloat_arg; + else if (seen_big_l) this_argclass = long_double_arg; else this_argclass = double_arg; @@ -2124,50 +2119,101 @@ break; } - /* Handles decimal floating point values. */ + /* Handles decimal floating values. */ case decfloat_arg: { - char *eos; - char decstr[MAX_DECIMAL_STRING]; - 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]); - + const gdb_byte *param_ptr = value_contents (val_args[i]); #if defined (PRINTF_HAS_DECFLOAT) - printf_filtered (current_substring, dfp_value_ptr); + /* If we have native support for Decimal floating + printing, handle it here. */ + printf_filtered (current_substring, param_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'; + /* 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. */ + + char *eos, *sos; + int nnull_chars = 0; + + /* Parameter data. */ + struct type *param_type = value_type (val_args[i]); + unsigned int param_len = TYPE_LENGTH (param_type); + + /* DFP output data. */ + struct value *dfp_value = NULL; + gdb_byte *dfp_ptr; + int dfp_len = 16; + gdb_byte dec[16]; + struct type *dfp_type = NULL; + char decstr[MAX_DECIMAL_STRING]; + + /* Points to the end of the string so that we can go back + and check for DFP length modifiers. */ + eos = current_substring + strlen (current_substring); + + /* Look for the float/double format specifier. */ + while (*eos != 'f' && *eos != 'e' && *eos != 'E' + && *eos != 'g' && *eos != 'G') + eos--; + + sos = eos; + + /* Search for the '%' char and extract the size and type of + the output decimal value based on its modifiers + (%Hf, %Df, %DDf). */ + while (*--sos != '%') + { + if (*sos == 'H') + { + dfp_len = 4; + dfp_type = builtin_type (current_gdbarch)->builtin_decfloat; + } + else if (*sos == 'D' && *(sos - 1) == 'D') + { + dfp_len = 16; + dfp_type = builtin_type (current_gdbarch)->builtin_declong; + sos--; + } + else + { + dfp_len = 8; + dfp_type = builtin_type (current_gdbarch)->builtin_decdouble; + } + } + + /* Replace %Hf, %Df and %DDf with %s's. */ + *++sos = 's'; + + /* Go through the whole format string and pull the correct + number of chars back to compensate for the change in the + format specifier. */ + while (nnull_chars < nargs - i) + { + if (*eos == '\0') + nnull_chars++; + + *++sos = *++eos; + } + + /* Conversion between different DFP types. */ + if (TYPE_CODE (param_type) == TYPE_CODE_DECFLOAT) + decimal_convert (param_ptr, param_len, dec, dfp_len); + else + /* If this is a non-trivial conversion, just output 0. + A correct converted value can be displayed by explicitly + casting to a DFP type. */ + decimal_from_string (dec, dfp_len, "0"); + + dfp_value = value_from_decfloat (dfp_type, dec); + + dfp_ptr = (gdb_byte *) value_contents (dfp_value); + + decimal_to_string (dfp_ptr, dfp_len, decstr); /* Print the DFP value. */ printf_filtered (current_substring, decstr); + break; #endif } Index: gdb/doc/gdb.texinfo =================================================================== --- gdb.orig/doc/gdb.texinfo 2008-01-08 07:03:19.000000000 -0800 +++ gdb/doc/gdb.texinfo 2008-01-08 07:03:39.000000000 -0800 @@ -16693,7 +16693,8 @@ supported. Additionally, @code{printf} supports conversion specifications for DFP -(@dfn{Decimal Floating Point}) types using the following conversion +(@dfn{Decimal Floating Point}) types using the following length modifiers +together with a floating point specifier. letters: @itemize @bullet @@ -16708,7 +16709,7 @@ @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 +support for the three length modifiers for DFP types, other modifiers such as width and precision will also be available for @value{GDBN} to use. In case there is no such @code{C} support, no additional modifiers will be @@ -16716,7 +16717,7 @@ 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 +printf "D32: %Hf - D64: %Df - D128: %DDf\n",1.2345df,1.2E10dd,1.2E1dl @end smallexample @end table Index: gdb/testsuite/gdb.base/printcmds.exp =================================================================== --- gdb.orig/testsuite/gdb.base/printcmds.exp 2008-01-08 07:03:19.000000000 -0800 +++ gdb/testsuite/gdb.base/printcmds.exp 2008-01-08 07:03:39.000000000 -0800 @@ -674,49 +674,49 @@ # 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" + gdb_test "printf \"%Hf\\n\",1.2df" "1.2" + gdb_test "printf \"%Hf\\n\",-1.2df" "-1.2" + gdb_test "printf \"%Hf\\n\",1.234567df" "1.234567" + gdb_test "printf \"%Hf\\n\",-1.234567df" "-1.234567" + gdb_test "printf \"%Hf\\n\",1234567.df" "1234567" + gdb_test "printf \"%Hf\\n\",-1234567.df" "-1234567" + + gdb_test "printf \"%Hf\\n\",1.2E1df" "12" + gdb_test "printf \"%Hf\\n\",1.2E10df" "1.2E\\+10" + gdb_test "printf \"%Hf\\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" + gdb_test "printf \"%Hf\\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" + gdb_test "printf \"%Df\\n\",1.2dd" "1.2" + gdb_test "printf \"%Df\\n\",-1.2dd" "-1.2" + gdb_test "printf \"%Df\\n\",1.234567890123456dd" "1.234567890123456" + gdb_test "printf \"%Df\\n\",-1.234567890123456dd" "-1.234567890123456" + gdb_test "printf \"%Df\\n\",1234567890123456.dd" "1234567890123456" + gdb_test "printf \"%Df\\n\",-1234567890123456.dd" "-1234567890123456" + + gdb_test "printf \"%Df\\n\",1.2E1dd" "12" + gdb_test "printf \"%Df\\n\",1.2E10dd" "1.2E\\+10" + gdb_test "printf \"%Df\\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" + gdb_test "printf \"%Df\\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" + gdb_test "printf \"%DDf\\n\",1.2dl" "1.2" + gdb_test "printf \"%DDf\\n\",-1.2dl" "-1.2" + gdb_test "printf \"%DDf\\n\",1.234567890123456789012345678901234dl" "1.234567890123456789012345678901234" + gdb_test "printf \"%DDf\\n\",-1.234567890123456789012345678901234dl" "-1.234567890123456789012345678901234" + gdb_test "printf \"%DDf\\n\",1234567890123456789012345678901234.dl" "1234567890123456789012345678901234" + gdb_test "printf \"%DDf\\n\",-1234567890123456789012345678901234.dl" "-1234567890123456789012345678901234" + + gdb_test "printf \"%DDf\\n\",1.2E1dl" "12" + gdb_test "printf \"%DDf\\n\",1.2E10dl" "1.2E\\+10" + gdb_test "printf \"%DDf\\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" + gdb_test "printf \"%DDf\\n\",1.2E6144dl" "1.200000000000000000000000000000000E\\+6144" } # Escape a left curly brace to prevent it from being interpreted as --=-AMwOjcngerw/42+Lcjje--