From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 11233 invoked by alias); 8 Jan 2008 13:28:17 -0000 Received: (qmail 11223 invoked by uid 22791); 8 Jan 2008 13:28:14 -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; Tue, 08 Jan 2008 13:27:50 +0000 Received: from mailhub1.br.ibm.com (mailhub1 [9.18.232.109]) by igw2.br.ibm.com (Postfix) with ESMTP id 3200317F537 for ; Tue, 8 Jan 2008 11:22:10 -0200 (BRDT) Received: from d24av01.br.ibm.com (d24av01.br.ibm.com [9.18.232.46]) by mailhub1.br.ibm.com (8.13.8/8.13.8/NCO v8.7) with ESMTP id m08DRjHt3473472 for ; Tue, 8 Jan 2008 11:27:45 -0200 Received: from d24av01.br.ibm.com (loopback [127.0.0.1]) by d24av01.br.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id m08DRinP017869 for ; Tue, 8 Jan 2008 11:27:45 -0200 Received: from [9.8.14.212] ([9.8.14.212]) by d24av01.br.ibm.com (8.12.11.20060308/8.12.11) with ESMTP id m08DRgpm017640 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Tue, 8 Jan 2008 11:27:42 -0200 Subject: [PATCH] Improve printf DFP support From: Luis Machado Reply-To: luisgpm@linux.vnet.ibm.com To: gdb-patches@sourceware.org Content-Type: multipart/mixed; boundary="=-LTivLZPJKJSv9lWPo2JL" Date: Tue, 08 Jan 2008 13:28:00 -0000 Message-Id: <1199798856.22083.9.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/msg00127.txt.bz2 --=-LTivLZPJKJSv9lWPo2JL Content-Type: text/plain Content-Transfer-Encoding: 7bit Content-length: 492 Hi folks, This is an improvement over the last patch i have submited to add DFP support for GDB's printf command. The DFP modifiers are now being treated as length modifiers, and not type modifiers. This puts us in agreement with what the C99 standard's DFP annex says. The parsing of the string is a bit more robust than the last version. A documentation and testcase updated is attached as well. Comments? Best regards, -- Luis Machado Software Engineer IBM Linux Technology Center --=-LTivLZPJKJSv9lWPo2JL 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: 13412 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: 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 04:52:15.000000000 -0800 +++ gdb/printcmd.c 2008-01-08 05:23:52.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,103 @@ 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]) + gdb_byte *param_ptr = (gdb_byte *) value_contents_all (val_args[i]) + value_offset (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_all (dfp_value) + + value_offset (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 04:52:15.000000000 -0800 +++ gdb/doc/gdb.texinfo 2008-01-08 04:56:54.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 04:52:15.000000000 -0800 +++ gdb/testsuite/gdb.base/printcmds.exp 2008-01-08 04:56:54.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 --=-LTivLZPJKJSv9lWPo2JL--