* printcmd.c: (printf_command): Add support for new DFP
authorLuis Machado <luisgpm@br.ibm.com>
Mon, 5 Nov 2007 11:32:31 +0000 (11:32 +0000)
committerLuis Machado <luisgpm@br.ibm.com>
Mon, 5 Nov 2007 11:32:31 +0000 (11:32 +0000)
    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.

gdb/ChangeLog
gdb/configure
gdb/configure.ac
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/printcmd.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/printcmds.exp

index bcc0b1f74470c5e2d04b3c779aa5e656b6df14d1..df6053477ddfc7d15f662a011d4f6c007459857d 100644 (file)
@@ -1,3 +1,10 @@
+2007-11-05  Luis Machado  <luisgpm@br.ibm.com>
+
+       * 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  <uweigand@de.ibm.com>
 
        * gdbtypes.h (struct cplus_struct_type): Remove runtime_ptr member.
index ea652973bcc2b6aba41eaac2363a959c66990b3a..bcd75e9e6362a3d3765d194c2f8facfbba0a834f 100755 (executable)
@@ -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 <float.h> that fail on some systems,
index eab68b07818eefd12531b75f75bcdb88e0262c13..d20329c62d1a79a60f954feaf2555b6125b24668 100644 (file)
@@ -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 <float.h> that fail on some systems,
index 83d679fe2ac8e35742d44c8b86acf2287400f8ef..61aad5a8b252b98d3debe1fe081cd7dff9e59ab7 100644 (file)
@@ -1,3 +1,7 @@
+2007-11-05  Luis Machado  <luisgpm@br.ibm.com>
+
+       * gdb.texinfo: Update printf command's description.
+
 2007-10-30  Daniel Jacobowitz  <dan@codesourcery.com>
 
        * gdb.texinfo (PowerPC): Document "set powerpc vector-abi" and "set
index 83c768098ac770f64b55e6fdea49c93d7596a0c8..f26393e0f727676370b041f1062e6de734285628 100644 (file)
@@ -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
index 04cfd771877f2a442d230390ba748480b925dad4..209572759470e92aeafcd7a35919660a3e0e95d3 100644 (file)
@@ -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
index 97490244f64c3886e21cd6e943647077c2313f5b..290ec1b8633bce3e8d37419159eccbac3b622705 100644 (file)
@@ -1,3 +1,8 @@
+2007-11-05  Luis Machado  <luisgpm@br.ibm.com>
+
+       * gdb.base/printcmds.exp: New function
+       test_printf_with_dfp.
+
 2007-11-02  Doug Evans  <dje@google.com>
 
        * gdb.disasm/t01_mov.s: Remove carriage returns.
index a44db01676c5c1d7aceefc958b2c84ab0eb15fc7..77451160f59632c62cf2a55558632bdb78e40e58 100644 (file)
@@ -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"