+
+/* Implement the "-ada-task-info" command. */
+
+void
+mi_cmd_ada_task_info (const char *command, char **argv, int argc)
+{
+ if (argc != 0 && argc != 1)
+ error (_("Invalid MI command"));
+
+ print_ada_task_info (current_uiout, argv[0], current_inferior ());
+}
+
+/* Print EXPRESSION according to VALUES. */
+
+static void
+print_variable_or_computed (const char *expression, enum print_values values)
+{
+ struct value *val;
+ struct type *type;
+ struct ui_out *uiout = current_uiout;
+
+ string_file stb;
+
+ expression_up expr = parse_expression (expression);
+
+ if (values == PRINT_SIMPLE_VALUES)
+ val = evaluate_type (expr.get ());
+ else
+ val = evaluate_expression (expr.get ());
+
+ gdb::optional<ui_out_emit_tuple> tuple_emitter;
+ if (values != PRINT_NO_VALUES)
+ tuple_emitter.emplace (uiout, nullptr);
+ uiout->field_string ("name", expression);
+
+ switch (values)
+ {
+ case PRINT_SIMPLE_VALUES:
+ type = check_typedef (value_type (val));
+ type_print (value_type (val), "", &stb, -1);
+ uiout->field_stream ("type", stb);
+ if (TYPE_CODE (type) != TYPE_CODE_ARRAY
+ && TYPE_CODE (type) != TYPE_CODE_STRUCT
+ && TYPE_CODE (type) != TYPE_CODE_UNION)
+ {
+ struct value_print_options opts;
+
+ get_no_prettyformat_print_options (&opts);
+ opts.deref_ref = 1;
+ common_val_print (val, &stb, 0, &opts, current_language);
+ uiout->field_stream ("value", stb);
+ }
+ break;
+ case PRINT_ALL_VALUES:
+ {
+ struct value_print_options opts;
+
+ get_no_prettyformat_print_options (&opts);
+ opts.deref_ref = 1;
+ common_val_print (val, &stb, 0, &opts, current_language);
+ uiout->field_stream ("value", stb);
+ }
+ break;
+ }
+}
+
+/* Implement the "-trace-frame-collected" command. */
+
+void
+mi_cmd_trace_frame_collected (const char *command, char **argv, int argc)
+{
+ struct bp_location *tloc;
+ int stepping_frame;
+ struct collection_list *clist;
+ struct collection_list tracepoint_list, stepping_list;
+ struct traceframe_info *tinfo;
+ int oind = 0;
+ enum print_values var_print_values = PRINT_ALL_VALUES;
+ enum print_values comp_print_values = PRINT_ALL_VALUES;
+ int registers_format = 'x';
+ int memory_contents = 0;
+ struct ui_out *uiout = current_uiout;
+ enum opt
+ {
+ VAR_PRINT_VALUES,
+ COMP_PRINT_VALUES,
+ REGISTERS_FORMAT,
+ MEMORY_CONTENTS,
+ };
+ static const struct mi_opt opts[] =
+ {
+ {"-var-print-values", VAR_PRINT_VALUES, 1},
+ {"-comp-print-values", COMP_PRINT_VALUES, 1},
+ {"-registers-format", REGISTERS_FORMAT, 1},
+ {"-memory-contents", MEMORY_CONTENTS, 0},
+ { 0, 0, 0 }
+ };
+
+ while (1)
+ {
+ char *oarg;
+ int opt = mi_getopt ("-trace-frame-collected", argc, argv, opts,
+ &oind, &oarg);
+ if (opt < 0)
+ break;
+ switch ((enum opt) opt)
+ {
+ case VAR_PRINT_VALUES:
+ var_print_values = mi_parse_print_values (oarg);
+ break;
+ case COMP_PRINT_VALUES:
+ comp_print_values = mi_parse_print_values (oarg);
+ break;
+ case REGISTERS_FORMAT:
+ registers_format = oarg[0];
+ break;
+ case MEMORY_CONTENTS:
+ memory_contents = 1;
+ break;
+ }
+ }
+
+ if (oind != argc)
+ error (_("Usage: -trace-frame-collected "
+ "[--var-print-values PRINT_VALUES] "
+ "[--comp-print-values PRINT_VALUES] "
+ "[--registers-format FORMAT]"
+ "[--memory-contents]"));
+
+ /* This throws an error is not inspecting a trace frame. */
+ tloc = get_traceframe_location (&stepping_frame);
+
+ /* This command only makes sense for the current frame, not the
+ selected frame. */
+ scoped_restore_current_thread restore_thread;
+ select_frame (get_current_frame ());
+
+ encode_actions (tloc, &tracepoint_list, &stepping_list);
+
+ if (stepping_frame)
+ clist = &stepping_list;
+ else
+ clist = &tracepoint_list;
+
+ tinfo = get_traceframe_info ();
+
+ /* Explicitly wholly collected variables. */
+ {
+ ui_out_emit_list list_emitter (uiout, "explicit-variables");
+ const std::vector<std::string> &wholly_collected
+ = clist->wholly_collected ();
+ for (size_t i = 0; i < wholly_collected.size (); i++)
+ {
+ const std::string &str = wholly_collected[i];
+ print_variable_or_computed (str.c_str (), var_print_values);
+ }
+ }
+
+ /* Computed expressions. */
+ {
+ ui_out_emit_list list_emitter (uiout, "computed-expressions");
+
+ const std::vector<std::string> &computed = clist->computed ();
+ for (size_t i = 0; i < computed.size (); i++)
+ {
+ const std::string &str = computed[i];
+ print_variable_or_computed (str.c_str (), comp_print_values);
+ }
+ }
+
+ /* Registers. Given pseudo-registers, and that some architectures
+ (like MIPS) actually hide the raw registers, we don't go through
+ the trace frame info, but instead consult the register cache for
+ register availability. */
+ {
+ struct frame_info *frame;
+ struct gdbarch *gdbarch;
+ int regnum;
+ int numregs;
+
+ ui_out_emit_list list_emitter (uiout, "registers");
+
+ frame = get_selected_frame (NULL);
+ gdbarch = get_frame_arch (frame);
+ numregs = gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch);
+
+ for (regnum = 0; regnum < numregs; regnum++)
+ {
+ if (gdbarch_register_name (gdbarch, regnum) == NULL
+ || *(gdbarch_register_name (gdbarch, regnum)) == '\0')
+ continue;
+
+ output_register (frame, regnum, registers_format, 1);
+ }
+ }
+
+ /* Trace state variables. */
+ {
+ ui_out_emit_list list_emitter (uiout, "tvars");
+
+ for (int tvar : tinfo->tvars)
+ {
+ struct trace_state_variable *tsv;
+
+ tsv = find_trace_state_variable_by_number (tvar);
+
+ ui_out_emit_tuple tuple_emitter (uiout, NULL);
+
+ if (tsv != NULL)
+ {
+ uiout->field_fmt ("name", "$%s", tsv->name.c_str ());
+
+ tsv->value_known = target_get_trace_state_variable_value (tsv->number,
+ &tsv->value);
+ uiout->field_int ("current", tsv->value);
+ }
+ else
+ {
+ uiout->field_skip ("name");
+ uiout->field_skip ("current");
+ }
+ }
+ }
+
+ /* Memory. */
+ {
+ std::vector<mem_range> available_memory;
+
+ traceframe_available_memory (&available_memory, 0, ULONGEST_MAX);
+
+ ui_out_emit_list list_emitter (uiout, "memory");
+
+ for (const mem_range &r : available_memory)
+ {
+ struct gdbarch *gdbarch = target_gdbarch ();
+
+ ui_out_emit_tuple tuple_emitter (uiout, NULL);
+
+ uiout->field_core_addr ("address", gdbarch, r.start);
+ uiout->field_int ("length", r.length);
+
+ gdb::byte_vector data (r.length);
+
+ if (memory_contents)
+ {
+ if (target_read_memory (r.start, data.data (), r.length) == 0)
+ {
+ std::string data_str = bin2hex (data.data (), r.length);
+ uiout->field_string ("contents", data_str.c_str ());
+ }
+ else
+ uiout->field_skip ("contents");
+ }
+ }
+ }
+}
+
+void
+_initialize_mi_main (void)
+{
+ struct cmd_list_element *c;
+
+ add_setshow_boolean_cmd ("mi-async", class_run,
+ &mi_async_1, _("\
+Set whether MI asynchronous mode is enabled."), _("\
+Show whether MI asynchronous mode is enabled."), _("\
+Tells GDB whether MI should be in asynchronous mode."),
+ set_mi_async_command,
+ show_mi_async_command,
+ &setlist,
+ &showlist);
+
+ /* Alias old "target-async" to "mi-async". */
+ c = add_alias_cmd ("target-async", "mi-async", class_run, 0, &setlist);
+ deprecate_cmd (c, "set mi-async");
+ c = add_alias_cmd ("target-async", "mi-async", class_run, 0, &showlist);
+ deprecate_cmd (c, "show mi-async");
+}