* printcmd.c (printf_command): Add seen_big_h, seen_big_d and
authorLuis Machado <luisgpm@br.ibm.com>
Wed, 9 Jan 2008 13:47:59 +0000 (13:47 +0000)
committerLuis Machado <luisgpm@br.ibm.com>
Wed, 9 Jan 2008 13:47:59 +0000 (13:47 +0000)
seen_double_big_d, treat the new H, D, and DD modifiers as length
modifiers.
* doc/gdb.texinfo (Output): Update documentation on using printf with DFP
types.
* testsuite/gdb.base/printcmds.exp (test_printf_with_dfp): Update
printf calls with required float modifiers.

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

index 4d62be790320d11674f80c4a76b2aec61214d769..c6c54eca621f6c32ca2aab507ff196a34670be6b 100644 (file)
@@ -1,3 +1,9 @@
+2008-01-09  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.
+
 2008-01-08  Joel Brobecker  <brobecker@adacore.com>
 
        * dwarf2read.c (read_enumeration_type): Add comment.
index f1ca784d70a594a7325914b8b0a1d51324d593a1..613a5b08213a5383f05282be09aef43f398d066d 100644 (file)
@@ -1,3 +1,8 @@
+2008-01-09  Luis Machado  <luisgpm@br.ibm.com>
+
+       * gdb.texinfo (Output): Update documentation on using printf with DFP
+       types.
+
 2008-01-07  Thiago Jung Bauermann  <bauerman@br.ibm.com>
 
        * gdb.texinfo (C and C++): Add Decimal Floating Point format
index da05dcc701f5780fd2022ccbab3b41538e1ad04f..519b10b50fc77df60ef1fb0cbc504e4351bcacdc 100644 (file)
@@ -16693,7 +16693,8 @@ 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
+(@dfn{Decimal Floating Point}) types using the following length modifiers
+together with a floating point specifier.
 letters:
 
 @itemize @bullet
@@ -16708,7 +16709,7 @@ letters:
 @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 @@ 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
+printf "D32: %Hf - D64: %Df - D128: %DDf\n",1.2345df,1.2E10dd,1.2E1dl
 @end smallexample
 
 @end table
index 51b5efc115765c79f9b7c1fe24772ee7903561f0..c631f5a910b793d15197b2e065639c7304f12c1d 100644 (file)
@@ -1837,7 +1837,8 @@ printf_command (char *arg, int from_tty)
        {
          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 @@ printf_command (char *arg, int from_tty)
              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 @@ 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)
@@ -1986,7 +1979,9 @@ printf_command (char *arg, int from_tty)
            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,101 @@ printf_command (char *arg, int from_tty)
              break;
            }
 
-         /* Handles decimal floating point values.  */
-         case decfloat_arg:
+         /* 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])
-                                      + value_offset (val_args[i]);
-
+             const gdb_byte *param_ptr = value_contents (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);
+              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 format specifiers.  */
+                and check for DFP length modifiers.  */
              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';
+             /* 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 (dfp_value);
+
+             decimal_to_string (dfp_ptr, dfp_len, decstr);
 
              /* Print the DFP value.  */
              printf_filtered (current_substring, decstr);
+
              break;
 #endif
            }
index dc7c11a3632fe35743ea7b67019299e1f32da5d7..bc898caed034ee8d298d8afe00458d3ea6fd7065 100644 (file)
@@ -1,3 +1,8 @@
+2008-01-09  Luis Machado  <luisgpm@br.ibm.com>
+
+       * gdb.base/printcmds.exp (test_printf_with_dfp): Update printf calls
+       with required float modifiers.
+
 2008-01-08  Joel Brobecker  <brobecker@adacore.com>
 
        * gdb.ada/funcall_param: New test program.
index 36bda54c7ce4c24a6c09906e34936494d3feb19f..bad73beec41f70a20545f0240341d7e569836b75 100644 (file)
@@ -674,49 +674,49 @@ 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 \"%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 \"%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.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 \"%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 \"%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.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 \"%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 \"%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.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