From: Luis Machado <luisgpm@linux.vnet.ibm.com>
To: gdb-patches@sourceware.org
Subject: [PATCH] Improve printf DFP support
Date: Tue, 08 Jan 2008 13:28:00 -0000 [thread overview]
Message-ID: <1199798856.22083.9.camel@gargoyle> (raw)
[-- Attachment #1: Type: text/plain, Size: 492 bytes --]
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
[-- Attachment #2: dfp-printf.diff --]
[-- Type: text/x-patch, Size: 13412 bytes --]
2008-08-01 Luis Machado <luisgpm@br.ibm.com>
* 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
next reply other threads:[~2008-01-08 13:28 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-01-08 13:28 Luis Machado [this message]
2008-01-08 15:19 ` Thiago Jung Bauermann
2008-01-08 15:29 ` Daniel Jacobowitz
2008-01-08 23:54 ` Jim Blandy
2008-01-08 15:29 ` Luis Machado
2008-01-08 20:42 ` Eli Zaretskii
2008-01-09 0:04 ` Luis Machado
2008-01-09 4:14 ` Eli Zaretskii
2008-01-09 12:52 ` Daniel Jacobowitz
2008-01-09 13:51 ` Luis Machado
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1199798856.22083.9.camel@gargoyle \
--to=luisgpm@linux.vnet.ibm.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox