Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [PATCH] Improve printf DFP support
@ 2008-01-08 13:28 Luis Machado
  2008-01-08 15:19 ` Thiago Jung Bauermann
  2008-01-08 20:42 ` Eli Zaretskii
  0 siblings, 2 replies; 10+ messages in thread
From: Luis Machado @ 2008-01-08 13:28 UTC (permalink / raw)
  To: gdb-patches

[-- 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 

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2008-01-09 13:51 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-01-08 13:28 [PATCH] Improve printf DFP support Luis Machado
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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox