Use previous count when 'x' command is repeated
[deliverable/binutils-gdb.git] / gdb / printcmd.c
index 51e3d384798acce8e80d3215223ea725755c6186..18c41103bd55b2d0c9e7adc81fa434a95ddad5fa 100644 (file)
@@ -1,6 +1,6 @@
 /* Print values for GNU debugger GDB.
 
-   Copyright (C) 1986-2017 Free Software Foundation, Inc.
+   Copyright (C) 1986-2018 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -39,7 +39,7 @@
 #include "block.h"
 #include "disasm.h"
 #include "target-float.h"
-#include "observer.h"
+#include "observable.h"
 #include "solist.h"
 #include "parser-defs.h"
 #include "charset.h"
@@ -62,6 +62,10 @@ static char last_format = 0;
 
 static char last_size = 'w';
 
+/* Last specified count for the 'x' command.  */
+
+static int last_count;
+
 /* Default address to examine next, and associated architecture.  */
 
 static struct gdbarch *next_gdbarch;
@@ -78,7 +82,7 @@ static CORE_ADDR last_examine_address;
 /* Contents of last address examined.
    This is not valid past the end of the `x' command!  */
 
-static struct value *last_examine_value;
+static value_ref_ptr last_examine_value;
 
 /* Largest offset between a symbolic value and an address, that will be
    printed as `0x1234 <symbol+offset>'.  */
@@ -1093,9 +1097,6 @@ do_examine (struct format_data fmt, struct gdbarch *gdbarch, CORE_ADDR addr)
             object.  */
          last_examine_address = next_address;
 
-         if (last_examine_value)
-           value_free (last_examine_value);
-
          /* The value to be displayed is not fetched greedily.
             Instead, to avoid the possibility of a fetched value not
             being used, its retrieval is delayed until the print code
@@ -1105,12 +1106,10 @@ do_examine (struct format_data fmt, struct gdbarch *gdbarch, CORE_ADDR addr)
             the disassembler be modified so that LAST_EXAMINE_VALUE
             is left with the byte sequence from the last complete
             instruction fetched from memory?  */
-         last_examine_value = value_at_lazy (val_type, next_address);
+         last_examine_value
+           = release_value (value_at_lazy (val_type, next_address));
 
-         if (last_examine_value)
-           release_value (last_examine_value);
-
-         print_formatted (last_examine_value, size, &opts, gdb_stdout);
+         print_formatted (last_examine_value.get (), size, &opts, gdb_stdout);
 
          /* Display any branch delay slots following the final insn.  */
          if (format == 'i' && count == 1)
@@ -1214,14 +1213,14 @@ print_command_1 (const char *exp, int voidprint)
 }
 
 static void
-print_command (char *exp, int from_tty)
+print_command (const char *exp, int from_tty)
 {
   print_command_1 (exp, 1);
 }
 
 /* Same as print, except it doesn't print void results.  */
 static void
-call_command (char *exp, int from_tty)
+call_command (const char *exp, int from_tty)
 {
   print_command_1 (exp, 0);
 }
@@ -1229,7 +1228,7 @@ call_command (char *exp, int from_tty)
 /* Implementation of the "output" command.  */
 
 static void
-output_command (char *exp, int from_tty)
+output_command (const char *exp, int from_tty)
 {
   output_command_const (exp, from_tty);
 }
@@ -1295,16 +1294,8 @@ set_command (const 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
-info_symbol_command (char *arg, int from_tty)
+info_symbol_command (const char *arg, int from_tty)
 {
   struct minimal_symbol *msymbol;
   struct objfile *objfile;
@@ -1395,7 +1386,7 @@ info_symbol_command (char *arg, int from_tty)
 }
 
 static void
-info_address_command (char *exp, int from_tty)
+info_address_command (const char *exp, int from_tty)
 {
   struct gdbarch *gdbarch;
   int regno;
@@ -1619,7 +1610,7 @@ info_address_command (char *exp, int from_tty)
 \f
 
 static void
-x_command (char *exp, int from_tty)
+x_command (const char *exp, int from_tty)
 {
   struct format_data fmt;
   struct value *val;
@@ -1629,6 +1620,11 @@ x_command (char *exp, int from_tty)
   fmt.count = 1;
   fmt.raw = 0;
 
+  /* If there is no expression and no format, use the most recent
+     count.  */
+  if (exp == nullptr && last_count > 0)
+    fmt.count = last_count;
+
   if (exp && *exp == '/')
     {
       const char *tmp = exp + 1;
@@ -1637,6 +1633,8 @@ x_command (char *exp, int from_tty)
       exp = (char *) tmp;
     }
 
+  last_count = fmt.count;
+
   /* If we have an expression, evaluate it and use it as the address.  */
 
   if (exp != 0 && *exp != 0)
@@ -1676,12 +1674,12 @@ x_command (char *exp, int from_tty)
   last_format = fmt.format;
 
   /* Set a couple of internal variables if appropriate.  */
-  if (last_examine_value)
+  if (last_examine_value != nullptr)
     {
       /* Make last address examined available to the user as $_.  Use
          the correct pointer type.  */
       struct type *pointer_type
-       = lookup_pointer_type (value_type (last_examine_value));
+       = lookup_pointer_type (value_type (last_examine_value.get ()));
       set_internalvar (lookup_internalvar ("_"),
                       value_from_pointer (pointer_type,
                                           last_examine_address));
@@ -1690,10 +1688,10 @@ x_command (char *exp, int from_tty)
         as $__.  If the last value has not been fetched from memory
         then don't fetch it now; instead mark it by voiding the $__
         variable.  */
-      if (value_lazy (last_examine_value))
+      if (value_lazy (last_examine_value.get ()))
        clear_internalvar (lookup_internalvar ("__"));
       else
-       set_internalvar (lookup_internalvar ("__"), last_examine_value);
+       set_internalvar (lookup_internalvar ("__"), last_examine_value.get ());
     }
 }
 \f
@@ -1702,7 +1700,7 @@ x_command (char *exp, int from_tty)
    Specify the expression.  */
 
 static void
-display_command (char *arg, int from_tty)
+display_command (const char *arg, int from_tty)
 {
   struct format_data fmt;
   struct display *newobj;
@@ -1731,14 +1729,14 @@ display_command (char *arg, int from_tty)
       fmt.raw = 0;
     }
 
-  innermost_block = NULL;
+  innermost_block.reset ();
   expression_up expr = parse_expression (exp);
 
   newobj = new display ();
 
   newobj->exp_string = xstrdup (exp);
   newobj->exp = std::move (expr);
-  newobj->block = innermost_block;
+  newobj->block = innermost_block.block ();
   newobj->pspace = current_program_space;
   newobj->number = ++display_number;
   newobj->format = fmt;
@@ -1899,9 +1897,9 @@ do_one_display (struct display *d)
 
       TRY
        {
-         innermost_block = NULL;
+         innermost_block.reset ();
          d->exp = parse_expression (d->exp_string);
-         d->block = innermost_block;
+         d->block = innermost_block.block ();
        }
       CATCH (ex, RETURN_MASK_ALL)
        {
@@ -2061,7 +2059,7 @@ disable_current_display (void)
 }
 
 static void
-info_display_command (char *ignore, int from_tty)
+info_display_command (const char *ignore, int from_tty)
 {
   struct display *d;
 
@@ -2228,6 +2226,11 @@ printf_c_string (struct ui_file *stream, const char *format,
   int j;
 
   tem = value_as_address (value);
+  if (tem == 0)
+    {
+      fprintf_filtered (stream, format, "(null)");
+      return;
+    }
 
   /* This is a %s argument.  Find the length of the string.  */
   for (j = 0;; j++)
@@ -2268,6 +2271,11 @@ printf_wide_c_string (struct ui_file *stream, const char *format,
   gdb_byte *buf = (gdb_byte *) alloca (wcwidth);
 
   tem = value_as_address (value);
+  if (tem == 0)
+    {
+      fprintf_filtered (stream, format, "(null)");
+      return;
+    }
 
   /* This is a %s argument.  Find the length of the string.  */
   for (j = 0;; j += wcwidth)
@@ -2407,8 +2415,9 @@ printf_pointer (struct ui_file *stream, const char *format,
   if (val != 0)
     *fmt_p++ = '#';
 
-  /* Copy any width.  */
-  while (*p >= '0' && *p < '9')
+  /* Copy any width or flags.  Only the "-" flag is valid for pointers
+     -- see the format_pieces constructor.  */
+  while (*p == '-' || (*p >= '0' && *p < '9'))
     *fmt_p++ = *p++;
 
   gdb_assert (*p == 'p' && *(p + 1) == '\0');
@@ -2435,14 +2444,8 @@ printf_pointer (struct ui_file *stream, const char *format,
 static void
 ui_printf (const char *arg, struct ui_file *stream)
 {
-  struct format_piece *fpieces;
   const char *s = arg;
-  struct value **val_args;
-  int allocated_args = 20;
-  struct cleanup *old_cleanups;
-
-  val_args = XNEWVEC (struct value *, allocated_args);
-  old_cleanups = make_cleanup (free_current_contents, &val_args);
+  std::vector<struct value *> val_args;
 
   if (s == 0)
     error_no_arg (_("format-control string and values to print"));
@@ -2453,9 +2456,7 @@ ui_printf (const char *arg, struct ui_file *stream)
   if (*s++ != '"')
     error (_("Bad format string, missing '\"'."));
 
-  fpieces = parse_format_string (&s);
-
-  make_cleanup (free_format_pieces_cleanup, &fpieces);
+  format_pieces fpieces (&s);
 
   if (*s++ != '"')
     error (_("Bad format string, non-terminated '\"'."));
@@ -2470,14 +2471,13 @@ ui_printf (const char *arg, struct ui_file *stream)
   s = skip_spaces (s);
 
   {
-    int nargs = 0;
     int nargs_wanted;
-    int i, fr;
-    char *current_substring;
+    int i;
+    const char *current_substring;
 
     nargs_wanted = 0;
-    for (fr = 0; fpieces[fr].string != NULL; fr++)
-      if (fpieces[fr].argclass != literal_piece)
+    for (auto &&piece : fpieces)
+      if (piece.argclass != literal_piece)
        ++nargs_wanted;
 
     /* Now, parse all arguments and evaluate them.
@@ -2487,28 +2487,23 @@ ui_printf (const char *arg, struct ui_file *stream)
       {
        const char *s1;
 
-       if (nargs == allocated_args)
-         val_args = (struct value **) xrealloc ((char *) val_args,
-                                                (allocated_args *= 2)
-                                                * sizeof (struct value *));
        s1 = s;
-       val_args[nargs] = parse_to_comma_and_eval (&s1);
+       val_args.push_back (parse_to_comma_and_eval (&s1));
 
-       nargs++;
        s = s1;
        if (*s == ',')
          s++;
       }
 
-    if (nargs != nargs_wanted)
+    if (val_args.size () != nargs_wanted)
       error (_("Wrong number of arguments for specified format-string"));
 
     /* Now actually print them.  */
     i = 0;
-    for (fr = 0; fpieces[fr].string != NULL; fr++)
+    for (auto &&piece : fpieces)
       {
-       current_substring = fpieces[fr].string;
-       switch (fpieces[fr].argclass)
+       current_substring = piece.string;
+       switch (piece.argclass)
          {
          case string_arg:
            printf_c_string (stream, current_substring, val_args[i]);
@@ -2577,7 +2572,7 @@ ui_printf (const char *arg, struct ui_file *stream)
          case dec64float_arg:
          case dec128float_arg:
            printf_floating (stream, current_substring, val_args[i],
-                            fpieces[fr].argclass);
+                            piece.argclass);
            break;
          case ptr_arg:
            printf_pointer (stream, current_substring, val_args[i]);
@@ -2598,17 +2593,16 @@ ui_printf (const char *arg, struct ui_file *stream)
                            _("failed internal consistency check"));
          }
        /* Maybe advance to the next argument.  */
-       if (fpieces[fr].argclass != literal_piece)
+       if (piece.argclass != literal_piece)
          ++i;
       }
   }
-  do_cleanups (old_cleanups);
 }
 
 /* Implement the "printf" command.  */
 
 static void
-printf_command (char *arg, int from_tty)
+printf_command (const char *arg, int from_tty)
 {
   ui_printf (arg, gdb_stdout);
   gdb_flush (gdb_stdout);
@@ -2617,7 +2611,7 @@ printf_command (char *arg, int from_tty)
 /* Implement the "eval" command.  */
 
 static void
-eval_command (char *arg, int from_tty)
+eval_command (const char *arg, int from_tty)
 {
   string_file stb;
 
@@ -2625,7 +2619,7 @@ eval_command (char *arg, int from_tty)
 
   std::string expanded = insert_user_defined_cmd_args (stb.c_str ());
 
-  execute_command (&expanded[0], from_tty);
+  execute_command (expanded.c_str (), from_tty);
 }
 
 void
@@ -2635,7 +2629,7 @@ _initialize_printcmd (void)
 
   current_display_number = -1;
 
-  observer_attach_free_objfile (clear_dangling_display_expressions);
+  gdb::observers::free_objfile.attach (clear_dangling_display_expressions);
 
   add_info ("address", info_address_command,
            _("Describe where symbol SYM is stored."));
@@ -2703,8 +2697,9 @@ No argument means cancel all automatic-display expressions.\n\
 Do \"info display\" to see current list of code numbers."), &deletelist);
 
   add_com ("printf", class_vars, printf_command, _("\
-printf \"printf format string\", arg1, arg2, arg3, ..., argn\n\
-This is useful for formatted output in user-defined commands."));
+Formatted printing, like the C \"printf\" function.\n\
+Usage: printf \"format string\", arg1, arg2, arg3, ..., argn\n\
+This supports most C printf format specifications, like %s, %d, etc."));
 
   add_com ("output", class_vars, output_command, _("\
 Like \"print\" but don't put in value history and don't print newline.\n\
@@ -2722,7 +2717,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, non_const_set_command, _("\
+    add_com ("assign", class_vars, 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\
@@ -2748,6 +2743,7 @@ with $), a register (a few standard names starting with $), or an actual\n\
 variable in the program being debugged.  EXP is any valid expression.\n\
 This may usually be abbreviated to simply \"set\"."),
           &setlist);
+  add_alias_cmd ("var", "variable", class_vars, 0, &setlist);
 
   c = add_com ("print", class_vars, print_command, _("\
 Print value of expression EXP.\n\
This page took 0.033394 seconds and 4 git commands to generate.