Work around GCC 6.3.1 bug
[deliverable/binutils-gdb.git] / gdb / printcmd.c
index 84f41f5b747a1a345dc15ab95703d737a9595dcf..77a05e5d9f2ec7a0083a2d3b8194fc0ecb4bd3b4 100644 (file)
@@ -48,6 +48,7 @@
 #include "cli/cli-script.h"
 #include "format.h"
 #include "source.h"
+#include "common/byte-vector.h"
 
 #ifdef TUI
 #include "tui/tui.h"           /* For tui_active et al.   */
@@ -157,10 +158,6 @@ static int display_number;
        B ? (TMP = B->next, 1): 0;              \
        B = TMP)
 
-/* Prototypes for exported functions.  */
-
-void _initialize_printcmd (void);
-
 /* Prototypes for local functions.  */
 
 static void do_one_display (struct display *);
@@ -356,47 +353,12 @@ print_scalar_formatted (const gdb_byte *valaddr, struct type *type,
                        int size, struct ui_file *stream)
 {
   struct gdbarch *gdbarch = get_type_arch (type);
-  LONGEST val_long = 0;
   unsigned int len = TYPE_LENGTH (type);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
 
   /* String printing should go through val_print_scalar_formatted.  */
   gdb_assert (options->format != 's');
 
-  if (len > sizeof(LONGEST)
-      && (TYPE_CODE (type) == TYPE_CODE_INT
-         || TYPE_CODE (type) == TYPE_CODE_ENUM))
-    {
-      switch (options->format)
-       {
-       case 'o':
-         print_octal_chars (stream, valaddr, len, byte_order);
-         return;
-       case 'u':
-       case 'd':
-         print_decimal_chars (stream, valaddr, len, !TYPE_UNSIGNED (type),
-                              byte_order);
-         return;
-       case 't':
-         print_binary_chars (stream, valaddr, len, byte_order, size > 0);
-         return;
-       case 'x':
-         print_hex_chars (stream, valaddr, len, byte_order, size > 0);
-         return;
-       case 'z':
-         print_hex_chars (stream, valaddr, len, byte_order, true);
-         return;
-       case 'c':
-         print_char_chars (stream, type, valaddr, len, byte_order);
-         return;
-       default:
-         break;
-       };
-    }
-
-  if (options->format != 'f')
-    val_long = unpack_long (type, valaddr);
-
   /* If the value is a pointer, and pointers and addresses are not the
      same, then at this point, the value's length (in target bytes) is
      gdbarch_addr_bit/TARGET_CHAR_BIT, not TYPE_LENGTH (type).  */
@@ -406,58 +368,97 @@ print_scalar_formatted (const gdb_byte *valaddr, struct type *type,
   /* If we are printing it as unsigned, truncate it in case it is actually
      a negative signed value (e.g. "print/u (short)-1" should print 65535
      (if shorts are 16 bits) instead of 4294967295).  */
-  if (options->format != 'd' || TYPE_UNSIGNED (type))
+  if (options->format != 'c'
+      && (options->format != 'd' || TYPE_UNSIGNED (type)))
     {
-      if (len < sizeof (LONGEST))
-       val_long &= ((LONGEST) 1 << HOST_CHAR_BIT * len) - 1;
+      if (len < TYPE_LENGTH (type) && byte_order == BFD_ENDIAN_BIG)
+       valaddr += TYPE_LENGTH (type) - len;
     }
 
-  switch (options->format)
+  if (size != 0 && (options->format == 'x' || options->format == 't'))
     {
-    case 'x':
-      if (!size)
+      /* Truncate to fit.  */
+      unsigned newlen;
+      switch (size)
        {
-         /* No size specified, like in print.  Print varying # of digits.  */
-         print_longest (stream, 'x', 1, val_long);
+       case 'b':
+         newlen = 1;
+         break;
+       case 'h':
+         newlen = 2;
+         break;
+       case 'w':
+         newlen = 4;
+         break;
+       case 'g':
+         newlen = 8;
+         break;
+       default:
+         error (_("Undefined output size \"%c\"."), size);
        }
-      else
-       switch (size)
-         {
-         case 'b':
-         case 'h':
-         case 'w':
-         case 'g':
-           print_longest (stream, size, 1, val_long);
-           break;
-         default:
-           error (_("Undefined output size \"%c\"."), size);
-         }
-      break;
+      if (newlen < len && byte_order == BFD_ENDIAN_BIG)
+       valaddr += len - newlen;
+      len = newlen;
+    }
 
+  /* Historically gdb has printed floats by first casting them to a
+     long, and then printing the long.  PR cli/16242 suggests changing
+     this to using C-style hex float format.  */
+  gdb::byte_vector converted_float_bytes;
+  if (TYPE_CODE (type) == TYPE_CODE_FLT
+      && (options->format == 'o'
+         || options->format == 'x'
+         || options->format == 't'
+         || options->format == 'z'
+         || options->format == 'd'
+         || options->format == 'u'))
+    {
+      LONGEST val_long = unpack_long (type, valaddr);
+      converted_float_bytes.resize (TYPE_LENGTH (type));
+      store_signed_integer (converted_float_bytes.data (), TYPE_LENGTH (type),
+                           byte_order, val_long);
+      valaddr = converted_float_bytes.data ();
+    }
+
+  switch (options->format)
+    {
+    case 'o':
+      print_octal_chars (stream, valaddr, len, byte_order);
+      break;
     case 'd':
-      print_longest (stream, 'd', 1, val_long);
+      print_decimal_chars (stream, valaddr, len, true, byte_order);
       break;
-
     case 'u':
-      print_longest (stream, 'u', 0, val_long);
+      print_decimal_chars (stream, valaddr, len, false, byte_order);
       break;
-
-    case 'o':
-      print_longest (stream, 'o', 1, val_long);
+    case 0:
+      if (TYPE_CODE (type) != TYPE_CODE_FLT)
+       {
+         print_decimal_chars (stream, valaddr, len, !TYPE_UNSIGNED (type),
+                              byte_order);
+         break;
+       }
+      /* FALLTHROUGH */
+    case 'f':
+      type = float_type_from_length (type);
+      print_floating (valaddr, type, stream);
       break;
 
-    case 'a':
-      {
-       CORE_ADDR addr = unpack_pointer (type, valaddr);
-
-       print_address (gdbarch, addr, stream);
-      }
+    case 't':
+      print_binary_chars (stream, valaddr, len, byte_order, size > 0);
+      break;
+    case 'x':
+      print_hex_chars (stream, valaddr, len, byte_order, size > 0);
+      break;
+    case 'z':
+      print_hex_chars (stream, valaddr, len, byte_order, true);
       break;
-
     case 'c':
       {
        struct value_print_options opts = *options;
 
+       LONGEST val_long = unpack_long (type, valaddr);
+
        opts.format = 0;
        if (TYPE_UNSIGNED (type))
          type = builtin_type (gdbarch)->builtin_true_unsigned_char;
@@ -468,66 +469,14 @@ print_scalar_formatted (const gdb_byte *valaddr, struct type *type,
       }
       break;
 
-    case 'f':
-      type = float_type_from_length (type);
-      print_floating (valaddr, type, stream);
-      break;
-
-    case 0:
-      internal_error (__FILE__, __LINE__,
-                     _("failed internal consistency check"));
-
-    case 't':
-      /* Binary; 't' stands for "two".  */
+    case 'a':
       {
-       char bits[8 * (sizeof val_long) + 1];
-       char buf[8 * (sizeof val_long) + 32];
-       char *cp = bits;
-       int width;
-
-       if (!size)
-         width = 8 * (sizeof val_long);
-       else
-         switch (size)
-           {
-           case 'b':
-             width = 8;
-             break;
-           case 'h':
-             width = 16;
-             break;
-           case 'w':
-             width = 32;
-             break;
-           case 'g':
-             width = 64;
-             break;
-           default:
-             error (_("Undefined output size \"%c\"."), size);
-           }
+       CORE_ADDR addr = unpack_pointer (type, valaddr);
 
-       bits[width] = '\0';
-       while (width-- > 0)
-         {
-           bits[width] = (val_long & 1) ? '1' : '0';
-           val_long >>= 1;
-         }
-       if (!size)
-         {
-           while (*cp && *cp == '0')
-             cp++;
-           if (*cp == '\0')
-             cp--;
-         }
-       strncpy (buf, cp, sizeof (bits));
-       fputs_filtered (buf, stream);
+       print_address (gdbarch, addr, stream);
       }
       break;
 
-    case 'z':
-      print_hex_chars (stream, valaddr, len, byte_order, true);
-      break;
-
     default:
       error (_("Undefined output format \"%c\"."), options->format);
     }
@@ -949,8 +898,6 @@ find_string_backward (struct gdbarch *gdbarch,
                       int *strings_counted)
 {
   const int chunk_size = 0x20;
-  gdb_byte *buffer = NULL;
-  struct cleanup *cleanup = NULL;
   int read_error = 0;
   int chars_read = 0;
   int chars_to_read = chunk_size;
@@ -959,14 +906,13 @@ find_string_backward (struct gdbarch *gdbarch,
   CORE_ADDR string_start_addr = addr;
 
   gdb_assert (char_size == 1 || char_size == 2 || char_size == 4);
-  buffer = (gdb_byte *) xmalloc (chars_to_read * char_size);
-  cleanup = make_cleanup (xfree, buffer);
+  gdb::byte_vector buffer (chars_to_read * char_size);
   while (count > 0 && read_error == 0)
     {
       int i;
 
       addr -= chars_to_read * char_size;
-      chars_read = read_memory_backward (gdbarch, addr, buffer,
+      chars_read = read_memory_backward (gdbarch, addr, buffer.data (),
                                          chars_to_read * char_size);
       chars_read /= char_size;
       read_error = (chars_read == chars_to_read) ? 0 : 1;
@@ -975,7 +921,7 @@ find_string_backward (struct gdbarch *gdbarch,
         {
           int offset = (chars_to_read - i - 1) * char_size;
 
-          if (integer_is_zero (buffer + offset, char_size)
+          if (integer_is_zero (&buffer[offset], char_size)
               || chars_counted == options->print_max)
             {
               /* Found '\0' or reached print_max.  As OFFSET is the offset to
@@ -998,7 +944,6 @@ find_string_backward (struct gdbarch *gdbarch,
       string_start_addr -= chars_counted * char_size;
     }
 
-  do_cleanups (cleanup);
   return string_start_addr;
 }
 
@@ -1317,7 +1262,7 @@ output_command_const (const char *exp, int from_tty)
 }
 
 static void
-set_command (char *exp, int from_tty)
+set_command (const char *exp, int from_tty)
 {
   expression_up expr = parse_expression (exp);
 
@@ -1340,8 +1285,16 @@ set_command (char *exp, int from_tty)
   evaluate_expression (expr.get ());
 }
 
+/* Temporary non-const version of set_command.  */
+
+static void
+non_const_set_command (char *exp, int from_tty)
+{
+  set_command (exp, from_tty);
+}
+
 static void
-sym_info (char *arg, int from_tty)
+info_symbol_command (char *arg, int from_tty)
 {
   struct minimal_symbol *msymbol;
   struct objfile *objfile;
@@ -1369,7 +1322,7 @@ sym_info (char *arg, int from_tty)
            = lookup_minimal_symbol_by_pc_section (sect_addr, osect).minsym))
       {
        const char *obj_name, *mapped, *sec_name, *msym_name;
-       char *loc_string;
+       const char *loc_string;
        struct cleanup *old_chain;
 
        matches = 1;
@@ -1380,14 +1333,14 @@ sym_info (char *arg, int from_tty)
 
        /* Don't print the offset if it is zero.
           We assume there's no need to handle i18n of "sym + offset".  */
+       std::string string_holder;
        if (offset)
-         loc_string = xstrprintf ("%s + %u", msym_name, offset);
+         {
+           string_holder = string_printf ("%s + %u", msym_name, offset);
+           loc_string = string_holder.c_str ();
+         }
        else
-         loc_string = xstrprintf ("%s", msym_name);
-
-       /* Use a cleanup to free loc_string in case the user quits
-          a pagination request inside printf_filtered.  */
-       old_chain = make_cleanup (xfree, loc_string);
+         loc_string = msym_name;
 
        gdb_assert (osect->objfile && objfile_name (osect->objfile));
        obj_name = objfile_name (osect->objfile);
@@ -1425,8 +1378,6 @@ sym_info (char *arg, int from_tty)
            else
              printf_filtered (_("%s in section %s\n"),
                               loc_string, sec_name);
-
-       do_cleanups (old_chain);
       }
   }
   if (matches == 0)
@@ -1434,7 +1385,7 @@ sym_info (char *arg, int from_tty)
 }
 
 static void
-address_info (char *exp, int from_tty)
+info_address_command (char *exp, int from_tty)
 {
   struct gdbarch *gdbarch;
   int regno;
@@ -1661,7 +1612,6 @@ static void
 x_command (char *exp, int from_tty)
 {
   struct format_data fmt;
-  struct cleanup *old_chain;
   struct value *val;
 
   fmt.format = last_format ? last_format : 'x';
@@ -1850,7 +1800,7 @@ delete_display (struct display *display)
    ARGS.  DATA is passed unmodified to FUNCTION.  */
 
 static void
-map_display_numbers (char *args,
+map_display_numbers (const char *args,
                     void (*function) (struct display *,
                                       void *),
                     void *data)
@@ -1895,7 +1845,7 @@ do_delete_display (struct display *d, void *data)
 /* "undisplay" command.  */
 
 static void
-undisplay_command (char *args, int from_tty)
+undisplay_command (const char *args, int from_tty)
 {
   if (args == NULL)
     {
@@ -2101,7 +2051,7 @@ disable_current_display (void)
 }
 
 static void
-display_info (char *ignore, int from_tty)
+info_display_command (char *ignore, int from_tty)
 {
   struct display *d;
 
@@ -2140,7 +2090,7 @@ do_enable_disable_display (struct display *d, void *data)
    commands.  ENABLE decides what to do.  */
 
 static void
-enable_disable_display_command (char *args, int from_tty, int enable)
+enable_disable_display_command (const char *args, int from_tty, int enable)
 {
   if (args == NULL)
     {
@@ -2157,7 +2107,7 @@ enable_disable_display_command (char *args, int from_tty, int enable)
 /* The "enable display" command.  */
 
 static void
-enable_display_command (char *args, int from_tty)
+enable_display_command (const char *args, int from_tty)
 {
   enable_disable_display_command (args, from_tty, 1);
 }
@@ -2165,7 +2115,7 @@ enable_display_command (char *args, int from_tty)
 /* The "disable display" command.  */
 
 static void
-disable_display_command (char *args, int from_tty)
+disable_display_command (const char *args, int from_tty)
 {
   enable_disable_display_command (args, from_tty, 0);
 }
@@ -2306,8 +2256,6 @@ printf_wide_c_string (struct ui_file *stream, const char *format,
                                         "wchar_t", NULL, 0);
   int wcwidth = TYPE_LENGTH (wctype);
   gdb_byte *buf = (gdb_byte *) alloca (wcwidth);
-  struct obstack output;
-  struct cleanup *inner_cleanup;
 
   tem = value_as_address (value);
 
@@ -2326,8 +2274,7 @@ printf_wide_c_string (struct ui_file *stream, const char *format,
     read_memory (tem, str, j);
   memset (&str[j], 0, wcwidth);
 
-  obstack_init (&output);
-  inner_cleanup = make_cleanup_obstack_free (&output);
+  auto_obstack output;
 
   convert_between_encodings (target_wide_charset (gdbarch),
                             host_charset (),
@@ -2336,7 +2283,6 @@ printf_wide_c_string (struct ui_file *stream, const char *format,
   obstack_grow_str0 (&output, "");
 
   fprintf_filtered (stream, format, obstack_base (&output));
-  do_cleanups (inner_cleanup);
 }
 
 /* Subroutine of ui_printf to simplify it.
@@ -2369,7 +2315,6 @@ printf_decfloat (struct ui_file *stream, const char *format,
   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.  */
@@ -2417,10 +2362,9 @@ printf_decfloat (struct ui_file *stream, const char *format,
 
   dfp_ptr = (gdb_byte *) value_contents (dfp_value);
 
-  decimal_to_string (dfp_ptr, dfp_len, byte_order, decstr);
-
-  /* Print the DFP value.  */
-  fprintf_filtered (stream, "%s", decstr);
+  /* Convert the value to a string and print it.  */
+  std::string str = decimal_to_string (dfp_ptr, dfp_len, byte_order);
+  fputs_filtered (str.c_str (), stream);
 #endif
 }
 
@@ -2506,7 +2450,7 @@ ui_printf (const char *arg, struct ui_file *stream)
   if (s == 0)
     error_no_arg (_("format-control string and values to print"));
 
-  s = skip_spaces_const (s);
+  s = skip_spaces (s);
 
   /* A format string should follow, enveloped in double quotes.  */
   if (*s++ != '"')
@@ -2519,14 +2463,14 @@ ui_printf (const char *arg, struct ui_file *stream)
   if (*s++ != '"')
     error (_("Bad format string, non-terminated '\"'."));
   
-  s = skip_spaces_const (s);
+  s = skip_spaces (s);
 
   if (*s != ',' && *s != 0)
     error (_("Invalid argument syntax"));
 
   if (*s == ',')
     s++;
-  s = skip_spaces_const (s);
+  s = skip_spaces (s);
 
   {
     int nargs = 0;
@@ -2582,8 +2526,6 @@ ui_printf (const char *arg, struct ui_file *stream)
              struct type *wctype = lookup_typename (current_language, gdbarch,
                                                     "wchar_t", NULL, 0);
              struct type *valtype;
-             struct obstack output;
-             struct cleanup *inner_cleanup;
              const gdb_byte *bytes;
 
              valtype = value_type (val_args[i]);
@@ -2593,8 +2535,7 @@ ui_printf (const char *arg, struct ui_file *stream)
 
              bytes = value_contents (val_args[i]);
 
-             obstack_init (&output);
-             inner_cleanup = make_cleanup_obstack_free (&output);
+             auto_obstack output;
 
              convert_between_encodings (target_wide_charset (gdbarch),
                                         host_charset (),
@@ -2605,7 +2546,6 @@ ui_printf (const char *arg, struct ui_file *stream)
 
              fprintf_filtered (stream, current_substring,
                                 obstack_base (&output));
-             do_cleanups (inner_cleanup);
            }
            break;
          case double_arg:
@@ -2732,10 +2672,10 @@ _initialize_printcmd (void)
 
   observer_attach_free_objfile (clear_dangling_display_expressions);
 
-  add_info ("address", address_info,
+  add_info ("address", info_address_command,
            _("Describe where symbol SYM is stored."));
 
-  add_info ("symbol", sym_info, _("\
+  add_info ("symbol", info_symbol_command, _("\
 Describe what symbol is at location ADDR.\n\
 Only for symbols with fixed locations (global or static scope)."));
 
@@ -2759,7 +2699,7 @@ with this command or \"print\"."));
           _("Print line number and file of definition of variable."));
 #endif
 
-  add_info ("display", display_info, _("\
+  add_info ("display", info_display_command, _("\
 Expressions to display when program stops, with code numbers."));
 
   add_cmd ("undisplay", class_vars, undisplay_command, _("\
@@ -2817,7 +2757,7 @@ With a subcommand, this command modifies parts of the gdb environment.\n\
 You can see these environment settings with the \"show\" command."),
                  &setlist, "set ", 1, &cmdlist);
   if (dbx_commands)
-    add_com ("assign", class_vars, set_command, _("\
+    add_com ("assign", class_vars, non_const_set_command, _("\
 Evaluate expression EXP and assign result to variable VAR, using assignment\n\
 syntax appropriate for the current language (VAR = EXP or VAR := EXP for\n\
 example).  VAR may be a debugger \"convenience\" variable (names starting\n\
This page took 0.03145 seconds and 4 git commands to generate.