2008-04-23 Andrew Stubbs <andrew.stubbs@st.com>
[deliverable/binutils-gdb.git] / gdb / printcmd.c
index 51b5efc115765c79f9b7c1fe24772ee7903561f0..26a54cbb70f60b29935fdd765710e3996d7c2ce9 100644 (file)
 #include "tui/tui.h"           /* For tui_active et.al.   */
 #endif
 
+#if defined(__MINGW32__)
+# define USE_PRINTF_I64 1
+# define PRINTF_HAS_LONG_LONG
+#else
+# define USE_PRINTF_I64 0
+#endif
+
 extern int asm_demangle;       /* Whether to demangle syms in asm printouts */
 extern int addressprint;       /* Whether to print hex addresses in HLL " */
 
@@ -285,6 +292,7 @@ print_formatted (struct value *val, int format, int size,
     }
 
   if (format == 0 || format == 's'
+      || TYPE_CODE (type) == TYPE_CODE_REF
       || TYPE_CODE (type) == TYPE_CODE_ARRAY
       || TYPE_CODE (type) == TYPE_CODE_STRING
       || TYPE_CODE (type) == TYPE_CODE_STRUCT
@@ -691,7 +699,7 @@ deprecated_print_address_numeric (CORE_ADDR addr, int use_local,
 void
 print_address (CORE_ADDR addr, struct ui_file *stream)
 {
-  deprecated_print_address_numeric (addr, 1, stream);
+  fputs_filtered (paddress (addr), stream);
   print_address_symbolic (addr, stream, asm_demangle, " ");
 }
 
@@ -710,7 +718,7 @@ print_address_demangle (CORE_ADDR addr, struct ui_file *stream,
     }
   else if (addressprint)
     {
-      deprecated_print_address_numeric (addr, 1, stream);
+      fputs_filtered (paddress (addr), stream);
       print_address_symbolic (addr, stream, do_demangle, " ");
     }
   else
@@ -1068,14 +1076,14 @@ address_info (char *exp, int from_tty)
          fprintf_symbol_filtered (gdb_stdout, exp,
                                   current_language->la_language, DMGL_ANSI);
          printf_filtered ("\" is at ");
-         deprecated_print_address_numeric (load_addr, 1, gdb_stdout);
+         fputs_filtered (paddress (load_addr), gdb_stdout);
          printf_filtered (" in a file compiled without debugging");
          section = SYMBOL_BFD_SECTION (msymbol);
          if (section_is_overlay (section))
            {
              load_addr = overlay_unmapped_address (load_addr, section);
              printf_filtered (",\n -- loaded at ");
-             deprecated_print_address_numeric (load_addr, 1, gdb_stdout);
+             fputs_filtered (paddress (load_addr), gdb_stdout);
              printf_filtered (" in overlay section %s", section->name);
            }
          printf_filtered (".\n");
@@ -1102,13 +1110,13 @@ address_info (char *exp, int from_tty)
 
     case LOC_LABEL:
       printf_filtered ("a label at address ");
-      deprecated_print_address_numeric (load_addr = SYMBOL_VALUE_ADDRESS (sym),
-                            1, gdb_stdout);
+      fputs_filtered (paddress (load_addr = SYMBOL_VALUE_ADDRESS (sym)),
+                     gdb_stdout);
       if (section_is_overlay (section))
        {
          load_addr = overlay_unmapped_address (load_addr, section);
          printf_filtered (",\n -- loaded at ");
-         deprecated_print_address_numeric (load_addr, 1, gdb_stdout);
+         fputs_filtered (paddress (load_addr), gdb_stdout);
          printf_filtered (" in overlay section %s", section->name);
        }
       break;
@@ -1130,27 +1138,27 @@ address_info (char *exp, int from_tty)
 
     case LOC_STATIC:
       printf_filtered (_("static storage at address "));
-      deprecated_print_address_numeric (load_addr = SYMBOL_VALUE_ADDRESS (sym),
-                            1, gdb_stdout);
+     fputs_filtered (paddress (load_addr = SYMBOL_VALUE_ADDRESS (sym)),
+                    gdb_stdout);
       if (section_is_overlay (section))
        {
          load_addr = overlay_unmapped_address (load_addr, section);
          printf_filtered (_(",\n -- loaded at "));
-         deprecated_print_address_numeric (load_addr, 1, gdb_stdout);
+         fputs_filtered (paddress (load_addr), gdb_stdout);
          printf_filtered (_(" in overlay section %s"), section->name);
        }
       break;
 
     case LOC_INDIRECT:
       printf_filtered (_("external global (indirect addressing), at address *("));
-      deprecated_print_address_numeric (load_addr = SYMBOL_VALUE_ADDRESS (sym),
-                            1, gdb_stdout);
+      fputs_filtered (paddress (load_addr = SYMBOL_VALUE_ADDRESS (sym)),
+                     gdb_stdout);
       printf_filtered (")");
       if (section_is_overlay (section))
        {
          load_addr = overlay_unmapped_address (load_addr, section);
          printf_filtered (_(",\n -- loaded at "));
-         deprecated_print_address_numeric (load_addr, 1, gdb_stdout);
+         fputs_filtered (paddress (load_addr), gdb_stdout);
          printf_filtered (_(" in overlay section %s"), section->name);
        }
       break;
@@ -1198,12 +1206,12 @@ address_info (char *exp, int from_tty)
     case LOC_BLOCK:
       printf_filtered (_("a function at address "));
       load_addr = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
-      deprecated_print_address_numeric (load_addr, 1, gdb_stdout);
+      fputs_filtered (paddress (load_addr), gdb_stdout);
       if (section_is_overlay (section))
        {
          load_addr = overlay_unmapped_address (load_addr, section);
          printf_filtered (_(",\n -- loaded at "));
-         deprecated_print_address_numeric (load_addr, 1, gdb_stdout);
+         fputs_filtered (paddress (load_addr), gdb_stdout);
          printf_filtered (_(" in overlay section %s"), section->name);
        }
       break;
@@ -1220,12 +1228,12 @@ address_info (char *exp, int from_tty)
            section = SYMBOL_BFD_SECTION (msym);
            printf_filtered (_("static storage at address "));
            load_addr = SYMBOL_VALUE_ADDRESS (msym);
-           deprecated_print_address_numeric (load_addr, 1, gdb_stdout);
+           fputs_filtered (paddress (load_addr), gdb_stdout);
            if (section_is_overlay (section))
              {
                load_addr = overlay_unmapped_address (load_addr, section);
                printf_filtered (_(",\n -- loaded at "));
-               deprecated_print_address_numeric (load_addr, 1, gdb_stdout);
+               fputs_filtered (paddress (load_addr), gdb_stdout);
                printf_filtered (_(" in overlay section %s"), section->name);
              }
          }
@@ -1837,7 +1845,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 +1910,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 +1958,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 +1987,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;
@@ -2013,8 +2016,23 @@ printf_command (char *arg, int from_tty)
                   *f);
 
          f++;
-         strncpy (current_substring, last_arg, f - last_arg);
-         current_substring += f - last_arg;
+
+         if (lcount > 1 && USE_PRINTF_I64)
+           {
+             /* Windows' printf does support long long, but not the usual way.
+                Convert %lld to %I64d.  */
+             int length_before_ll = f - last_arg - 1 - lcount;
+             strncpy (current_substring, last_arg, length_before_ll);
+             strcpy (current_substring + length_before_ll, "I64");
+             current_substring[length_before_ll + 3] =
+               last_arg[length_before_ll + lcount];
+             current_substring += length_before_ll + 4;
+           }
+         else
+           {
+             strncpy (current_substring, last_arg, f - last_arg);
+             current_substring += f - last_arg;
+           }
          *current_substring++ = '\0';
          last_arg = f;
          argclass[nargs_wanted++] = this_argclass;
@@ -2124,50 +2142,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
            }
This page took 0.030271 seconds and 4 git commands to generate.