X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fmi%2Fmi-cmd-stack.c;h=6cd255d072003e811bfc74848c65283bcabbada8;hb=c1b5c1ebc938b6dc0277363b8c47d75b0b5a621f;hp=1cd9a47586fcd35ca597a0acb784051bf1304a42;hpb=1e611234ee3f4a1d2434f3fe7530cab87c936e0d;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c index 1cd9a47586..6cd255d072 100644 --- a/gdb/mi/mi-cmd-stack.c +++ b/gdb/mi/mi-cmd-stack.c @@ -1,5 +1,5 @@ /* MI Command Set - stack commands. - Copyright (C) 2000-2013 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. @@ -27,41 +27,50 @@ #include "block.h" #include "stack.h" #include "dictionary.h" -#include "gdb_string.h" #include "language.h" #include "valprint.h" -#include "exceptions.h" #include "utils.h" #include "mi-getopt.h" -#include "python/python.h" +#include "extension.h" #include +#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); + 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 (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; } -/* Parse the --no-frame-filters option in commands where we cannot use - mi_getopt. */ -static int -parse_no_frames_option (const char *arg) -{ - if (arg && (strcmp (arg, "--no-frame-filters") == 0)) - return 1; +/* Like apply_ext_lang_frame_filter, but take a print_values */ - return 0; +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 @@ -71,14 +80,13 @@ parse_no_frames_option (const char *arg) 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 py_bt_status result = PY_BT_ERROR; + enum ext_lang_bt_status result = EXT_LANG_BT_ERROR; int raw_arg = 0; int oind = 0; enum opt @@ -137,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 @@ -150,14 +158,14 @@ mi_cmd_stack_list_frames (char *command, char **argv, int argc) if (py_frame_low == -1) py_frame_low++; - result = apply_frame_filter (get_current_frame (), flags, - NO_VALUES, current_uiout, - py_frame_low, frame_high); + result = apply_ext_lang_frame_filter (get_current_frame (), flags, + NO_VALUES, current_uiout, + py_frame_low, frame_high); } /* 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 == PY_BT_NO_FILTERS) + 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. */ @@ -168,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 */ ); + 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; @@ -197,25 +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); -} - -static enum print_values -parse_print_values (char *name) -{ - if (strcmp (name, "0") == 0 - || strcmp (name, mi_no_values) == 0) - return PRINT_NO_VALUES; - else if (strcmp (name, "1") == 0 - || strcmp (name, mi_all_values) == 0) - return PRINT_ALL_VALUES; - else if (strcmp (name, "2") == 0 - || strcmp (name, mi_simple_values) == 0) - return PRINT_SIMPLE_VALUES; - else - error (_("Unknown value for PRINT_VALUES: must be: \ -0 or \"%s\", 1 or \"%s\", 2 or \"%s\""), - mi_no_values, mi_all_values, mi_simple_values); + current_uiout->field_signed ("depth", i); } /* Print a list of the locals for the current frame. With argument of @@ -223,36 +212,74 @@ parse_print_values (char *name) 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 py_bt_status result = PY_BT_ERROR; - int print_value; + enum ext_lang_bt_status result = EXT_LANG_BT_ERROR; + enum print_values print_value; + int oind = 0; + int skip_unavailable = 0; - if (argc > 0) - raw_arg = parse_no_frames_option (argv[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 } + }; + + 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; + } + } + } - if (argc < 1 || argc > 2 || (argc == 2 && ! raw_arg) - || (argc == 1 && raw_arg)) - error (_("-stack-list-locals: Usage: [--no-frame-filters] PRINT_VALUES")); + /* 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 = parse_print_values (argv[raw_arg]); + print_value = mi_parse_print_values (argv[oind]); if (! raw_arg && frame_filters) { - int flags = PRINT_LEVEL | PRINT_LOCALS; + frame_filter_flags flags = PRINT_LEVEL | PRINT_LOCALS; - result = apply_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 == PY_BT_NO_FILTERS) + 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); } } @@ -261,29 +288,58 @@ 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; - enum py_bt_status result = PY_BT_ERROR; + 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 } + }; - if (argc > 0) - raw_arg = parse_no_frames_option (argv[0]); + while (1) + { + char *oarg; + int opt = mi_getopt_allow_unknown ("-stack-list-args", argc, 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; + } + } - if (argc < 1 || (argc > 3 && ! raw_arg) || (argc == 2 && ! raw_arg)) - error (_("-stack-list-arguments: Usage: " \ - "[--no-frame-filters] PRINT_VALUES [FRAME_LOW FRAME_HIGH]")); + 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 + raw_arg]); - frame_high = atoi (argv[2 + raw_arg]); + frame_low = atoi (argv[1 + oind]); + frame_high = atoi (argv[2 + oind]); } else { @@ -293,7 +349,7 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc) frame_high = -1; } - print_values = parse_print_values (argv[raw_arg]); + 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 @@ -305,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 @@ -319,14 +374,14 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc) if (py_frame_low == -1) py_frame_low++; - result = apply_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 if "--no-frame-filters" has been specified from the command. */ - if (! frame_filters || raw_arg || result == PY_BT_NO_FILTERS) + 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. */ @@ -334,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); - 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 @@ -352,37 +404,74 @@ 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 py_bt_status result = PY_BT_ERROR; - int print_value; + enum ext_lang_bt_status result = EXT_LANG_BT_ERROR; + enum print_values print_value; + int oind = 0; + int skip_unavailable = 0; - if (argc > 0) - raw_arg = parse_no_frames_option (argv[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 } + }; + + 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; + } + } + } - if (argc < 1 || argc > 2 || (argc == 2 && ! raw_arg) - || (argc == 1 && raw_arg)) - error (_("-stack-list-variables: Usage: " \ - "[--no-frame-filters] PRINT_VALUES")); + /* 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 = parse_print_values (argv[raw_arg]); + print_value = mi_parse_print_values (argv[oind]); 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_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 == PY_BT_NO_FILTERS) + 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); } } @@ -390,19 +479,14 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc) 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. */ + 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 list_arg_or_local (const struct frame_arg *arg, enum what_to_list what, - enum print_values values) + enum print_values values, int skip_unavailable) { - struct cleanup *old_chain; - struct cleanup *cleanup_tuple = NULL; struct ui_out *uiout = current_uiout; - struct ui_file *stb; - - stb = mem_fileopen (); - old_chain = make_cleanup_ui_file_delete (stb); gdb_assert (!arg->val || !arg->error); gdb_assert ((values == PRINT_NO_VALUES && arg->val == NULL @@ -414,70 +498,79 @@ list_arg_or_local (const struct frame_arg *arg, enum what_to_list what, || (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 tuple_emitter; if (values != PRINT_NO_VALUES || what == all) - cleanup_tuple = 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 (_(""), 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_raw_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 (_(""), + except.what ()); } } - if (except.message) - fprintf_filtered (stb, _(""), - except.message); - ui_out_field_stream (uiout, "value", stb); + uiout->field_stream ("value", stb); } - - if (values != PRINT_NO_VALUES || what == all) - do_cleanups (cleanup_tuple); - do_cleanups (old_chain); } -/* 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 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 (enum what_to_list what, enum print_values values, - struct frame_info *fi) +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); @@ -498,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) { @@ -541,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; @@ -564,17 +655,18 @@ list_args_or_locals (enum what_to_list what, enum print_values values, && TYPE_CODE (type) != TYPE_CODE_UNION) { case PRINT_ALL_VALUES: - read_frame_arg (sym2, fi, &arg, &entryarg); + if (SYMBOL_IS_ARGUMENT (sym)) + read_frame_arg (fp_opts, sym2, fi, &arg, &entryarg); + else + read_frame_local (sym2, fi, &arg); } break; } if (arg.entry_kind != print_entry_values_only) - list_arg_or_local (&arg, what, 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); - xfree (arg.error); - xfree (entryarg.error); + list_arg_or_local (&entryarg, what, values, skip_unavailable); } } @@ -583,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); + print_frame_info (user_frame_print_options, + get_selected_frame (NULL), 1, LOC_AND_ADDRESS, 0, 1); }