aboutsummaryrefslogtreecommitdiff
path: root/gdb/mi/mi-cmds.c
diff options
context:
space:
mode:
authorJan Vrany <jan.vrany@labware.com>2020-06-23 14:45:38 +0100
committerAndrew Burgess <aburgess@redhat.com>2021-12-14 11:28:00 +0000
commit1f6c8c3317e5692e9994c18f427b45093863d572 (patch)
treebec5656e39509e778ead182d9fff1388945b4ef9 /gdb/mi/mi-cmds.c
parent3be0fed62e0dfb36d674944fe85eaebbf70b9029 (diff)
downloadbinutils-1f6c8c3317e5692e9994c18f427b45093863d572.zip
binutils-1f6c8c3317e5692e9994c18f427b45093863d572.tar.gz
binutils-1f6c8c3317e5692e9994c18f427b45093863d572.tar.bz2
gdb/mi: use separate classes for different types of MI command
This commit changes the infrastructure in mi-cmds.{c,h} to add new sub-classes for the different types of MI command. Instances of these sub-classes are then created and added into mi_cmd_table. The existing mi_cmd class becomes the abstract base class, this has an invoke method and takes care of the suppress notifications handling, before calling a do_invoke virtual method which is implemented by all of the sub-classes. There's currently two different sub-classes, one of pure MI commands, and a second for MI commands that delegate to CLI commands. There should be no user visible changes after this commit.
Diffstat (limited to 'gdb/mi/mi-cmds.c')
-rw-r--r--gdb/mi/mi-cmds.c140
1 files changed, 113 insertions, 27 deletions
diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c
index e0eba0b..58892fe 100644
--- a/gdb/mi/mi-cmds.c
+++ b/gdb/mi/mi-cmds.c
@@ -22,6 +22,7 @@
#include "top.h"
#include "mi-cmds.h"
#include "mi-main.h"
+#include "mi-parse.h"
#include <map>
#include <string>
@@ -33,6 +34,80 @@ using mi_cmd_up = std::unique_ptr<struct mi_cmd>;
static std::map<std::string, mi_cmd_up> mi_cmd_table;
+/* MI command with a pure MI implementation. */
+
+struct mi_command_mi : public mi_cmd
+{
+ /* Constructor. For NAME and SUPPRESS_NOTIFICATION see mi_cmd
+ constructor, FUNC is the function called from do_invoke, which
+ implements this MI command. */
+ mi_command_mi (const char *name, mi_cmd_argv_ftype func,
+ int *suppress_notification)
+ : mi_cmd (name, suppress_notification),
+ m_argv_function (func)
+ {
+ gdb_assert (func != nullptr);
+ }
+
+protected:
+
+ /* Called when this MI command has been invoked, calls m_argv_function
+ with arguments contained within PARSE. */
+ void do_invoke (struct mi_parse *parse) const override
+ {
+ mi_parse_argv (parse->args, parse);
+
+ if (parse->argv == nullptr)
+ error (_("Problem parsing arguments: %s %s"), parse->command,
+ parse->args);
+
+ this->m_argv_function (parse->command, parse->argv, parse->argc);
+ }
+
+private:
+
+ /* The function that implements this MI command. */
+ mi_cmd_argv_ftype *m_argv_function;
+};
+
+/* MI command implemented on top of a CLI command. */
+
+struct mi_command_cli : public mi_cmd
+{
+ /* Constructor. For NAME and SUPPRESS_NOTIFICATION see mi_cmd
+ constructor, CLI_NAME is the name of a CLI command that should be
+ invoked to implement this MI command. If ARGS_P is true then any
+ arguments from entered by the user as part of the MI command line are
+ forwarded to CLI_NAME as its argument string, otherwise, if ARGS_P is
+ false, nullptr is send to CLI_NAME as its argument string. */
+ mi_command_cli (const char *name, const char *cli_name, bool args_p,
+ int *suppress_notification)
+ : mi_cmd (name, suppress_notification),
+ m_cli_name (cli_name),
+ m_args_p (args_p)
+ { /* Nothing. */ }
+
+protected:
+
+ /* Called when this MI command has been invoked, calls the m_cli_name
+ CLI function. In m_args_p is true then the argument string from
+ within PARSE is passed through to the CLI function, otherwise nullptr
+ is passed through to the CLI function as its argument string. */
+ void do_invoke (struct mi_parse *parse) const override
+ {
+ const char *args = m_args_p ? parse->args : nullptr;
+ mi_execute_cli_command (m_cli_name, m_args_p, args);
+ }
+
+private:
+
+ /* The name of the CLI command to execute. */
+ const char *m_cli_name;
+
+ /* Should we be passing an argument string to the m_cli_name function? */
+ bool m_args_p;
+};
+
/* Insert COMMAND into the global mi_cmd_table. Return false if
COMMAND->name already exists in mi_cmd_table, in which case COMMAND will
not have been added to mi_cmd_table. Otherwise, return true, and
@@ -42,9 +117,8 @@ static bool
insert_mi_cmd_entry (mi_cmd_up command)
{
gdb_assert (command != nullptr);
- gdb_assert (command->name != nullptr);
- std::string name (command->name);
+ const std::string &name = command->name ();
if (mi_cmd_table.find (name) != mi_cmd_table.end ())
return false;
@@ -53,16 +127,6 @@ insert_mi_cmd_entry (mi_cmd_up command)
return true;
}
-/* Create an mi_cmd structure with name NAME. */
-
-static mi_cmd_up
-create_mi_cmd (const char *name)
-{
- mi_cmd_up cmd (new mi_cmd ());
- cmd->name = name;
- return cmd;
-}
-
/* Create and register a new MI command with an MI specific implementation.
NAME must name an MI command that does not already exist, otherwise an
assertion will trigger. */
@@ -71,14 +135,10 @@ static void
add_mi_cmd_mi (const char *name, mi_cmd_argv_ftype function,
int *suppress_notification = nullptr)
{
- mi_cmd_up cmd_up = create_mi_cmd (name);
-
- cmd_up->cli.cmd = nullptr;
- cmd_up->cli.args_p = 0;
- cmd_up->argv_func = function;
- cmd_up->suppress_notification = suppress_notification;
+ mi_cmd_up command (new mi_command_mi (name, function,
+ suppress_notification));
- bool success = insert_mi_cmd_entry (std::move (cmd_up));
+ bool success = insert_mi_cmd_entry (std::move (command));
gdb_assert (success);
}
@@ -90,18 +150,44 @@ static void
add_mi_cmd_cli (const char *name, const char *cli_name, int args_p,
int *suppress_notification = nullptr)
{
- mi_cmd_up cmd_up = create_mi_cmd (name);
-
- cmd_up->cli.cmd = cli_name;
- cmd_up->cli.args_p = args_p;
- cmd_up->argv_func = nullptr;
- cmd_up->suppress_notification = suppress_notification;
+ mi_cmd_up command (new mi_command_cli (name, cli_name, args_p != 0,
+ suppress_notification));
- bool success = insert_mi_cmd_entry (std::move (cmd_up));
+ bool success = insert_mi_cmd_entry (std::move (command));
gdb_assert (success);
}
-/* Initialize MI_CMD_TABLE, the global map of MI commands. */
+/* See mi-cmds.h. */
+
+mi_cmd::mi_cmd (const char *name, int *suppress_notification)
+ : m_name (name),
+ m_suppress_notification (suppress_notification)
+{
+ gdb_assert (m_name != nullptr && m_name[0] != '\0');
+}
+
+/* See mi-cmds.h. */
+
+void
+mi_cmd::invoke (struct mi_parse *parse) const
+{
+ gdb::optional<scoped_restore_tmpl<int>> restore
+ = do_suppress_notification ();
+ this->do_invoke (parse);
+}
+
+/* See mi-cmds.h. */
+
+gdb::optional<scoped_restore_tmpl<int>>
+mi_cmd::do_suppress_notification () const
+{
+ if (m_suppress_notification != nullptr)
+ return scoped_restore_tmpl<int> (m_suppress_notification, 1);
+ else
+ return {};
+}
+
+/* Initialize the available MI commands. */
static void
build_table ()