Use an accessor function for general_symbol_info::language
[deliverable/binutils-gdb.git] / gdb / mi / mi-cmd-stack.c
index 7bc81145d486b1d9c7473f434e1788d2f51c9f95..6cd255d072003e811bfc74848c65283bcabbada8 100644 (file)
@@ -1,5 +1,5 @@
 /* MI Command Set - stack commands.
-   Copyright (C) 2000-2014 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.
 #include "block.h"
 #include "stack.h"
 #include "dictionary.h"
-#include <string.h>
 #include "language.h"
 #include "valprint.h"
-#include "exceptions.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 (enum what_to_list what,
+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);
@@ -48,13 +49,30 @@ static void list_args_or_locals (enum what_to_list what,
 static int frame_filters = 0;
 
 void
-mi_cmd_enable_frame_filters (char *command, char **argv, int argc)
+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;
 }
 
+/* Like apply_ext_lang_frame_filter, but take a print_values */
+
+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
    we want to print the whole backtrace, or a pair of numbers
    specifying the frame numbers at which to start and stop the
@@ -62,12 +80,11 @@ mi_cmd_enable_frame_filters (char *command, char **argv, int argc)
    displayed.  */
 
 void
-mi_cmd_stack_list_frames (char *command, char **argv, int argc)
+mi_cmd_stack_list_frames (const char *command, char **argv, int argc)
 {
   int frame_low;
   int frame_high;
   int i;
-  struct cleanup *cleanup_stack;
   struct frame_info *fi;
   enum ext_lang_bt_status result = EXT_LANG_BT_ERROR;
   int raw_arg = 0;
@@ -128,11 +145,11 @@ mi_cmd_stack_list_frames (char *command, char **argv, int argc)
   if (fi == NULL)
     error (_("-stack-list-frames: Not enough frames in stack."));
 
-  cleanup_stack = make_cleanup_ui_out_list_begin_end (current_uiout, "stack");
+  ui_out_emit_list list_emitter (current_uiout, "stack");
 
   if (! raw_arg && frame_filters)
     {
-      int flags = PRINT_LEVEL | PRINT_FRAME_INFO;
+      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
@@ -159,15 +176,14 @@ mi_cmd_stack_list_frames (char *command, char **argv, int argc)
          QUIT;
          /* Print the location and the address always, even for level 0.
             If args is 0, don't print the arguments.  */
-         print_frame_info (fi, 1, LOC_AND_ADDRESS, 0 /* args */, 0);
+         print_frame_info (user_frame_print_options,
+                           fi, 1, LOC_AND_ADDRESS, 0 /* args */, 0);
        }
     }
-
-  do_cleanups (cleanup_stack);
 }
 
 void
-mi_cmd_stack_info_depth (char *command, char **argv, int argc)
+mi_cmd_stack_info_depth (const char *command, char **argv, int argc)
 {
   int frame_high;
   int i;
@@ -188,7 +204,7 @@ mi_cmd_stack_info_depth (char *command, char **argv, int argc)
        i++, fi = get_prev_frame (fi))
     QUIT;
 
-  ui_out_field_int (current_uiout, "depth", i);
+  current_uiout->field_signed ("depth", i);
 }
 
 /* Print a list of the locals for the current frame.  With argument of
@@ -196,19 +212,17 @@ mi_cmd_stack_info_depth (char *command, char **argv, int argc)
    values.  */
 
 void
-mi_cmd_stack_list_locals (char *command, char **argv, int argc)
+mi_cmd_stack_list_locals (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;
-  int print_value;
+  enum print_values print_value;
   int oind = 0;
   int skip_unavailable = 0;
-  int i;
 
   if (argc > 1)
     {
-      int i;
       enum opt
       {
        NO_FRAME_FILTERS,
@@ -234,6 +248,7 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc)
            {
            case NO_FRAME_FILTERS:
              raw_arg = oind;
+             break;
            case SKIP_UNAVAILABLE:
              skip_unavailable = 1;
              break;
@@ -252,17 +267,18 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc)
 
    if (! raw_arg && frame_filters)
      {
-       int flags = PRINT_LEVEL | PRINT_LOCALS;
+       frame_filter_flags flags = PRINT_LEVEL | PRINT_LOCALS;
 
-       result = apply_ext_lang_frame_filter (frame, flags, print_value,
-                                            current_uiout, 0, 0);
+       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 (locals, print_value, frame,
+       list_args_or_locals (user_frame_print_options,
+                           locals, print_value, frame,
                            skip_unavailable);
      }
 }
@@ -272,13 +288,12 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc)
    values.  */
 
 void
-mi_cmd_stack_list_args (char *command, char **argv, int argc)
+mi_cmd_stack_list_args (const char *command, char **argv, int argc)
 {
   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;
@@ -346,12 +361,11 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc)
   if (fi == NULL)
     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");
 
   if (! raw_arg && frame_filters)
     {
-      int flags = PRINT_LEVEL | PRINT_ARGS;
+      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
@@ -360,9 +374,9 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc)
       if (py_frame_low == -1)
        py_frame_low++;
 
-      result = apply_ext_lang_frame_filter (get_current_frame (), flags,
-                                           print_values, current_uiout,
-                                           py_frame_low, frame_high);
+      result = mi_apply_ext_lang_frame_filter (get_current_frame (), flags,
+                                              print_values, current_uiout,
+                                              py_frame_low, frame_high);
     }
 
      /* Run the inbuilt backtrace if there are no filters registered, or
@@ -375,16 +389,13 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc)
           fi && (i <= frame_high || frame_high == -1);
           i++, fi = get_prev_frame (fi))
        {
-         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 (arguments, print_values, fi, skip_unavailable);
-         do_cleanups (cleanup_frame);
+         ui_out_emit_tuple tuple_emitter (uiout, "frame");
+         uiout->field_signed ("level", i);
+         list_args_or_locals (user_frame_print_options,
+                              arguments, print_values, fi, skip_unavailable);
        }
     }
-  do_cleanups (cleanup_stack_args);
 }
 
 /* Print a list of the local variables (including arguments) for the 
@@ -393,18 +404,17 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc)
    parse_print_value for possible values.  */
 
 void
-mi_cmd_stack_list_variables (char *command, char **argv, int argc)
+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;
-  int print_value;
+  enum print_values print_value;
   int oind = 0;
   int skip_unavailable = 0;
 
   if (argc > 1)
     {
-      int i;
       enum opt
       {
        NO_FRAME_FILTERS,
@@ -448,17 +458,19 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc)
 
    if (! raw_arg && frame_filters)
      {
-       int flags = PRINT_LEVEL | PRINT_ARGS | PRINT_LOCALS;
+       frame_filter_flags flags = PRINT_LEVEL | PRINT_ARGS | PRINT_LOCALS;
 
-       result = apply_ext_lang_frame_filter (frame, flags, print_value,
-                                            current_uiout, 0, 0);
+       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 (all, print_value, frame,
+       list_args_or_locals (user_frame_print_options,
+                           all, print_value, frame,
                            skip_unavailable);
      }
 }
@@ -474,9 +486,7 @@ static void
 list_arg_or_local (const struct frame_arg *arg, enum what_to_list what,
                   enum print_values values, int skip_unavailable)
 {
-  struct cleanup *old_chain;
   struct ui_out *uiout = current_uiout;
-  struct ui_file *stb;
 
   gdb_assert (!arg->val || !arg->error);
   gdb_assert ((values == PRINT_NO_VALUES && arg->val == NULL
@@ -499,54 +509,50 @@ list_arg_or_local (const struct frame_arg *arg, enum what_to_list what,
                                         TYPE_LENGTH (value_type (arg->val))))))
     return;
 
-  stb = mem_fileopen ();
-  old_chain = make_cleanup_ui_file_delete (stb);
-
+  gdb::optional<ui_out_emit_tuple> tuple_emitter;
   if (values != PRINT_NO_VALUES || what == all)
-    make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
+    tuple_emitter.emplace (uiout, nullptr);
+
+  string_file stb;
 
-  fputs_filtered (SYMBOL_PRINT_NAME (arg->sym), stb);
+  stb.puts (arg->sym->print_name ());
   if (arg->entry_kind == print_entry_values_only)
-    fputs_filtered ("@entry", stb);
-  ui_out_field_stream (uiout, "name", stb);
+    stb.puts ("@entry");
+  uiout->field_stream ("name", stb);
 
   if (what == all && SYMBOL_IS_ARGUMENT (arg->sym))
-    ui_out_field_int (uiout, "arg", 1);
+    uiout->field_signed ("arg", 1);
 
   if (values == PRINT_SIMPLE_VALUES)
     {
       check_typedef (arg->sym->type);
-      type_print (arg->sym->type, "", stb, -1);
-      ui_out_field_stream (uiout, "type", stb);
+      type_print (arg->sym->type, "", &stb, -1);
+      uiout->field_stream ("type", stb);
     }
 
   if (arg->val || arg->error)
     {
-      volatile struct gdb_exception except;
-
       if (arg->error)
-       except.message = arg->error;
+       stb.printf (_("<error reading variable: %s>"), arg->error.get ());
       else
        {
-         /* TRY_CATCH has two statements, wrap it in a block.  */
-
-         TRY_CATCH (except, RETURN_MASK_ERROR)
+         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)));
+             common_val_print (arg->val, &stb, 0, &opts,
+                               language_def (arg->sym->language ()));
+           }
+         catch (const gdb_exception_error &except)
+           {
+             stb.printf (_("<error reading variable: %s>"),
+                         except.what ());
            }
        }
-      if (except.message)
-       fprintf_filtered (stb, _("<error reading variable: %s>"),
-                         except.message);
-      ui_out_field_stream (uiout, "value", stb);
+      uiout->field_stream ("value", stb);
     }
-
-  do_cleanups (old_chain);
 }
 
 /* Print a list of the objects for the frame FI in a certain form,
@@ -556,15 +562,15 @@ list_arg_or_local (const struct frame_arg *arg, enum what_to_list what,
    are available.  */
 
 static void
-list_args_or_locals (enum what_to_list what, enum print_values values,
+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)
 {
-  struct block *block;
+  const struct block *block;
   struct symbol *sym;
   struct block_iterator iter;
-  struct cleanup *cleanup_list;
   struct type *type;
-  char *name_of_result;
+  const char *name_of_result;
   struct ui_out *uiout = current_uiout;
 
   block = get_frame_block (fi, 0);
@@ -585,7 +591,7 @@ list_args_or_locals (enum what_to_list what, enum print_values values,
                      "unexpected what_to_list: %d", (int) what);
     }
 
-  cleanup_list = make_cleanup_ui_out_list_begin_end (uiout, name_of_result);
+  ui_out_emit_list list_emitter (uiout, name_of_result);
 
   while (block != 0)
     {
@@ -628,17 +634,15 @@ list_args_or_locals (enum what_to_list what, enum print_values values,
              struct frame_arg arg, entryarg;
 
              if (SYMBOL_IS_ARGUMENT (sym))
-               sym2 = lookup_symbol (SYMBOL_LINKAGE_NAME (sym),
+               sym2 = lookup_symbol (sym->linkage_name (),
                                      block, VAR_DOMAIN,
-                                     NULL);
+                                     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;
 
@@ -652,7 +656,7 @@ list_args_or_locals (enum what_to_list what, enum print_values values,
                    {
                case PRINT_ALL_VALUES:
                  if (SYMBOL_IS_ARGUMENT (sym))
-                   read_frame_arg (sym2, fi, &arg, &entryarg);
+                   read_frame_arg (fp_opts, sym2, fi, &arg, &entryarg);
                  else
                    read_frame_local (sym2, fi, &arg);
                    }
@@ -663,8 +667,6 @@ list_args_or_locals (enum what_to_list what, enum print_values values,
                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);
            }
        }
 
@@ -673,23 +675,97 @@ list_args_or_locals (enum what_to_list what, enum print_values values,
       else
        block = BLOCK_SUPERBLOCK (block);
     }
-  do_cleanups (cleanup_list);
 }
 
+/* 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)
+{
+  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;
+
+         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;
+       }
+    }
+
+  /* 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 (char *command, char **argv, int argc)
+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_command (argv[0], 1 /* not used */ );
+  select_frame_for_mi (parse_frame_specification (argv[0]));
 }
 
 void
-mi_cmd_stack_info_frame (char *command, char **argv, int argc)
+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 (get_selected_frame (NULL), 1, LOC_AND_ADDRESS, 0, 1);
+  print_frame_info (user_frame_print_options,
+                   get_selected_frame (NULL), 1, LOC_AND_ADDRESS, 0, 1);
 }
This page took 0.031109 seconds and 4 git commands to generate.