This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] printf support for DFP values


Hi folks,

Libdecnumber has been already integrated into GDB, but there are still
some missing features that must be addressed for DFP types.

GDB's printf command currently does not support printing of DFP values
(Decimal32, Decimal64 and Decimal128). The following patch proposes to
fix that by allowing GDB's printf command to deal with those numbers.

Native DFP printing support with printf is not yet ready, but it should
be in some time eventually. Due to this, i'm testing for native printf
support for DFP in the configure script and setting a constant to
reflect the result (PRINTF_HAS_DECFLOAT). Based on that GDB has two ways
of dealing with the problem:

1 - If we have native support (and thus PRINTF_HAS_DECFLOAT is set), we
just send the DFP value straight to the standard printing routine with
its format specifiers (printf_filtered).

2 - If there's currently no support, we stick with converting the DFP
values to strings and using string format specifiers to print them. This
should make things flexible enough for both systems, one that has native
printf support for DFP and one that doesn't.

I'd appreciate comments on this one.

Regards,
Luis
2007-10-26  Luis Machado  <luisgpm@br.ibm.com>

  * printcmd.c: (printf_command): Add new DFP modifiers %H, %D and
    %DD.
  * configure.ac: Add check for DECFLOAT printf support.
  * configure: Regenerated.

Index: git/gdb/printcmd.c
===================================================================
--- git.orig/gdb/printcmd.c	2007-10-26 17:43:36.000000000 -0700
+++ git/gdb/printcmd.c	2007-10-26 17:58:07.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,31 @@
 		bad = 1;
 	      break;
 
+	    /* DFP Decimal32 types.  */
+	    case 'H':
+	      this_argclass = decfloat_arg;
+
+              if (lcount || seen_h || seen_big_l)
+                bad = 1;
+              if (seen_prec || seen_zero || seen_space || seen_plus)
+                bad = 1;
+	      break;
+
+	    /* DFP Decimal64 and Decimal128 types.  */
+	    case 'D':
+	      this_argclass = decfloat_arg;
+
+              if (lcount || seen_h || seen_big_l)
+                bad = 1;
+              if (seen_prec || seen_zero || seen_space || seen_plus)
+                bad = 1;
+
+	      if (*(++f) == 'D')
+		printf_unfiltered("\nDecimal 128\n");
+	      else
+		printf_unfiltered("\nDecimal 64\n");
+	      break;
+
 	    case 'c':
 	      this_argclass = int_arg;
 	      if (lcount || seen_h || seen_big_l)
@@ -2094,6 +2120,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]));
+	      uint8_t *dfp_value_ptr = (uint8_t *) 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 for %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-26 17:43:36.000000000 -0700
+++ git/gdb/configure.ac	2007-10-26 17:52:25.000000000 -0700
@@ -927,6 +927,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 <float.h> that fail on some systems,
Index: git/gdb/configure
===================================================================
--- git.orig/gdb/configure	2007-10-26 17:43:36.000000000 -0700
+++ git/gdb/configure	2007-10-26 17:59:22.000000000 -0700
@@ -21132,6 +21132,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 <float.h> that fail on some systems,

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]