+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;
+
+ 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 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
+list_arg_or_local (const struct frame_arg *arg, enum what_to_list what,
+ enum print_values values, int skip_unavailable)
+{
+ 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 (arg->sym->print_name ());
+ 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_signed ("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.get ());
+ 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 (arg->sym->language ()));
+ }
+ catch (const gdb_exception_error &except)
+ {
+ stb.printf (_("<error reading variable: %s>"),
+ except.what ());
+ }
+ }
+ uiout->field_stream ("value", stb);
+ }