Rename common to gdbsupport
[deliverable/binutils-gdb.git] / gdb / mi / mi-cmd-stack.c
index 1f6a9a1aa73f0005f4093097b881156a972bb80d..c8a4ce73c9789ca6be383a3e7f49d7a7ee6adff1 100644 (file)
@@ -1,12 +1,12 @@
 /* MI Command Set - stack commands.
 /* MI Command Set - stack commands.
-   Copyright 2000, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 2000-2019 Free Software Foundation, Inc.
    Contributed by Cygnus Solutions (a Red Hat company).
 
    This file is part of GDB.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    Contributed by Cygnus Solutions (a Red Hat company).
 
    This file is part of GDB.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -15,9 +15,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
 #include "target.h"
 
 #include "defs.h"
 #include "target.h"
 #include "ui-out.h"
 #include "symtab.h"
 #include "block.h"
 #include "ui-out.h"
 #include "symtab.h"
 #include "block.h"
+#include "stack.h"
+#include "dictionary.h"
+#include "language.h"
+#include "valprint.h"
+#include "utils.h"
+#include "mi-getopt.h"
+#include "extension.h"
+#include <ctype.h>
+#include "mi-parse.h"
+#include "gdbsupport/gdb_optional.h"
+#include "safe-ctype.h"
+
+enum what_to_list { locals, arguments, all };
+
+static void list_args_or_locals (const frame_print_options &fp_opts,
+                                enum what_to_list what,
+                                enum print_values values,
+                                struct frame_info *fi,
+                                int skip_unavailable);
+
+/* True if we want to allow Python-based frame filters.  */
+static int frame_filters = 0;
+
+void
+mi_cmd_enable_frame_filters (const char *command, char **argv, int argc)
+{
+  if (argc != 0)
+    error (_("-enable-frame-filters: no arguments allowed"));
+  frame_filters = 1;
+}
 
 
-/* FIXME: these should go in some .h file but stack.c doesn't have a
-   corresponding .h file. These wrappers will be obsolete anyway, once
-   we pull the plug on the sanitization. */
-extern void select_frame_command_wrapper (char *, int);
+/* Like apply_ext_lang_frame_filter, but take a print_values */
 
 
-static void list_args_or_locals (int locals, int values, struct frame_info *fi);
+static enum ext_lang_bt_status
+mi_apply_ext_lang_frame_filter (struct frame_info *frame,
+                               frame_filter_flags flags,
+                               enum print_values print_values,
+                               struct ui_out *out,
+                               int frame_low, int frame_high)
+{
+  /* ext_lang_frame_args's MI options are compatible with MI print
+     values.  */
+  return apply_ext_lang_frame_filter (frame, flags,
+                                     (enum ext_lang_frame_args) print_values,
+                                     out,
+                                     frame_low, frame_high);
+}
 
 
-/* Print a list of the stack frames. Args can be none, in which case
+/* Print a list of the stack frames.  Args can be none, in which case
    we want to print the whole backtrace, or a pair of numbers
    specifying the frame numbers at which to start and stop the
    we want to print the whole backtrace, or a pair of numbers
    specifying the frame numbers at which to start and stop the
-   display. If the two numbers are equal, a single frame will be
-   displayed. */
-enum mi_cmd_result
-mi_cmd_stack_list_frames (char *command, char **argv, int argc)
+   display.  If the two numbers are equal, a single frame will be
+   displayed.  */
+
+void
+mi_cmd_stack_list_frames (const char *command, char **argv, int argc)
 {
   int frame_low;
   int frame_high;
   int i;
 {
   int frame_low;
   int frame_high;
   int i;
-  struct cleanup *cleanup_stack;
   struct frame_info *fi;
   struct frame_info *fi;
+  enum ext_lang_bt_status result = EXT_LANG_BT_ERROR;
+  int raw_arg = 0;
+  int oind = 0;
+  enum opt
+    {
+      NO_FRAME_FILTERS
+    };
+  static const struct mi_opt opts[] =
+    {
+      {"-no-frame-filters", NO_FRAME_FILTERS, 0},
+      { 0, 0, 0 }
+    };
 
 
-  if (!target_has_stack)
-    error ("mi_cmd_stack_list_frames: No stack.");
+  /* Parse arguments.  In this instance we are just looking for
+     --no-frame-filters.  */
+  while (1)
+    {
+      char *oarg;
+      int opt = mi_getopt ("-stack-list-frames", argc, argv,
+                          opts, &oind, &oarg);
+      if (opt < 0)
+       break;
+      switch ((enum opt) opt)
+       {
+       case NO_FRAME_FILTERS:
+         raw_arg = oind;
+         break;
+       }
+    }
 
 
-  if (argc > 2 || argc == 1)
-    error ("mi_cmd_stack_list_frames: Usage: [FRAME_LOW FRAME_HIGH]");
+  /* After the last option is parsed, there should either be low -
+     high range, or no further arguments.  */
+  if ((argc - oind != 0) && (argc - oind != 2))
+    error (_("-stack-list-frames: Usage: [--no-frame-filters] [FRAME_LOW FRAME_HIGH]"));
 
 
-  if (argc == 2)
+  /* If there is a range, set it.  */
+  if (argc - oind == 2)
     {
     {
-      frame_low = atoi (argv[0]);
-      frame_high = atoi (argv[1]);
+      frame_low = atoi (argv[0 + oind]);
+      frame_high = atoi (argv[1 + oind]);
     }
   else
     {
       /* Called with no arguments, it means we want the whole
     }
   else
     {
       /* Called with no arguments, it means we want the whole
-         backtrace. */
+         backtrace.  */
       frame_low = -1;
       frame_high = -1;
     }
 
   /* Let's position fi on the frame at which to start the
      display. Could be the innermost frame if the whole stack needs
       frame_low = -1;
       frame_high = -1;
     }
 
   /* Let's position fi on the frame at which to start the
      display. Could be the innermost frame if the whole stack needs
-     displaying, or if frame_low is 0. */
+     displaying, or if frame_low is 0.  */
   for (i = 0, fi = get_current_frame ();
        fi && i < frame_low;
        i++, fi = get_prev_frame (fi));
 
   if (fi == NULL)
   for (i = 0, fi = get_current_frame ();
        fi && i < frame_low;
        i++, fi = get_prev_frame (fi));
 
   if (fi == NULL)
-    error ("mi_cmd_stack_list_frames: Not enough frames in stack.");
+    error (_("-stack-list-frames: Not enough frames in stack."));
 
 
-  cleanup_stack = make_cleanup_ui_out_list_begin_end (uiout, "stack");
+  ui_out_emit_list list_emitter (current_uiout, "stack");
 
 
-  /* Now let;s print the frames up to frame_high, or until there are
-     frames in the stack. */
-  for (;
-       fi && (i <= frame_high || frame_high == -1);
-       i++, fi = get_prev_frame (fi))
+  if (! raw_arg && frame_filters)
     {
     {
-      QUIT;
-      /* level == i: always print the level 'i'
-         source == LOC_AND_ADDRESS: print the location and the address 
-         always, even for level 0.
-         args == 0: don't print the arguments. */
-      print_frame_info (fi /* frame info */ ,
-                       i /* level */ ,
-                       LOC_AND_ADDRESS /* source */ ,
-                       0 /* args */ );
+      frame_filter_flags flags = PRINT_LEVEL | PRINT_FRAME_INFO;
+      int py_frame_low = frame_low;
+
+      /* We cannot pass -1 to frame_low, as that would signify a
+      relative backtrace from the tail of the stack.  So, in the case
+      of frame_low == -1, assign and increment it.  */
+      if (py_frame_low == -1)
+       py_frame_low++;
+
+      result = apply_ext_lang_frame_filter (get_current_frame (), flags,
+                                           NO_VALUES,  current_uiout,
+                                           py_frame_low, frame_high);
     }
 
     }
 
-  do_cleanups (cleanup_stack);
-  if (i < frame_high)
-    error ("mi_cmd_stack_list_frames: Not enough frames in stack.");
-
-  return MI_CMD_DONE;
+  /* Run the inbuilt backtrace if there are no filters registered, or
+     if "--no-frame-filters" has been specified from the command.  */
+  if (! frame_filters || raw_arg  || result == EXT_LANG_BT_NO_FILTERS)
+    {
+      /* Now let's print the frames up to frame_high, or until there are
+        frames in the stack.  */
+      for (;
+          fi && (i <= frame_high || frame_high == -1);
+          i++, fi = get_prev_frame (fi))
+       {
+         QUIT;
+         /* Print the location and the address always, even for level 0.
+            If args is 0, don't print the arguments.  */
+         print_frame_info (user_frame_print_options,
+                           fi, 1, LOC_AND_ADDRESS, 0 /* args */, 0);
+       }
+    }
 }
 
 }
 
-enum mi_cmd_result
-mi_cmd_stack_info_depth (char *command, char **argv, int argc)
+void
+mi_cmd_stack_info_depth (const char *command, char **argv, int argc)
 {
   int frame_high;
   int i;
   struct frame_info *fi;
 
 {
   int frame_high;
   int i;
   struct frame_info *fi;
 
-  if (!target_has_stack)
-    error ("mi_cmd_stack_info_depth: No stack.");
-
   if (argc > 1)
   if (argc > 1)
-    error ("mi_cmd_stack_info_depth: Usage: [MAX_DEPTH]");
+    error (_("-stack-info-depth: Usage: [MAX_DEPTH]"));
 
   if (argc == 1)
     frame_high = atoi (argv[0]);
   else
     /* Called with no arguments, it means we want the real depth of
 
   if (argc == 1)
     frame_high = atoi (argv[0]);
   else
     /* Called with no arguments, it means we want the real depth of
-       the stack. */
+       the stack.  */
     frame_high = -1;
 
   for (i = 0, fi = get_current_frame ();
     frame_high = -1;
 
   for (i = 0, fi = get_current_frame ();
@@ -129,107 +204,398 @@ mi_cmd_stack_info_depth (char *command, char **argv, int argc)
        i++, fi = get_prev_frame (fi))
     QUIT;
 
        i++, fi = get_prev_frame (fi))
     QUIT;
 
-  ui_out_field_int (uiout, "depth", i);
-
-  return MI_CMD_DONE;
+  current_uiout->field_int ("depth", i);
 }
 
 }
 
-/* Print a list of the locals for the current frame. With argument of
+/* Print a list of the locals for the current frame.  With argument of
    0, print only the names, with argument of 1 print also the
    0, print only the names, with argument of 1 print also the
-   values. */
-enum mi_cmd_result
-mi_cmd_stack_list_locals (char *command, char **argv, int argc)
+   values.  */
+
+void
+mi_cmd_stack_list_locals (const char *command, char **argv, int argc)
 {
 {
-  if (argc != 1)
-    error ("mi_cmd_stack_list_locals: Usage: PRINT_VALUES");
+  struct frame_info *frame;
+  int raw_arg = 0;
+  enum ext_lang_bt_status result = EXT_LANG_BT_ERROR;
+  enum print_values print_value;
+  int oind = 0;
+  int skip_unavailable = 0;
+
+  if (argc > 1)
+    {
+      enum opt
+      {
+       NO_FRAME_FILTERS,
+       SKIP_UNAVAILABLE,
+      };
+      static const struct mi_opt opts[] =
+       {
+         {"-no-frame-filters", NO_FRAME_FILTERS, 0},
+         {"-skip-unavailable", SKIP_UNAVAILABLE, 0},
+         { 0, 0, 0 }
+       };
 
 
-  list_args_or_locals (1, atoi (argv[0]), deprecated_selected_frame);
-  return MI_CMD_DONE;
+      while (1)
+       {
+         char *oarg;
+         /* Don't parse 'print-values' as an option.  */
+         int opt = mi_getopt ("-stack-list-locals", argc - 1, argv,
+                              opts, &oind, &oarg);
+
+         if (opt < 0)
+           break;
+         switch ((enum opt) opt)
+           {
+           case NO_FRAME_FILTERS:
+             raw_arg = oind;
+             break;
+           case SKIP_UNAVAILABLE:
+             skip_unavailable = 1;
+             break;
+           }
+       }
+    }
+
+  /* After the last option is parsed, there should be only
+     'print-values'.  */
+  if (argc - oind != 1)
+    error (_("-stack-list-locals: Usage: [--no-frame-filters] "
+            "[--skip-unavailable] PRINT_VALUES"));
+
+  frame = get_selected_frame (NULL);
+  print_value = mi_parse_print_values (argv[oind]);
+
+   if (! raw_arg && frame_filters)
+     {
+       frame_filter_flags flags = PRINT_LEVEL | PRINT_LOCALS;
+
+       result = mi_apply_ext_lang_frame_filter (frame, flags, print_value,
+                                               current_uiout, 0, 0);
+     }
+
+   /* Run the inbuilt backtrace if there are no filters registered, or
+      if "--no-frame-filters" has been specified from the command.  */
+   if (! frame_filters || raw_arg  || result == EXT_LANG_BT_NO_FILTERS)
+     {
+       list_args_or_locals (user_frame_print_options,
+                           locals, print_value, frame,
+                           skip_unavailable);
+     }
 }
 
 }
 
-/* Print a list of the arguments for the current frame. With argument
+/* Print a list of the arguments for the current frame.  With argument
    of 0, print only the names, with argument of 1 print also the
    of 0, print only the names, with argument of 1 print also the
-   values. */
-enum mi_cmd_result
-mi_cmd_stack_list_args (char *command, char **argv, int argc)
+   values.  */
+
+void
+mi_cmd_stack_list_args (const char *command, char **argv, int argc)
 {
   int frame_low;
   int frame_high;
   int i;
   struct frame_info *fi;
 {
   int frame_low;
   int frame_high;
   int i;
   struct frame_info *fi;
-  struct cleanup *cleanup_stack_args;
+  enum print_values print_values;
+  struct ui_out *uiout = current_uiout;
+  int raw_arg = 0;
+  int oind = 0;
+  int skip_unavailable = 0;
+  enum ext_lang_bt_status result = EXT_LANG_BT_ERROR;
+  enum opt
+  {
+    NO_FRAME_FILTERS,
+    SKIP_UNAVAILABLE,
+  };
+  static const struct mi_opt opts[] =
+    {
+      {"-no-frame-filters", NO_FRAME_FILTERS, 0},
+      {"-skip-unavailable", SKIP_UNAVAILABLE, 0},
+      { 0, 0, 0 }
+    };
+
+  while (1)
+    {
+      char *oarg;
+      int opt = mi_getopt_allow_unknown ("-stack-list-args", argc, argv,
+                                        opts, &oind, &oarg);
 
 
-  if (argc < 1 || argc > 3 || argc == 2)
-    error ("mi_cmd_stack_list_args: Usage: PRINT_VALUES [FRAME_LOW FRAME_HIGH]");
+      if (opt < 0)
+       break;
+      switch ((enum opt) opt)
+       {
+       case NO_FRAME_FILTERS:
+         raw_arg = oind;
+         break;
+       case SKIP_UNAVAILABLE:
+         skip_unavailable = 1;
+         break;
+       }
+    }
+
+  if (argc - oind != 1 && argc - oind != 3)
+    error (_("-stack-list-arguments: Usage: "  \
+            "[--no-frame-filters] [--skip-unavailable] "
+            "PRINT_VALUES [FRAME_LOW FRAME_HIGH]"));
 
 
-  if (argc == 3)
+  if (argc - oind == 3)
     {
     {
-      frame_low = atoi (argv[1]);
-      frame_high = atoi (argv[2]);
+      frame_low = atoi (argv[1 + oind]);
+      frame_high = atoi (argv[2 + oind]);
     }
   else
     {
       /* Called with no arguments, it means we want args for the whole
     }
   else
     {
       /* Called with no arguments, it means we want args for the whole
-         backtrace. */
+         backtrace.  */
       frame_low = -1;
       frame_high = -1;
     }
 
       frame_low = -1;
       frame_high = -1;
     }
 
+  print_values = mi_parse_print_values (argv[oind]);
+
   /* Let's position fi on the frame at which to start the
      display. Could be the innermost frame if the whole stack needs
   /* Let's position fi on the frame at which to start the
      display. Could be the innermost frame if the whole stack needs
-     displaying, or if frame_low is 0. */
+     displaying, or if frame_low is 0.  */
   for (i = 0, fi = get_current_frame ();
        fi && i < frame_low;
        i++, fi = get_prev_frame (fi));
 
   if (fi == NULL)
   for (i = 0, fi = get_current_frame ();
        fi && i < frame_low;
        i++, fi = get_prev_frame (fi));
 
   if (fi == NULL)
-    error ("mi_cmd_stack_list_args: Not enough frames in stack.");
+    error (_("-stack-list-arguments: Not enough frames in stack."));
 
 
-  cleanup_stack_args = make_cleanup_ui_out_list_begin_end (uiout, "stack-args");
+  ui_out_emit_list list_emitter (uiout, "stack-args");
 
 
-  /* Now let's print the frames up to frame_high, or until there are
-     frames in the stack. */
-  for (;
-       fi && (i <= frame_high || frame_high == -1);
-       i++, fi = get_prev_frame (fi))
+  if (! raw_arg && frame_filters)
     {
     {
-      struct cleanup *cleanup_frame;
-      QUIT;
-      cleanup_frame = make_cleanup_ui_out_tuple_begin_end (uiout, "frame");
-      ui_out_field_int (uiout, "level", i);
-      list_args_or_locals (0, atoi (argv[0]), fi);
-      do_cleanups (cleanup_frame);
+      frame_filter_flags flags = PRINT_LEVEL | PRINT_ARGS;
+      int py_frame_low = frame_low;
+
+      /* We cannot pass -1 to frame_low, as that would signify a
+      relative backtrace from the tail of the stack.  So, in the case
+      of frame_low == -1, assign and increment it.  */
+      if (py_frame_low == -1)
+       py_frame_low++;
+
+      result = mi_apply_ext_lang_frame_filter (get_current_frame (), flags,
+                                              print_values, current_uiout,
+                                              py_frame_low, frame_high);
     }
 
     }
 
-  do_cleanups (cleanup_stack_args);
-  if (i < frame_high)
-    error ("mi_cmd_stack_list_args: Not enough frames in stack.");
+     /* Run the inbuilt backtrace if there are no filters registered, or
+      if "--no-frame-filters" has been specified from the command.  */
+   if (! frame_filters || raw_arg  || result == EXT_LANG_BT_NO_FILTERS)
+     {
+      /* Now let's print the frames up to frame_high, or until there are
+        frames in the stack.  */
+      for (;
+          fi && (i <= frame_high || frame_high == -1);
+          i++, fi = get_prev_frame (fi))
+       {
+         QUIT;
+         ui_out_emit_tuple tuple_emitter (uiout, "frame");
+         uiout->field_int ("level", i);
+         list_args_or_locals (user_frame_print_options,
+                              arguments, print_values, fi, skip_unavailable);
+       }
+    }
+}
+
+/* Print a list of the local variables (including arguments) for the 
+   current frame.  ARGC must be 1 and ARGV[0] specify if only the names,
+   or both names and values of the variables must be printed.  See 
+   parse_print_value for possible values.  */
+
+void
+mi_cmd_stack_list_variables (const char *command, char **argv, int argc)
+{
+  struct frame_info *frame;
+  int raw_arg = 0;
+  enum ext_lang_bt_status result = EXT_LANG_BT_ERROR;
+  enum print_values print_value;
+  int oind = 0;
+  int skip_unavailable = 0;
 
 
-  return MI_CMD_DONE;
+  if (argc > 1)
+    {
+      enum opt
+      {
+       NO_FRAME_FILTERS,
+       SKIP_UNAVAILABLE,
+      };
+      static const struct mi_opt opts[] =
+       {
+         {"-no-frame-filters", NO_FRAME_FILTERS, 0},
+         {"-skip-unavailable", SKIP_UNAVAILABLE, 0},
+         { 0, 0, 0 }
+       };
+
+      while (1)
+       {
+         char *oarg;
+         /* Don't parse 'print-values' as an option.  */
+         int opt = mi_getopt ("-stack-list-variables", argc - 1,
+                              argv, opts, &oind, &oarg);
+         if (opt < 0)
+           break;
+         switch ((enum opt) opt)
+           {
+           case NO_FRAME_FILTERS:
+             raw_arg = oind;
+             break;
+           case SKIP_UNAVAILABLE:
+             skip_unavailable = 1;
+             break;
+           }
+       }
+    }
+
+  /* After the last option is parsed, there should be only
+     'print-values'.  */
+  if (argc - oind != 1)
+    error (_("-stack-list-variables: Usage: [--no-frame-filters] " \
+            "[--skip-unavailable] PRINT_VALUES"));
+
+   frame = get_selected_frame (NULL);
+   print_value = mi_parse_print_values (argv[oind]);
+
+   if (! raw_arg && frame_filters)
+     {
+       frame_filter_flags flags = PRINT_LEVEL | PRINT_ARGS | PRINT_LOCALS;
+
+       result = mi_apply_ext_lang_frame_filter (frame, flags,
+                                               print_value,
+                                               current_uiout, 0, 0);
+     }
+
+   /* Run the inbuilt backtrace if there are no filters registered, or
+      if "--no-frame-filters" has been specified from the command.  */
+   if (! frame_filters || raw_arg  || result == EXT_LANG_BT_NO_FILTERS)
+     {
+       list_args_or_locals (user_frame_print_options,
+                           all, print_value, frame,
+                           skip_unavailable);
+     }
 }
 
 }
 
-/* Print a list of the locals or the arguments for the currently
-   selected frame.  If the argument passed is 0, printonly the names
-   of the variables, if an argument of 1 is passed, print the values
-   as well. */
+/* Print single local or argument.  ARG must be already read in.  For
+   WHAT and VALUES see list_args_or_locals.
+
+   Errors are printed as if they would be the parameter value.  Use
+   zeroed ARG iff it should not be printed according to VALUES.  If
+   SKIP_UNAVAILABLE is true, only print ARG if it is available.  */
+
 static void
 static void
-list_args_or_locals (int locals, int values, struct frame_info *fi)
+list_arg_or_local (const struct frame_arg *arg, enum what_to_list what,
+                  enum print_values values, int skip_unavailable)
 {
 {
-  struct block *block;
-  struct symbol *sym;
-  int i, nsyms;
-  struct cleanup *cleanup_list;
-  static struct ui_stream *stb = NULL;
+  struct ui_out *uiout = current_uiout;
+
+  gdb_assert (!arg->val || !arg->error);
+  gdb_assert ((values == PRINT_NO_VALUES && arg->val == NULL
+              && arg->error == NULL)
+             || values == PRINT_SIMPLE_VALUES
+             || (values == PRINT_ALL_VALUES
+                 && (arg->val != NULL || arg->error != NULL)));
+  gdb_assert (arg->entry_kind == print_entry_values_no
+             || (arg->entry_kind == print_entry_values_only
+                 && (arg->val || arg->error)));
+
+  if (skip_unavailable && arg->val != NULL
+      && (value_entirely_unavailable (arg->val)
+         /* A scalar object that does not have all bits available is
+            also considered unavailable, because all bits contribute
+            to its representation.  */
+         || (val_print_scalar_type_p (value_type (arg->val))
+             && !value_bytes_available (arg->val,
+                                        value_embedded_offset (arg->val),
+                                        TYPE_LENGTH (value_type (arg->val))))))
+    return;
+
+  gdb::optional<ui_out_emit_tuple> tuple_emitter;
+  if (values != PRINT_NO_VALUES || what == all)
+    tuple_emitter.emplace (uiout, nullptr);
+
+  string_file stb;
+
+  stb.puts (SYMBOL_PRINT_NAME (arg->sym));
+  if (arg->entry_kind == print_entry_values_only)
+    stb.puts ("@entry");
+  uiout->field_stream ("name", stb);
+
+  if (what == all && SYMBOL_IS_ARGUMENT (arg->sym))
+    uiout->field_int ("arg", 1);
+
+  if (values == PRINT_SIMPLE_VALUES)
+    {
+      check_typedef (arg->sym->type);
+      type_print (arg->sym->type, "", &stb, -1);
+      uiout->field_stream ("type", stb);
+    }
+
+  if (arg->val || arg->error)
+    {
+      if (arg->error)
+       stb.printf (_("<error reading variable: %s>"), arg->error);
+      else
+       {
+         try
+           {
+             struct value_print_options opts;
+
+             get_no_prettyformat_print_options (&opts);
+             opts.deref_ref = 1;
+             common_val_print (arg->val, &stb, 0, &opts,
+                               language_def (SYMBOL_LANGUAGE (arg->sym)));
+           }
+         catch (const gdb_exception_error &except)
+           {
+             stb.printf (_("<error reading variable: %s>"),
+                         except.what ());
+           }
+       }
+      uiout->field_stream ("value", stb);
+    }
+}
 
 
-  stb = ui_out_stream_new (uiout);
+/* Print a list of the objects for the frame FI in a certain form,
+   which is determined by VALUES.  The objects can be locals,
+   arguments or both, which is determined by WHAT.  If SKIP_UNAVAILABLE
+   is true, only print the arguments or local variables whose values
+   are available.  */
+
+static void
+list_args_or_locals (const frame_print_options &fp_opts,
+                    enum what_to_list what, enum print_values values,
+                    struct frame_info *fi, int skip_unavailable)
+{
+  const struct block *block;
+  struct symbol *sym;
+  struct block_iterator iter;
+  struct type *type;
+  const char *name_of_result;
+  struct ui_out *uiout = current_uiout;
 
   block = get_frame_block (fi, 0);
 
 
   block = get_frame_block (fi, 0);
 
-  cleanup_list = make_cleanup_ui_out_list_begin_end (uiout, locals ? "locals" : "args");
+  switch (what)
+    {
+    case locals:
+      name_of_result = "locals";
+      break;
+    case arguments:
+      name_of_result = "args";
+      break;
+    case all:
+      name_of_result = "variables";
+      break;
+    default:
+      internal_error (__FILE__, __LINE__,
+                     "unexpected what_to_list: %d", (int) what);
+    }
+
+  ui_out_emit_list list_emitter (uiout, name_of_result);
 
   while (block != 0)
     {
 
   while (block != 0)
     {
-      ALL_BLOCK_SYMBOLS (block, i, sym)
+      ALL_BLOCK_SYMBOLS (block, iter, sym)
        {
           int print_me = 0;
 
        {
           int print_me = 0;
 
@@ -249,70 +615,161 @@ list_args_or_locals (int locals, int values, struct frame_info *fi)
 
            case LOC_ARG:       /* argument              */
            case LOC_REF_ARG:   /* reference arg         */
 
            case LOC_ARG:       /* argument              */
            case LOC_REF_ARG:   /* reference arg         */
-           case LOC_REGPARM:   /* register arg          */
            case LOC_REGPARM_ADDR:      /* indirect register arg */
            case LOC_REGPARM_ADDR:      /* indirect register arg */
-           case LOC_LOCAL_ARG: /* stack arg             */
-           case LOC_BASEREG_ARG:       /* basereg arg           */
-           case LOC_COMPUTED_ARG:      /* arg with computed location */
-             if (!locals)
-               print_me = 1;
-             break;
-
            case LOC_LOCAL:     /* stack local           */
            case LOC_LOCAL:     /* stack local           */
-           case LOC_BASEREG:   /* basereg local         */
            case LOC_STATIC:    /* static                */
            case LOC_REGISTER:  /* register              */
            case LOC_COMPUTED:  /* computed location     */
            case LOC_STATIC:    /* static                */
            case LOC_REGISTER:  /* register              */
            case LOC_COMPUTED:  /* computed location     */
-             if (locals)
+             if (what == all)
                print_me = 1;
                print_me = 1;
+             else if (what == locals)
+               print_me = !SYMBOL_IS_ARGUMENT (sym);
+             else
+               print_me = SYMBOL_IS_ARGUMENT (sym);
              break;
            }
          if (print_me)
            {
              break;
            }
          if (print_me)
            {
-             struct cleanup *cleanup_tuple = NULL;
-             if (values)
-               cleanup_tuple = 
-                 make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
-             ui_out_field_string (uiout, "name", DEPRECATED_SYMBOL_NAME (sym));
-
-             if (values)
+             struct symbol *sym2;
+             struct frame_arg arg, entryarg;
+
+             if (SYMBOL_IS_ARGUMENT (sym))
+               sym2 = lookup_symbol (SYMBOL_LINKAGE_NAME (sym),
+                                     block, VAR_DOMAIN,
+                                     NULL).symbol;
+             else
+               sym2 = sym;
+             gdb_assert (sym2 != NULL);
+
+             memset (&arg, 0, sizeof (arg));
+             arg.sym = sym2;
+             arg.entry_kind = print_entry_values_no;
+             memset (&entryarg, 0, sizeof (entryarg));
+             entryarg.sym = sym2;
+             entryarg.entry_kind = print_entry_values_no;
+
+             switch (values)
                {
                {
-                 struct symbol *sym2;
-                 if (!locals)
-                   sym2 = lookup_symbol (DEPRECATED_SYMBOL_NAME (sym),
-                                         block, VAR_DOMAIN,
-                                         (int *) NULL,
-                                         (struct symtab **) NULL);
+               case PRINT_SIMPLE_VALUES:
+                 type = check_typedef (sym2->type);
+                 if (TYPE_CODE (type) != TYPE_CODE_ARRAY
+                     && TYPE_CODE (type) != TYPE_CODE_STRUCT
+                     && TYPE_CODE (type) != TYPE_CODE_UNION)
+                   {
+               case PRINT_ALL_VALUES:
+                 if (SYMBOL_IS_ARGUMENT (sym))
+                   read_frame_arg (fp_opts, sym2, fi, &arg, &entryarg);
                  else
                  else
-                   sym2 = sym;
-                 print_variable_value (sym2, fi, stb->stream);
-                 ui_out_field_stream (uiout, "value", stb);
-                 do_cleanups (cleanup_tuple);
+                   read_frame_local (sym2, fi, &arg);
+                   }
+                 break;
                }
                }
+
+             if (arg.entry_kind != print_entry_values_only)
+               list_arg_or_local (&arg, what, values, skip_unavailable);
+             if (entryarg.entry_kind != print_entry_values_no)
+               list_arg_or_local (&entryarg, what, values, skip_unavailable);
+             xfree (arg.error);
+             xfree (entryarg.error);
            }
        }
            }
        }
+
       if (BLOCK_FUNCTION (block))
        break;
       else
        block = BLOCK_SUPERBLOCK (block);
     }
       if (BLOCK_FUNCTION (block))
        break;
       else
        block = BLOCK_SUPERBLOCK (block);
     }
-  do_cleanups (cleanup_list);
-  ui_out_stream_delete (stb);
 }
 
 }
 
-enum mi_cmd_result
-mi_cmd_stack_select_frame (char *command, char **argv, int argc)
+/* Read a frame specification from FRAME_EXP and return the selected frame.
+   Call error() if the specification is in any way invalid (so this
+   function never returns NULL).
+
+   The frame specification is usually an integer level number, however if
+   the number does not match a valid frame level then it will be treated as
+   a frame address.  The frame address will then be used to find a matching
+   frame in the stack.  If no matching frame is found then a new frame will
+   be created.
+
+   The use of FRAME_EXP as an address is undocumented in the GDB user
+   manual, this feature is supported here purely for backward
+   compatibility.  */
+
+static struct frame_info *
+parse_frame_specification (const char *frame_exp)
 {
 {
-  if (!target_has_stack)
-    error ("mi_cmd_stack_select_frame: No stack.");
+  gdb_assert (frame_exp != NULL);
+
+  /* NOTE: Parse and evaluate expression, but do not use
+     functions such as parse_and_eval_long or
+     parse_and_eval_address to also extract the value.
+     Instead value_as_long and value_as_address are used.
+     This avoids problems with expressions that contain
+     side-effects.  */
+  struct value *arg = parse_and_eval (frame_exp);
+
+  /* Assume ARG is an integer, and try using that to select a frame.  */
+  struct frame_info *fid;
+  int level = value_as_long (arg);
+
+  fid = find_relative_frame (get_current_frame (), &level);
+  if (level == 0)
+    /* find_relative_frame was successful.  */
+    return fid;
+
+  /* Convert the value into a corresponding address.  */
+  CORE_ADDR addr = value_as_address (arg);
+
+  /* Assume that ADDR is an address, use that to identify a frame with a
+     matching ID.  */
+  struct frame_id id = frame_id_build_wild (addr);
+
+  /* If (s)he specifies the frame with an address, he deserves
+     what (s)he gets.  Still, give the highest one that matches.
+     (NOTE: cagney/2004-10-29: Why highest, or outer-most, I don't
+     know).  */
+  for (fid = get_current_frame ();
+       fid != NULL;
+       fid = get_prev_frame (fid))
+    {
+      if (frame_id_eq (id, get_frame_id (fid)))
+       {
+         struct frame_info *prev_frame;
 
 
-  if (argc > 1)
-    error ("mi_cmd_stack_select_frame: Usage: [FRAME_SPEC]");
+         while (1)
+           {
+             prev_frame = get_prev_frame (fid);
+             if (!prev_frame
+                 || !frame_id_eq (id, get_frame_id (prev_frame)))
+               break;
+             fid = prev_frame;
+           }
+         return fid;
+       }
+    }
 
 
-  /* with no args, don't change frame */
-  if (argc == 0)
-    select_frame_command_wrapper (0, 1 /* not used */ );
-  else
-    select_frame_command_wrapper (argv[0], 1 /* not used */ );
-  return MI_CMD_DONE;
+  /* We couldn't identify the frame as an existing frame, but
+     perhaps we can create one with a single argument.  */
+  return create_new_frame (addr, 0);
+}
+
+/* Implement the -stack-select-frame MI command.  */
+
+void
+mi_cmd_stack_select_frame (const char *command, char **argv, int argc)
+{
+  if (argc == 0 || argc > 1)
+    error (_("-stack-select-frame: Usage: FRAME_SPEC"));
+
+  select_frame_for_mi (parse_frame_specification (argv[0]));
+}
+
+void
+mi_cmd_stack_info_frame (const char *command, char **argv, int argc)
+{
+  if (argc > 0)
+    error (_("-stack-info-frame: No arguments allowed"));
+
+  print_frame_info (user_frame_print_options,
+                   get_selected_frame (NULL), 1, LOC_AND_ADDRESS, 0, 1);
 }
 }
This page took 0.033421 seconds and 4 git commands to generate.