public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 2/2] Use classes to represent MI Command instead of structures
  2017-02-03  5:46 [PATCH 0/2] Use std::hashmap and MI commands classes in mi-cmds.c didier.nadeau
@ 2017-02-03  5:46 ` didier.nadeau
  2017-02-03  5:46 ` [PATCH 1/2] Use std::map for MI commands in mi-cmds.c didier.nadeau
  2017-02-06 15:58 ` [PATCH 0/2] Use std::hashmap and MI commands classes " Pedro Alves
  2 siblings, 0 replies; 10+ messages in thread
From: didier.nadeau @ 2017-02-03  5:46 UTC (permalink / raw)
  To: gdb-patches; +Cc: didier.nadeau

From: Didier Nadeau <didier.nadeau@gmail.com>

This commit changes the infrastructure of mi-cmds.h and associated
files to use classes instead of structure to populate the hashmap
containing the commands.

The base class is virtual and there is one subclass MI commands
implemented with pure MI implementation and another for MI commands
implemented over a CLI command.

Logic for suppress_notification and parsing of ARGV/ARGC has been moved
to the classes implementation.

gdb/ChangeLog:
2017-02-03  Didier Nadeau  <didier.nadeau@gmail.com>

    * mi/mi-cmds.c (create_mi_cmd): Remove.
    (mi_command::mi_command): New function.
    (mi_command::do_suppress_notification): New function.
    (mi_command_mi::mi_command_mi): New function.
    (mi_command_mi::invoke): New function.
    (mi_command_cli::mi_command_cli): New function.
    (mi_command_cli::invoke): New function.
    (mi_cmd_lookup): Change return type.
    * mi/mi-cmds.h (struct mi_cli): Remove.
    (struct mi_cmd): Remove.
    (class mi_command): New class.
    (class mi_command_mi): New class.
    (class mi_command_cli): New class.
    (mi_cmd_loopkup): Change return type.
    * mi/mi-main.c (mi_execute_cli_command): Remove declaration.
    (mi_execute_command): Remove suppress_notification handling.
    (mi_cmd_execute): Remove call to argv_func.
    (mi_cmd_execute): Remove call to mi_execute_cli_command.
    (mi_cmd_execute): New call to mi_command::invoke.
    * mi/mi-main.h (mi_execute_cli_command): New declaration.
    * mi/mi-parse.c (mi_parse): Remove call to mi_parse_argv.
    * mi/mi-parse.h (struct mi_parse): Remove field struct mi_cmd.
    (struct mi_parse): New field class mi_command.
    (mi_parse_argv): New declaration.
---
 gdb/mi/mi-cmd-info.c |  2 +-
 gdb/mi/mi-cmds.c     | 97 +++++++++++++++++++++++++++++++++++++---------------
 gdb/mi/mi-cmds.h     | 70 +++++++++++++++++++++++++------------
 gdb/mi/mi-main.c     | 21 ++----------
 gdb/mi/mi-main.h     |  2 ++
 gdb/mi/mi-parse.c    | 18 ++--------
 gdb/mi/mi-parse.h    |  6 +++-
 7 files changed, 130 insertions(+), 86 deletions(-)

diff --git a/gdb/mi/mi-cmd-info.c b/gdb/mi/mi-cmd-info.c
index 12e48bf..99800af 100644
--- a/gdb/mi/mi-cmd-info.c
+++ b/gdb/mi/mi-cmd-info.c
@@ -77,7 +77,7 @@ void
 mi_cmd_info_gdb_mi_command (char *command, char **argv, int argc)
 {
   const char *cmd_name;
-  struct mi_cmd *cmd;
+  mi_command *cmd;
   struct ui_out *uiout = current_uiout;
   struct cleanup *old_chain;
 
diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c
index eb1e446..160b864 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>
 #include <memory>
@@ -37,9 +38,9 @@ static bool
 insert_mi_cmd_entry (mi_cmd_up command)
 {
   gdb_assert (command != NULL);
-  gdb_assert (command->name != NULL);
+  gdb_assert (! command->name ().empty ());
 
-  std::string name (command->name);
+  const std::string &name = command->name ();
 
   if (mi_cmd_table.find (name) != mi_cmd_table.end ())
     return false;
@@ -49,32 +50,16 @@ 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 a pure MI implementation.  */
 
 static void
 add_mi_cmd_mi (const char *name, mi_cmd_argv_ftype function,
 	       int *suppress_notification = NULL)
 {
-  mi_cmd_up cmd_up = create_mi_cmd (name);
+  mi_command *micommand = new mi_command_mi (name, function,
+					     suppress_notification);
 
-  cmd_up->cli.cmd = NULL;
-  cmd_up->cli.args_p = 0;
-  cmd_up->argv_func = function;
-  cmd_up->suppress_notification = suppress_notification;
-
-  bool success = insert_mi_cmd_entry (std::move (cmd_up));
+  bool success = insert_mi_cmd_entry (std::move (mi_cmd_up (micommand)));
   gdb_assert (success);
 }
 
@@ -84,16 +69,71 @@ static void
 add_mi_cmd_cli (const char *name, const char *cli_name, int args_p,
 		int *suppress_notification = NULL)
 {
-  mi_cmd_up cmd_up = create_mi_cmd (name);
-
-  cmd_up->cli.args_p = args_p;
-  cmd_up->suppress_notification = NULL;
-  cmd_up->cli.cmd = cli_name;
+  mi_command *micommand = new mi_command_cli (name, cli_name, args_p,
+					      suppress_notification);
 
-  bool success = insert_mi_cmd_entry (std::move (cmd_up));
+  bool success = insert_mi_cmd_entry (std::move (mi_cmd_up (micommand)));
   gdb_assert (success);
 }
 
+/* See mi-cmds.h  */
+
+mi_command::mi_command (const char *name, int *suppress_notification)
+  : m_name (name),
+    m_suppress_notification (suppress_notification)
+{}
+
+std::unique_ptr<scoped_restore_tmpl<int>>
+mi_command::do_suppress_notification ()
+{
+  if (m_suppress_notification != NULL)
+    return std::unique_ptr<scoped_restore_tmpl <int>> (
+	new scoped_restore_tmpl <int> (m_suppress_notification, 1));
+
+  return std::unique_ptr<scoped_restore_tmpl <int>> ();
+}
+
+mi_command_mi::mi_command_mi (const char *name, mi_cmd_argv_ftype func,
+			      int *suppress_notification)
+  : mi_command (name, suppress_notification),
+    m_argv_function (func)
+{
+  gdb_assert (func != NULL);
+}
+
+void
+mi_command_mi::invoke (struct mi_parse *parse)
+{
+  std::unique_ptr<scoped_restore_tmpl <int>> restore
+    = do_suppress_notification ();
+
+  mi_parse_argv (parse->args, parse);
+
+  if (parse->argv == NULL)
+    error (_("Problem parsing arguments: %s %s"), parse->command, parse->args);
+
+  this->m_argv_function (parse->command, parse->argv, parse->argc);
+}
+
+mi_command_cli::mi_command_cli (const char *name, const char *cli_name,
+				int args_p, int *suppress_notification)
+  : mi_command (name, suppress_notification),
+    m_cli_name (cli_name),
+    m_args_p (args_p)
+{}
+
+void
+mi_command_cli::invoke (struct mi_parse *parse)
+{
+  std::unique_ptr<scoped_restore_tmpl <int>> restore
+    = do_suppress_notification ();
+
+  mi_execute_cli_command (this->m_cli_name.c_str (), this->m_args_p,
+			  parse->args);
+}
+
+/* Initialize the available MI commands.  */
+
 static void
 build_table ()
 {
@@ -237,7 +277,7 @@ build_table ()
 
 /* See mi-cmds.h.  */
 
-struct mi_cmd *
+mi_command *
 mi_cmd_lookup (const char *command)
 {
   gdb_assert (command != NULL);
@@ -255,3 +295,4 @@ _initialize_mi_cmds (void)
 {
   build_table ();
 }
+
diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h
index 75eadc5..c5e596b 100644
--- a/gdb/mi/mi-cmds.h
+++ b/gdb/mi/mi-cmds.h
@@ -124,38 +124,64 @@ extern mi_cmd_argv_ftype mi_cmd_enable_pretty_printing;
 extern mi_cmd_argv_ftype mi_cmd_enable_frame_filters;
 extern mi_cmd_argv_ftype mi_cmd_var_set_update_range;
 
-/* Description of a single command.  */
+/* mi_command base virtual class.  */
 
-struct mi_cli
+class mi_command
 {
-  /* Corresponding CLI command.  If ARGS_P is non-zero, the MI
-     command's argument list is appended to the CLI command.  */
-  const char *cmd;
-  int args_p;
+  public:
+    mi_command (const char *name, int *suppress_notification);
+    virtual ~mi_command () {};
+
+    const std::string &name ()
+    { return m_name; }
+
+    /* Execute the MI command.  */
+    virtual void invoke (struct mi_parse *parse) = 0;
+
+  protected:
+    std::unique_ptr<scoped_restore_tmpl<int>> do_suppress_notification ();
+
+  private:
+
+    /* The name of the command.  */
+    std::string m_name;
+
+    /* Pointer to integer to set during command's invocation.  */
+    int *m_suppress_notification;
 };
 
-struct mi_cmd
+/* MI command with a pure MI implementation.  */
+
+class mi_command_mi : public mi_command
+{
+  public:
+    mi_command_mi (const char *name, mi_cmd_argv_ftype func,
+		   int *suppress_notification);
+    void invoke (struct mi_parse *parse) override;
+
+  private:
+    mi_cmd_argv_ftype *m_argv_function;
+};
+
+/* MI command implemented on top of a CLI command.  */
+
+class mi_command_cli : public mi_command
 {
-  /* Official name of the command.  */
-  const char *name;
-  /* The corresponding CLI command that can be used to implement this
-     MI command (if cli.lhs is non NULL).  */
-  struct mi_cli cli;
-  /* If non-null, the function implementing the MI command.  */
-  mi_cmd_argv_ftype *argv_func;
-  /* If non-null, the pointer to a field in
-     'struct mi_suppress_notification', which will be set to true by MI
-     command processor (mi-main.c:mi_cmd_execute) when this command is
-     being executed.  It will be set back to false when command has been
-     executed.  */
-  int *suppress_notification;
+  public:
+    mi_command_cli (const char *name, const char *cli_name, int args_p,
+		  int *suppress_notification);
+    void invoke (struct mi_parse *parse) override;
+
+  private:
+    std::string m_cli_name;
+    int m_args_p;
 };
 
-typedef std::unique_ptr<struct mi_cmd> mi_cmd_up;
+typedef std::unique_ptr<mi_command> mi_cmd_up;
 
 /* Lookup a command in the MI command table.  */
 
-extern struct mi_cmd *mi_cmd_lookup (const char *command);
+extern mi_command *mi_cmd_lookup (const char *command);
 
 /* Debug flag */
 extern int mi_debug_p;
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index 57c23eb..5c58b6e 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -86,9 +86,6 @@ int mi_proceeded;
 
 extern void _initialize_mi_main (void);
 static void mi_cmd_execute (struct mi_parse *parse);
-
-static void mi_execute_cli_command (const char *cmd, int args_p,
-				    const char *args);
 static void mi_execute_async_cli_command (char *cli_command,
 					  char **argv, int argc);
 static int register_changed_p (int regnum, struct regcache *,
@@ -2155,12 +2152,6 @@ mi_execute_command (const char *cmd, int from_tty)
 
       command->token = token;
 
-      if (command->cmd != NULL && command->cmd->suppress_notification != NULL)
-        {
-          make_cleanup_restore_integer (command->cmd->suppress_notification);
-          *command->cmd->suppress_notification = 1;
-        }
-
       if (do_timings)
 	{
 	  command->cmd_start = new mi_timestamp ();
@@ -2302,17 +2293,9 @@ mi_cmd_execute (struct mi_parse *parse)
 
   current_context = parse;
 
-  if (parse->cmd->argv_func != NULL)
-    {
-      parse->cmd->argv_func (parse->command, parse->argv, parse->argc);
-    }
-  else if (parse->cmd->cli.cmd != 0)
+  if (parse->cmd != NULL)
     {
-      /* FIXME: DELETE THIS. */
-      /* The operation is still implemented by a cli command.  */
-      /* Must be a synchronous one.  */
-      mi_execute_cli_command (parse->cmd->cli.cmd, parse->cmd->cli.args_p,
-			      parse->args);
+      parse->cmd->invoke (parse);
     }
   else
     {
diff --git a/gdb/mi/mi-main.h b/gdb/mi/mi-main.h
index 90ec606..3759738 100644
--- a/gdb/mi/mi-main.h
+++ b/gdb/mi/mi-main.h
@@ -54,5 +54,7 @@ struct mi_suppress_notification
 };
 extern struct mi_suppress_notification mi_suppress_notification;
 
+void mi_execute_cli_command (const char *cmd, int args_p, const char *args);
+
 #endif
 
diff --git a/gdb/mi/mi-parse.c b/gdb/mi/mi-parse.c
index 0df0c31..92ed14c 100644
--- a/gdb/mi/mi-parse.c
+++ b/gdb/mi/mi-parse.c
@@ -106,7 +106,7 @@ mi_parse_escape (const char **string_ptr)
   return c;
 }
 
-static void
+void
 mi_parse_argv (const char *args, struct mi_parse *parse)
 {
   const char *chp = args;
@@ -379,20 +379,8 @@ mi_parse (const char *cmd, char **token)
       chp = skip_spaces_const (chp);
     }
 
-  /* For new argv commands, attempt to return the parsed argument
-     list.  */
-  if (parse->cmd->argv_func != NULL)
-    {
-      mi_parse_argv (chp, parse);
-      if (parse->argv == NULL)
-	error (_("Problem parsing arguments: %s %s"), parse->command, chp);
-    }
-
-  /* FIXME: DELETE THIS */
-  /* For CLI commands, also return the remainder of the
-     command line as a single string. */
-  if (parse->cmd->cli.cmd != NULL)
-    parse->args = xstrdup (chp);
+  /* Save the rest of the arguments for the command.  */
+  parse->args = xstrdup (chp);
 
   discard_cleanups (cleanup);
 
diff --git a/gdb/mi/mi-parse.h b/gdb/mi/mi-parse.h
index b11e5d3..2374087 100644
--- a/gdb/mi/mi-parse.h
+++ b/gdb/mi/mi-parse.h
@@ -44,7 +44,7 @@ struct mi_parse
     enum mi_command_type op;
     char *command;
     char *token;
-    const struct mi_cmd *cmd;
+    mi_command *cmd;
     struct mi_timestamp *cmd_start;
     char *args;
     char **argv;
@@ -77,4 +77,8 @@ extern void mi_parse_free (struct mi_parse *cmd);
 
 enum print_values mi_parse_print_values (const char *name);
 
+/* Split ARGS into argc/argv and store the result in PARSE.  */
+
+void mi_parse_argv (const char *args, struct mi_parse *parse);
+
 #endif
-- 
1.9.1

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/2] Use std::map for MI commands in mi-cmds.c
  2017-02-03  5:46 [PATCH 0/2] Use std::hashmap and MI commands classes in mi-cmds.c didier.nadeau
  2017-02-03  5:46 ` [PATCH 2/2] Use classes to represent MI Command instead of structures didier.nadeau
@ 2017-02-03  5:46 ` didier.nadeau
  2017-02-06 15:58 ` [PATCH 0/2] Use std::hashmap and MI commands classes " Pedro Alves
  2 siblings, 0 replies; 10+ messages in thread
From: didier.nadeau @ 2017-02-03  5:46 UTC (permalink / raw)
  To: gdb-patches; +Cc: didier.nadeau

From: Didier Nadeau <didier.nadeau@gmail.com>

This changes the hashmap used in mi-cmds.c from a custom
structure to std::map. This is done to be able to add new
MI commands at runtime, the previous structure had a fixed
size array.

gdb/ChangeLog:
2017-02-02  Didier Nadeau  <didier.nadeau@gmail.com>

	* mi/mi-cmds.h (mi_cmd_up): New typedef.
	(mi_lookup): Rename to ...
	(mi_cmd_lookup): this.
	* mi/mi-cmds.c (_initialize_mi_cmds): Remove declaration.
	(lookup_table): Remove declaration.
	(build_table): Remove declaration.
	(mi_table): Rename to ...
	(mi_cmd_table): this and change to std::map.
	(insert_mi_cmd_entry): New function.
	(DEF_MI_CMD_CLI_1, DEF_MI_CMD_CLI, DEF_MI_CMD_MI,
	DEF_MI_CMD_MI_1): Remove macros.
	(mi_cmds): Remove array.
	(mi_lookup): Rename to ...
	(mi_cmd_lookup): this.
	(create_mi_cmd): New function.
	(struct mi_cmd_stats): Remove.
	(stats): Remove.
	(add_mi_cmd_cli, add_mi_cmd_mi): New functions.
	(lookup_table): Remove.
	(build_table): Remove parameter.
	* mi/mi-parse.c (mi_parse): Change call from mi_lookup to
	mi_cmd_lookup.
	* mi/mi-cmd-info.c (mi_cmd_info_gdb_mi_command): Change call
	from mi_lookup to mi_cmd_lookup.
---
 gdb/mi/mi-cmd-info.c |   2 +-
 gdb/mi/mi-cmds.c     | 449 ++++++++++++++++++++++++---------------------------
 gdb/mi/mi-cmds.h     |   4 +-
 gdb/mi/mi-parse.c    |   2 +-
 4 files changed, 216 insertions(+), 241 deletions(-)

diff --git a/gdb/mi/mi-cmd-info.c b/gdb/mi/mi-cmd-info.c
index e8d2c60..12e48bf 100644
--- a/gdb/mi/mi-cmd-info.c
+++ b/gdb/mi/mi-cmd-info.c
@@ -93,7 +93,7 @@ mi_cmd_info_gdb_mi_command (char *command, char **argv, int argc)
   if (cmd_name[0] == '-')
     cmd_name++;
 
-  cmd = mi_lookup (cmd_name);
+  cmd = mi_cmd_lookup (cmd_name);
 
   old_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "command");
   uiout->field_string ("exists", cmd != NULL ? "true" : "false");
diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c
index abb70bd..eb1e446 100644
--- a/gdb/mi/mi-cmds.c
+++ b/gdb/mi/mi-cmds.c
@@ -22,263 +22,236 @@
 #include "top.h"
 #include "mi-cmds.h"
 #include "mi-main.h"
+#include <map>
+#include <string>
+#include <memory>
 
-extern void _initialize_mi_cmds (void);
+/* MI command table (built at run time). */
 
-struct mi_cmd;
-static struct mi_cmd **lookup_table (const char *command);
-static void build_table (struct mi_cmd *commands);
+static std::map<std::string, mi_cmd_up> mi_cmd_table;
 
-static struct mi_cmd mi_cmds[] =
+/* Insert a new mi-command into the command table.  Return true if
+   insertion was successful.  */
+
+static bool
+insert_mi_cmd_entry (mi_cmd_up command)
 {
-/* Define a MI command of NAME, and its corresponding CLI command is
-   CLI_NAME.  */
-#define DEF_MI_CMD_CLI_1(NAME, CLI_NAME, ARGS_P, CALLED)	\
-  { NAME, { CLI_NAME, ARGS_P}, NULL, CALLED }
-#define DEF_MI_CMD_CLI(NAME, CLI_NAME, ARGS_P) \
-  DEF_MI_CMD_CLI_1(NAME, CLI_NAME, ARGS_P, NULL)
-
-/* Define a MI command of NAME, and implemented by function MI_FUNC.  */
-#define DEF_MI_CMD_MI_1(NAME, MI_FUNC, CALLED) \
-  { NAME, {NULL, 0}, MI_FUNC, CALLED }
-#define DEF_MI_CMD_MI(NAME, MI_FUNC) DEF_MI_CMD_MI_1(NAME, MI_FUNC, NULL)
-
-  DEF_MI_CMD_MI ("ada-task-info", mi_cmd_ada_task_info),
-  DEF_MI_CMD_MI ("add-inferior", mi_cmd_add_inferior),
-  DEF_MI_CMD_CLI_1 ("break-after", "ignore", 1,
-		    &mi_suppress_notification.breakpoint),
-  DEF_MI_CMD_CLI_1 ("break-condition","cond", 1,
-		  &mi_suppress_notification.breakpoint),
-  DEF_MI_CMD_MI_1 ("break-commands", mi_cmd_break_commands,
-		   &mi_suppress_notification.breakpoint),
-  DEF_MI_CMD_CLI_1 ("break-delete", "delete breakpoint", 1,
-		    &mi_suppress_notification.breakpoint),
-  DEF_MI_CMD_CLI_1 ("break-disable", "disable breakpoint", 1,
-		    &mi_suppress_notification.breakpoint),
-  DEF_MI_CMD_CLI_1 ("break-enable", "enable breakpoint", 1,
-		     &mi_suppress_notification.breakpoint),
-  DEF_MI_CMD_CLI ("break-info", "info break", 1),
-  DEF_MI_CMD_MI_1 ("break-insert", mi_cmd_break_insert,
-		   &mi_suppress_notification.breakpoint),
-  DEF_MI_CMD_MI_1 ("dprintf-insert", mi_cmd_dprintf_insert,
-		   &mi_suppress_notification.breakpoint),
-  DEF_MI_CMD_CLI ("break-list", "info break", 0),
-  DEF_MI_CMD_MI_1 ("break-passcount", mi_cmd_break_passcount,
-		   &mi_suppress_notification.breakpoint),
-  DEF_MI_CMD_MI_1 ("break-watch", mi_cmd_break_watch,
-		   &mi_suppress_notification.breakpoint),
-  DEF_MI_CMD_MI_1 ("catch-assert", mi_cmd_catch_assert,
-                   &mi_suppress_notification.breakpoint),
-  DEF_MI_CMD_MI_1 ("catch-exception", mi_cmd_catch_exception,
-                   &mi_suppress_notification.breakpoint),
-  DEF_MI_CMD_MI_1 ("catch-load", mi_cmd_catch_load,
-                   &mi_suppress_notification.breakpoint),
-  DEF_MI_CMD_MI_1 ("catch-unload", mi_cmd_catch_unload,
-                   &mi_suppress_notification.breakpoint),
-  DEF_MI_CMD_MI ("data-disassemble", mi_cmd_disassemble),
-  DEF_MI_CMD_MI ("data-evaluate-expression", mi_cmd_data_evaluate_expression),
-  DEF_MI_CMD_MI ("data-list-changed-registers",
-		 mi_cmd_data_list_changed_registers),
-  DEF_MI_CMD_MI ("data-list-register-names", mi_cmd_data_list_register_names),
-  DEF_MI_CMD_MI ("data-list-register-values", mi_cmd_data_list_register_values),
-  DEF_MI_CMD_MI ("data-read-memory", mi_cmd_data_read_memory),
-  DEF_MI_CMD_MI ("data-read-memory-bytes", mi_cmd_data_read_memory_bytes),
-  DEF_MI_CMD_MI_1 ("data-write-memory", mi_cmd_data_write_memory,
-		   &mi_suppress_notification.memory),
-  DEF_MI_CMD_MI_1 ("data-write-memory-bytes", mi_cmd_data_write_memory_bytes,
-		   &mi_suppress_notification.memory),
-  DEF_MI_CMD_MI ("data-write-register-values",
-		 mi_cmd_data_write_register_values),
-  DEF_MI_CMD_MI ("enable-timings", mi_cmd_enable_timings),
-  DEF_MI_CMD_MI ("enable-pretty-printing", mi_cmd_enable_pretty_printing),
-  DEF_MI_CMD_MI ("enable-frame-filters", mi_cmd_enable_frame_filters),
-  DEF_MI_CMD_MI ("environment-cd", mi_cmd_env_cd),
-  DEF_MI_CMD_MI ("environment-directory", mi_cmd_env_dir),
-  DEF_MI_CMD_MI ("environment-path", mi_cmd_env_path),
-  DEF_MI_CMD_MI ("environment-pwd", mi_cmd_env_pwd),
-  DEF_MI_CMD_CLI_1 ("exec-arguments", "set args", 1,
-		    &mi_suppress_notification.cmd_param_changed),
-  DEF_MI_CMD_MI ("exec-continue", mi_cmd_exec_continue),
-  DEF_MI_CMD_MI ("exec-finish", mi_cmd_exec_finish),
-  DEF_MI_CMD_MI ("exec-jump", mi_cmd_exec_jump),
-  DEF_MI_CMD_MI ("exec-interrupt", mi_cmd_exec_interrupt),
-  DEF_MI_CMD_MI ("exec-next", mi_cmd_exec_next),
-  DEF_MI_CMD_MI ("exec-next-instruction", mi_cmd_exec_next_instruction),
-  DEF_MI_CMD_MI ("exec-return", mi_cmd_exec_return),
-  DEF_MI_CMD_MI ("exec-run", mi_cmd_exec_run),
-  DEF_MI_CMD_MI ("exec-step", mi_cmd_exec_step),
-  DEF_MI_CMD_MI ("exec-step-instruction", mi_cmd_exec_step_instruction),
-  DEF_MI_CMD_CLI ("exec-until", "until", 1),
-  DEF_MI_CMD_CLI ("file-exec-and-symbols", "file", 1),
-  DEF_MI_CMD_CLI ("file-exec-file", "exec-file", 1),
-  DEF_MI_CMD_MI ("file-list-exec-source-file",
-		 mi_cmd_file_list_exec_source_file),
-  DEF_MI_CMD_MI ("file-list-exec-source-files",
-		 mi_cmd_file_list_exec_source_files),
-  DEF_MI_CMD_CLI ("file-symbol-file", "symbol-file", 1),
-  DEF_MI_CMD_MI ("gdb-exit", mi_cmd_gdb_exit),
-  DEF_MI_CMD_CLI_1 ("gdb-set", "set", 1,
-		    &mi_suppress_notification.cmd_param_changed),
-  DEF_MI_CMD_CLI ("gdb-show", "show", 1),
-  DEF_MI_CMD_CLI ("gdb-version", "show version", 0),
-  DEF_MI_CMD_MI ("inferior-tty-set", mi_cmd_inferior_tty_set),
-  DEF_MI_CMD_MI ("inferior-tty-show", mi_cmd_inferior_tty_show),
-  DEF_MI_CMD_MI ("info-ada-exceptions", mi_cmd_info_ada_exceptions),
-  DEF_MI_CMD_MI ("info-gdb-mi-command", mi_cmd_info_gdb_mi_command),
-  DEF_MI_CMD_MI ("info-os", mi_cmd_info_os),
-  DEF_MI_CMD_MI ("interpreter-exec", mi_cmd_interpreter_exec),
-  DEF_MI_CMD_MI ("list-features", mi_cmd_list_features),
-  DEF_MI_CMD_MI ("list-target-features", mi_cmd_list_target_features),
-  DEF_MI_CMD_MI ("list-thread-groups", mi_cmd_list_thread_groups),
-  DEF_MI_CMD_MI ("remove-inferior", mi_cmd_remove_inferior),
-  DEF_MI_CMD_MI ("stack-info-depth", mi_cmd_stack_info_depth),
-  DEF_MI_CMD_MI ("stack-info-frame", mi_cmd_stack_info_frame),
-  DEF_MI_CMD_MI ("stack-list-arguments", mi_cmd_stack_list_args),
-  DEF_MI_CMD_MI ("stack-list-frames", mi_cmd_stack_list_frames),
-  DEF_MI_CMD_MI ("stack-list-locals", mi_cmd_stack_list_locals),
-  DEF_MI_CMD_MI ("stack-list-variables", mi_cmd_stack_list_variables),
-  DEF_MI_CMD_MI_1 ("stack-select-frame", mi_cmd_stack_select_frame,
-		   &mi_suppress_notification.user_selected_context),
-  DEF_MI_CMD_MI ("symbol-list-lines", mi_cmd_symbol_list_lines),
-  DEF_MI_CMD_CLI ("target-attach", "attach", 1),
-  DEF_MI_CMD_MI ("target-detach", mi_cmd_target_detach),
-  DEF_MI_CMD_CLI ("target-disconnect", "disconnect", 0),
-  DEF_MI_CMD_CLI ("target-download", "load", 1),
-  DEF_MI_CMD_MI ("target-file-delete", mi_cmd_target_file_delete),
-  DEF_MI_CMD_MI ("target-file-get", mi_cmd_target_file_get),
-  DEF_MI_CMD_MI ("target-file-put", mi_cmd_target_file_put),
-  DEF_MI_CMD_MI ("target-flash-erase", mi_cmd_target_flash_erase),
-  DEF_MI_CMD_CLI ("target-select", "target", 1),
-  DEF_MI_CMD_MI ("thread-info", mi_cmd_thread_info),
-  DEF_MI_CMD_MI ("thread-list-ids", mi_cmd_thread_list_ids),
-  DEF_MI_CMD_MI_1 ("thread-select", mi_cmd_thread_select,
-		   &mi_suppress_notification.user_selected_context),
-  DEF_MI_CMD_MI ("trace-define-variable", mi_cmd_trace_define_variable),
-  DEF_MI_CMD_MI_1 ("trace-find", mi_cmd_trace_find,
-		   &mi_suppress_notification.traceframe),
-  DEF_MI_CMD_MI ("trace-frame-collected",
-		 mi_cmd_trace_frame_collected),
-  DEF_MI_CMD_MI ("trace-list-variables", mi_cmd_trace_list_variables),
-  DEF_MI_CMD_MI ("trace-save", mi_cmd_trace_save),
-  DEF_MI_CMD_MI ("trace-start", mi_cmd_trace_start),
-  DEF_MI_CMD_MI ("trace-status", mi_cmd_trace_status),
-  DEF_MI_CMD_MI ("trace-stop", mi_cmd_trace_stop),
-  DEF_MI_CMD_MI ("var-assign", mi_cmd_var_assign),
-  DEF_MI_CMD_MI ("var-create", mi_cmd_var_create),
-  DEF_MI_CMD_MI ("var-delete", mi_cmd_var_delete),
-  DEF_MI_CMD_MI ("var-evaluate-expression", mi_cmd_var_evaluate_expression),
-  DEF_MI_CMD_MI ("var-info-path-expression", mi_cmd_var_info_path_expression),
-  DEF_MI_CMD_MI ("var-info-expression", mi_cmd_var_info_expression),
-  DEF_MI_CMD_MI ("var-info-num-children", mi_cmd_var_info_num_children),
-  DEF_MI_CMD_MI ("var-info-type", mi_cmd_var_info_type),
-  DEF_MI_CMD_MI ("var-list-children", mi_cmd_var_list_children),
-  DEF_MI_CMD_MI ("var-set-format", mi_cmd_var_set_format),
-  DEF_MI_CMD_MI ("var-set-frozen", mi_cmd_var_set_frozen),
-  DEF_MI_CMD_MI ("var-set-update-range", mi_cmd_var_set_update_range),
-  DEF_MI_CMD_MI ("var-set-visualizer", mi_cmd_var_set_visualizer),
-  DEF_MI_CMD_MI ("var-show-attributes", mi_cmd_var_show_attributes),
-  DEF_MI_CMD_MI ("var-show-format", mi_cmd_var_show_format),
-  DEF_MI_CMD_MI ("var-update", mi_cmd_var_update),
-  { NULL, }
-};
-
-/* Pointer to the mi command table (built at run time). */
-
-static struct mi_cmd **mi_table;
-
-/* A prime large enough to accomodate the entire command table.  */
-enum
-  {
-    MI_TABLE_SIZE = 227
-  };
-
-/* Exported function used to obtain info from the table.  */
-struct mi_cmd *
-mi_lookup (const char *command)
+  gdb_assert (command != NULL);
+  gdb_assert (command->name != NULL);
+
+  std::string name (command->name);
+
+  if (mi_cmd_table.find (name) != mi_cmd_table.end ())
+    return false;
+
+  mi_cmd_table[name] = std::move (command);
+
+  return true;
+}
+
+/* Create an mi_cmd structure with name NAME.  */
+
+static mi_cmd_up
+create_mi_cmd (const char *name)
 {
-  return *lookup_table (command);
+  mi_cmd_up cmd (new mi_cmd ());
+
+  cmd->name = name;
+
+  return cmd;
 }
 
-/* Used for collecting hash hit/miss statistics.  */
+/* Create and register a new MI command with a pure MI implementation.  */
 
-struct mi_cmd_stats
+static void
+add_mi_cmd_mi (const char *name, mi_cmd_argv_ftype function,
+	       int *suppress_notification = NULL)
 {
-  int hit;
-  int miss;
-  int rehash;
-};
-struct mi_cmd_stats stats;
+  mi_cmd_up cmd_up = create_mi_cmd (name);
+
+  cmd_up->cli.cmd = NULL;
+  cmd_up->cli.args_p = 0;
+  cmd_up->argv_func = function;
+  cmd_up->suppress_notification = suppress_notification;
 
-/* Look up a command.  */
+  bool success = insert_mi_cmd_entry (std::move (cmd_up));
+  gdb_assert (success);
+}
+
+/* Create and register a new MI command implemented on top of a CLI command.  */
 
-static struct mi_cmd **
-lookup_table (const char *command)
+static void
+add_mi_cmd_cli (const char *name, const char *cli_name, int args_p,
+		int *suppress_notification = NULL)
 {
-  const char *chp;
-  unsigned int index = 0;
-
-  /* Compute our hash.  */
-  for (chp = command; *chp; chp++)
-    {
-      /* We use a somewhat arbitrary formula.  */
-      index = ((index << 6) + (unsigned int) *chp) % MI_TABLE_SIZE;
-    }
-
-  while (1)
-    {
-      struct mi_cmd **entry = &mi_table[index];
-      if ((*entry) == 0)
-	{
-	  /* not found, return pointer to next free. */
-	  stats.miss++;
-	  return entry;
-	}
-      if (strcmp (command, (*entry)->name) == 0)
-	{
-	  stats.hit++;
-	  return entry;		/* found */
-	}
-      index = (index + 1) % MI_TABLE_SIZE;
-      stats.rehash++;
-    }
+  mi_cmd_up cmd_up = create_mi_cmd (name);
+
+  cmd_up->cli.args_p = args_p;
+  cmd_up->suppress_notification = NULL;
+  cmd_up->cli.cmd = cli_name;
+
+  bool success = insert_mi_cmd_entry (std::move (cmd_up));
+  gdb_assert (success);
 }
 
 static void
-build_table (struct mi_cmd *commands)
+build_table ()
 {
-  int nr_rehash = 0;
-  int nr_entries = 0;
-  struct mi_cmd *command;
-
-  mi_table = XCNEWVEC (struct mi_cmd *, MI_TABLE_SIZE);
-  for (command = commands; command->name != 0; command++)
-    {
-      struct mi_cmd **entry = lookup_table (command->name);
-
-      if (*entry)
-	internal_error (__FILE__, __LINE__,
-			_("command `%s' appears to be duplicated"),
-			command->name);
-      *entry = command;
-      /* FIXME lose these prints */
-      if (0)
-	{
-	  fprintf_unfiltered (gdb_stdlog, "%-30s %2d\n",
-			      command->name, stats.rehash - nr_rehash);
-	}
-      nr_entries++;
-      nr_rehash = stats.rehash;
-    }
-  if (0)
-    {
-      fprintf_filtered (gdb_stdlog, "Average %3.1f\n",
-			(double) nr_rehash / (double) nr_entries);
-    }
+  add_mi_cmd_mi ("ada-task-info", mi_cmd_ada_task_info);
+  add_mi_cmd_mi ("add-inferior", mi_cmd_add_inferior);
+  add_mi_cmd_cli ("break-after", "ignore", 1,
+		  &mi_suppress_notification.breakpoint);
+  add_mi_cmd_cli ("break-condition","cond", 1,
+		  &mi_suppress_notification.breakpoint);
+  add_mi_cmd_mi ("break-commands", mi_cmd_break_commands,
+		 &mi_suppress_notification.breakpoint);
+  add_mi_cmd_cli ("break-delete", "delete breakpoint", 1,
+		  &mi_suppress_notification.breakpoint);
+  add_mi_cmd_cli ("break-disable", "disable breakpoint", 1,
+		  &mi_suppress_notification.breakpoint);
+  add_mi_cmd_cli ("break-enable", "enable breakpoint", 1,
+		  &mi_suppress_notification.breakpoint);
+  add_mi_cmd_cli ("break-info", "info break", 1);
+  add_mi_cmd_mi ("break-insert", mi_cmd_break_insert,
+		 &mi_suppress_notification.breakpoint);
+  add_mi_cmd_mi ("dprintf-insert", mi_cmd_dprintf_insert,
+		 &mi_suppress_notification.breakpoint);
+  add_mi_cmd_cli ("break-list", "info break", 0);
+  add_mi_cmd_mi ("break-passcount", mi_cmd_break_passcount,
+		 &mi_suppress_notification.breakpoint);
+  add_mi_cmd_mi ("break-watch", mi_cmd_break_watch,
+		 &mi_suppress_notification.breakpoint);
+  add_mi_cmd_mi ("catch-assert", mi_cmd_catch_assert,
+		 &mi_suppress_notification.breakpoint);
+  add_mi_cmd_mi ("catch-exception", mi_cmd_catch_exception,
+		 &mi_suppress_notification.breakpoint);
+  add_mi_cmd_mi ("catch-load", mi_cmd_catch_load,
+		 &mi_suppress_notification.breakpoint);
+  add_mi_cmd_mi ("catch-unload", mi_cmd_catch_unload,
+		 &mi_suppress_notification.breakpoint);
+  add_mi_cmd_mi ("data-disassemble", mi_cmd_disassemble);
+  add_mi_cmd_mi ("data-evaluate-expression", mi_cmd_data_evaluate_expression);
+  add_mi_cmd_mi ("data-list-changed-registers",
+		 mi_cmd_data_list_changed_registers);
+  add_mi_cmd_mi ("data-list-register-names", mi_cmd_data_list_register_names);
+  add_mi_cmd_mi ("data-list-register-values",
+		 mi_cmd_data_list_register_values);
+  add_mi_cmd_mi ("data-read-memory", mi_cmd_data_read_memory);
+  add_mi_cmd_mi ("data-read-memory-bytes", mi_cmd_data_read_memory_bytes);
+  add_mi_cmd_mi ("data-write-memory", mi_cmd_data_write_memory,
+		 &mi_suppress_notification.memory);
+  add_mi_cmd_mi ("data-write-memory-bytes", mi_cmd_data_write_memory_bytes,
+		 &mi_suppress_notification.memory);
+  add_mi_cmd_mi ("data-write-register-values",
+		 mi_cmd_data_write_register_values);
+  add_mi_cmd_mi ("enable-timings", mi_cmd_enable_timings);
+  add_mi_cmd_mi ("enable-pretty-printing", mi_cmd_enable_pretty_printing);
+  add_mi_cmd_mi ("enable-frame-filters", mi_cmd_enable_frame_filters);
+  add_mi_cmd_mi ("environment-cd", mi_cmd_env_cd);
+  add_mi_cmd_mi ("environment-directory", mi_cmd_env_dir);
+  add_mi_cmd_mi ("environment-path", mi_cmd_env_path);
+  add_mi_cmd_mi ("environment-pwd", mi_cmd_env_pwd);
+  add_mi_cmd_cli ("exec-arguments", "set args", 1,
+		  &mi_suppress_notification.cmd_param_changed);
+  add_mi_cmd_mi ("exec-continue", mi_cmd_exec_continue);
+  add_mi_cmd_mi ("exec-finish", mi_cmd_exec_finish);
+  add_mi_cmd_mi ("exec-jump", mi_cmd_exec_jump);
+  add_mi_cmd_mi ("exec-interrupt", mi_cmd_exec_interrupt);
+  add_mi_cmd_mi ("exec-next", mi_cmd_exec_next);
+  add_mi_cmd_mi ("exec-next-instruction", mi_cmd_exec_next_instruction);
+  add_mi_cmd_mi ("exec-return", mi_cmd_exec_return);
+  add_mi_cmd_mi ("exec-run", mi_cmd_exec_run);
+  add_mi_cmd_mi ("exec-step", mi_cmd_exec_step);
+  add_mi_cmd_mi ("exec-step-instruction", mi_cmd_exec_step_instruction);
+  add_mi_cmd_cli ("exec-until", "until", 1);
+  add_mi_cmd_cli ("file-exec-and-symbols", "file", 1);
+  add_mi_cmd_cli ("file-exec-file", "exec-file", 1);
+  add_mi_cmd_mi ("file-list-exec-source-file",
+		 mi_cmd_file_list_exec_source_file);
+  add_mi_cmd_mi ("file-list-exec-source-files",
+		 mi_cmd_file_list_exec_source_files);
+  add_mi_cmd_cli ("file-symbol-file", "symbol-file", 1);
+  add_mi_cmd_mi ("gdb-exit", mi_cmd_gdb_exit);
+  add_mi_cmd_cli ("gdb-set", "set", 1,
+		  &mi_suppress_notification.cmd_param_changed);
+  add_mi_cmd_cli ("gdb-show", "show", 1);
+  add_mi_cmd_cli ("gdb-version", "show version", 0);
+  add_mi_cmd_mi ("inferior-tty-set", mi_cmd_inferior_tty_set);
+  add_mi_cmd_mi ("inferior-tty-show", mi_cmd_inferior_tty_show);
+  add_mi_cmd_mi ("info-ada-exceptions", mi_cmd_info_ada_exceptions);
+  add_mi_cmd_mi ("info-gdb-mi-command", mi_cmd_info_gdb_mi_command);
+  add_mi_cmd_mi ("info-os", mi_cmd_info_os);
+  add_mi_cmd_mi ("interpreter-exec", mi_cmd_interpreter_exec);
+  add_mi_cmd_mi ("list-features", mi_cmd_list_features);
+  add_mi_cmd_mi ("list-target-features", mi_cmd_list_target_features);
+  add_mi_cmd_mi ("list-thread-groups", mi_cmd_list_thread_groups);
+  add_mi_cmd_mi ("remove-inferior", mi_cmd_remove_inferior);
+  add_mi_cmd_mi ("stack-info-depth", mi_cmd_stack_info_depth);
+  add_mi_cmd_mi ("stack-info-frame", mi_cmd_stack_info_frame);
+  add_mi_cmd_mi ("stack-list-arguments", mi_cmd_stack_list_args);
+  add_mi_cmd_mi ("stack-list-frames", mi_cmd_stack_list_frames);
+  add_mi_cmd_mi ("stack-list-locals", mi_cmd_stack_list_locals);
+  add_mi_cmd_mi ("stack-list-variables", mi_cmd_stack_list_variables);
+  add_mi_cmd_mi ("stack-select-frame", mi_cmd_stack_select_frame,
+		 &mi_suppress_notification.user_selected_context);
+  add_mi_cmd_mi ("symbol-list-lines", mi_cmd_symbol_list_lines);
+  add_mi_cmd_cli ("target-attach", "attach", 1);
+  add_mi_cmd_mi ("target-detach", mi_cmd_target_detach);
+  add_mi_cmd_cli ("target-disconnect", "disconnect", 0);
+  add_mi_cmd_cli ("target-download", "load", 1);
+  add_mi_cmd_mi ("target-file-delete", mi_cmd_target_file_delete);
+  add_mi_cmd_mi ("target-file-get", mi_cmd_target_file_get);
+  add_mi_cmd_mi ("target-file-put", mi_cmd_target_file_put);
+  add_mi_cmd_mi ("target-flash-erase", mi_cmd_target_flash_erase);
+  add_mi_cmd_cli ("target-select", "target", 1);
+  add_mi_cmd_mi ("thread-info", mi_cmd_thread_info);
+  add_mi_cmd_mi ("thread-list-ids", mi_cmd_thread_list_ids);
+  add_mi_cmd_mi ("thread-select", mi_cmd_thread_select,
+		 &mi_suppress_notification.user_selected_context);
+  add_mi_cmd_mi ("trace-define-variable", mi_cmd_trace_define_variable);
+  add_mi_cmd_mi ("trace-find", mi_cmd_trace_find,
+		 &mi_suppress_notification.traceframe);
+  add_mi_cmd_mi ("trace-frame-collected", mi_cmd_trace_frame_collected);
+  add_mi_cmd_mi ("trace-list-variables", mi_cmd_trace_list_variables);
+  add_mi_cmd_mi ("trace-save", mi_cmd_trace_save);
+  add_mi_cmd_mi ("trace-start", mi_cmd_trace_start);
+  add_mi_cmd_mi ("trace-status", mi_cmd_trace_status);
+  add_mi_cmd_mi ("trace-stop", mi_cmd_trace_stop);
+  add_mi_cmd_mi ("var-assign", mi_cmd_var_assign);
+  add_mi_cmd_mi ("var-create", mi_cmd_var_create);
+  add_mi_cmd_mi ("var-delete", mi_cmd_var_delete);
+  add_mi_cmd_mi ("var-evaluate-expression", mi_cmd_var_evaluate_expression);
+  add_mi_cmd_mi ("var-info-path-expression", mi_cmd_var_info_path_expression);
+  add_mi_cmd_mi ("var-info-expression", mi_cmd_var_info_expression);
+  add_mi_cmd_mi ("var-info-num-children", mi_cmd_var_info_num_children);
+  add_mi_cmd_mi ("var-info-type", mi_cmd_var_info_type);
+  add_mi_cmd_mi ("var-list-children", mi_cmd_var_list_children);
+  add_mi_cmd_mi ("var-set-format", mi_cmd_var_set_format);
+  add_mi_cmd_mi ("var-set-frozen", mi_cmd_var_set_frozen);
+  add_mi_cmd_mi ("var-set-update-range", mi_cmd_var_set_update_range);
+  add_mi_cmd_mi ("var-set-visualizer", mi_cmd_var_set_visualizer);
+  add_mi_cmd_mi ("var-show-attributes", mi_cmd_var_show_attributes);
+  add_mi_cmd_mi ("var-show-format", mi_cmd_var_show_format);
+  add_mi_cmd_mi ("var-update", mi_cmd_var_update);
+}
+
+/* See mi-cmds.h.  */
+
+struct mi_cmd *
+mi_cmd_lookup (const char *command)
+{
+  gdb_assert (command != NULL);
+
+  auto it = mi_cmd_table.find (command);
+
+  if (it == mi_cmd_table.end ())
+    return NULL;
+
+  return it->second.get ();
 }
 
 void
 _initialize_mi_cmds (void)
 {
-  build_table (mi_cmds);
-  memset (&stats, 0, sizeof (stats));
+  build_table ();
 }
diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h
index d0906e6..75eadc5 100644
--- a/gdb/mi/mi-cmds.h
+++ b/gdb/mi/mi-cmds.h
@@ -151,9 +151,11 @@ struct mi_cmd
   int *suppress_notification;
 };
 
+typedef std::unique_ptr<struct mi_cmd> mi_cmd_up;
+
 /* Lookup a command in the MI command table.  */
 
-extern struct mi_cmd *mi_lookup (const char *command);
+extern struct mi_cmd *mi_cmd_lookup (const char *command);
 
 /* Debug flag */
 extern int mi_debug_p;
diff --git a/gdb/mi/mi-parse.c b/gdb/mi/mi-parse.c
index 19cbb14..0df0c31 100644
--- a/gdb/mi/mi-parse.c
+++ b/gdb/mi/mi-parse.c
@@ -282,7 +282,7 @@ mi_parse (const char *cmd, char **token)
   }
 
   /* Find the command in the MI table.  */
-  parse->cmd = mi_lookup (parse->command);
+  parse->cmd = mi_cmd_lookup (parse->command);
   if (parse->cmd == NULL)
     throw_error (UNDEFINED_COMMAND_ERROR,
 		 _("Undefined MI command: %s"), parse->command);
-- 
1.9.1

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 0/2] Use std::hashmap and MI commands classes in mi-cmds.c
@ 2017-02-03  5:46 didier.nadeau
  2017-02-03  5:46 ` [PATCH 2/2] Use classes to represent MI Command instead of structures didier.nadeau
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: didier.nadeau @ 2017-02-03  5:46 UTC (permalink / raw)
  To: gdb-patches; +Cc: didier.nadeau

From: Didier Nadeau <didier.nadeau@gmail.com>

This is a serie of two patches in preparation to a next patch that will allows
users to define custom MI commands using Python, similarly to what is currently
possible for Python CLI commands. 

The first patch modify mi-cmds.c to use an std::hashmap to store MI commands 
instead of the custom structure. It allows to insert new MI commands at runtime
as it does not use a fixed size array anymore.

The second patch removes structures mi_cli and mi_cmd from mi-cmds.c and replace
them with a hierarchy of classes. This way, each subtype of MI command inherits
from the base virtual class and register itself into the hashmap. Classes 
mi_command_mi for pure MI commands and mi_command_cli for MI commands over CLI
commands have been implemented. MI commands are now all called from a common
invoke virtual function. Logic for suppress_notification and ARGV/ARGC parsing 
has been moved to the classes implementation.

Didier Nadeau (2):
  Use std::map for MI commands in mi-cmds.c
  Use classes to represent MI Command instead of structures

 gdb/mi/mi-cmd-info.c |   4 +-
 gdb/mi/mi-cmds.c     | 490 ++++++++++++++++++++++++++-------------------------
 gdb/mi/mi-cmds.h     |  70 +++++---
 gdb/mi/mi-main.c     |  21 +--
 gdb/mi/mi-main.h     |   2 +
 gdb/mi/mi-parse.c    |  20 +--
 gdb/mi/mi-parse.h    |   6 +-
 7 files changed, 316 insertions(+), 297 deletions(-)

-- 
1.9.1

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/2] Use std::hashmap and MI commands classes in mi-cmds.c
  2017-02-03  5:46 [PATCH 0/2] Use std::hashmap and MI commands classes in mi-cmds.c didier.nadeau
  2017-02-03  5:46 ` [PATCH 2/2] Use classes to represent MI Command instead of structures didier.nadeau
  2017-02-03  5:46 ` [PATCH 1/2] Use std::map for MI commands in mi-cmds.c didier.nadeau
@ 2017-02-06 15:58 ` Pedro Alves
       [not found]   ` <CAK0EQJEOg0PA2xghH+89JvQr7ikf=nUBYJ9LvUvRY1RTkWGB_A@mail.gmail.com>
  2 siblings, 1 reply; 10+ messages in thread
From: Pedro Alves @ 2017-02-06 15:58 UTC (permalink / raw)
  To: didier.nadeau, gdb-patches

Hi Didier,

On 02/03/2017 05:46 AM, didier.nadeau@gmail.com wrote:
> This is a serie of two patches in preparation to a next patch that will allows
> users to define custom MI commands using Python, similarly to what is currently
> possible for Python CLI commands. 

Do you have that patch available already?  It may be that seeing it
helps understand these precursor patches better.

Before we can consider the patches, we'll need to sort out copyright
assignment.  Do you have an assignment with the FSF in place?  If not,
let me know and I can help get that process started.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/2] Use std::hashmap and MI commands classes in mi-cmds.c
       [not found]   ` <CAK0EQJEOg0PA2xghH+89JvQr7ikf=nUBYJ9LvUvRY1RTkWGB_A@mail.gmail.com>
@ 2017-02-06 18:23     ` Pedro Alves
  2017-02-10 18:19       ` Didier Nadeau
  0 siblings, 1 reply; 10+ messages in thread
From: Pedro Alves @ 2017-02-06 18:23 UTC (permalink / raw)
  To: Didier Nadeau; +Cc: gdb-patches

On 02/06/2017 05:53 PM, Didier Nadeau wrote:

> I do not have an assignment with the FSF yet. 

I sent the forms offlist.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/2] Use std::hashmap and MI commands classes in mi-cmds.c
  2017-02-06 18:23     ` Pedro Alves
@ 2017-02-10 18:19       ` Didier Nadeau
  2017-02-10 20:41         ` [PATCH] Create MI commands using python Didier Nadeau
  2017-02-11  5:01         ` [PATCH 0/2] Use std::hashmap and MI commands classes in mi-cmds.c Didier Nadeau
  0 siblings, 2 replies; 10+ messages in thread
From: Didier Nadeau @ 2017-02-10 18:19 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

Hi,

I have signed the assignment with the FSF. I am working on the third
patch for MI commands in Python.

Thanks,
Didier Nadeau

2017-02-06 13:23 GMT-05:00 Pedro Alves <palves@redhat.com>:
> On 02/06/2017 05:53 PM, Didier Nadeau wrote:
>
>> I do not have an assignment with the FSF yet.
>
> I sent the forms offlist.
>
> Thanks,
> Pedro Alves
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH] Create MI commands using python.
  2017-02-10 18:19       ` Didier Nadeau
@ 2017-02-10 20:41         ` Didier Nadeau
  2017-03-17 15:38           ` Pedro Alves
  2017-02-11  5:01         ` [PATCH 0/2] Use std::hashmap and MI commands classes in mi-cmds.c Didier Nadeau
  1 sibling, 1 reply; 10+ messages in thread
From: Didier Nadeau @ 2017-02-10 20:41 UTC (permalink / raw)
  To: palves; +Cc: gdb-patches, Didier Nadeau

This commit allows an user to create custom MI commands using Python
similarly to what is possible for Python CLI commands.

A new subclass of mi_command is defined for Python MI commands,
mi_command_py. A new file, py-micmd.c contains the logic for Python
MI commands.

gdb/ChangeLog
2017-02-10  Didier Nadeau  <didier.nadeau@gmail.com>

    * Makefile.in (SUBDIR_PYTHON_OBS): Add py-micmd.o.
    (SUBDIR_PYTHON_SRCS): Add py-micmd.c.
    * mi/mi-cmds.c (insert_mi_cmd_entry): Remove static.
    (mi_command_py::mi_command_py): New function.
    (mi_command_py::invoke): New function.
    * mi/mi-cmds.h (mi_command_py): New class.
    (insert_mi_cmd_entry): New declaration.
    * python/py-micmd.c: New file
    (micmdpy_object): New struct.
    (micmdpy_object): New typedef.
    (parse_mi_result): New function.
    (py_mi_invoke): New function.
    (micmdpy_parse_command_name): New function.
    (micmdpy_init): New function.
    (gdbpy_initialize_micommands): New function.
    * python/py-micmd.h: New file
    (py_mi_invoke): New function.
    * python/python-internal.h
    (gdbpy_initialize_micommands): New declaration.
    * python/python.c
    (_initialize_python): New call to gdbpy_initialize_micommands.
---
 gdb/Makefile.in              |   2 +
 gdb/mi/mi-cmds.c             |  27 +++-
 gdb/mi/mi-cmds.h             |  19 +++
 gdb/python/py-micmd.c        | 293 +++++++++++++++++++++++++++++++++++++++++++
 gdb/python/py-micmd.h        |   6 +
 gdb/python/python-internal.h |   2 +
 gdb/python/python.c          |   3 +-
 7 files changed, 348 insertions(+), 4 deletions(-)
 create mode 100644 gdb/python/py-micmd.c
 create mode 100644 gdb/python/py-micmd.h

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 3ce7d69..ae1f766 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -455,6 +455,7 @@ SUBDIR_PYTHON_OBS = \
 	py-infthread.o \
 	py-lazy-string.o \
 	py-linetable.o \
+	py-micmd.o \
 	py-newobjfileevent.o \
 	py-objfile.o \
 	py-param.o \
@@ -495,6 +496,7 @@ SUBDIR_PYTHON_SRCS = \
 	python/py-infthread.c \
 	python/py-lazy-string.c \
 	python/py-linetable.c \
+	python/py-micmd.c \
 	python/py-newobjfileevent.c \
 	python/py-objfile.c \
 	python/py-param.c \
diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c
index 160b864..2b4fef5 100644
--- a/gdb/mi/mi-cmds.c
+++ b/gdb/mi/mi-cmds.c
@@ -23,6 +23,7 @@
 #include "mi-cmds.h"
 #include "mi-main.h"
 #include "mi-parse.h"
+#include "python/py-micmd.h"
 #include <map>
 #include <string>
 #include <memory>
@@ -31,10 +32,9 @@
 
 static std::map<std::string, mi_cmd_up> mi_cmd_table;
 
-/* Insert a new mi-command into the command table.  Return true if
-   insertion was successful.  */
+/* See mi-cmds.h.  */
 
-static bool
+bool
 insert_mi_cmd_entry (mi_cmd_up command)
 {
   gdb_assert (command != NULL);
@@ -132,6 +132,27 @@ mi_command_cli::invoke (struct mi_parse *parse)
 			  parse->args);
 }
 
+mi_command_py::mi_command_py (const char *name, int *suppress_notification,
+			      void *object)
+  : mi_command (name, suppress_notification),
+    pyobj (object)
+{}
+
+void
+mi_command_py::invoke (struct mi_parse *parse)
+{
+  std::unique_ptr<scoped_restore_tmpl <int>> restore
+      = do_suppress_notification ();
+
+  mi_parse_argv (parse->args, parse);
+
+  if (parse->argv == NULL)
+      error (_("Problem parsing arguments: %s %s"), parse->command, parse->args);
+
+  py_mi_invoke (this->pyobj, parse->argv, parse->argc);
+
+}
+
 /* Initialize the available MI commands.  */
 
 static void
diff --git a/gdb/mi/mi-cmds.h b/gdb/mi/mi-cmds.h
index c5e596b..9d6ef8c 100644
--- a/gdb/mi/mi-cmds.h
+++ b/gdb/mi/mi-cmds.h
@@ -177,6 +177,20 @@ class mi_command_cli : public mi_command
     int m_args_p;
 };
 
+/* MI command implemented on top of a Python command.  */
+
+class mi_command_py : public mi_command
+{
+  public:
+    mi_command_py (const char *name, int *suppress_notification,
+		   void *object);
+    void invoke (struct mi_parse *parse) override;
+
+  private:
+    void *pyobj;
+
+};
+
 typedef std::unique_ptr<mi_command> mi_cmd_up;
 
 /* Lookup a command in the MI command table.  */
@@ -188,4 +202,9 @@ extern int mi_debug_p;
 
 extern void mi_execute_command (const char *cmd, int from_tty);
 
+/* Insert a new mi-command into the command table.  Return true if
+   insertion was successful.  */
+
+extern bool insert_mi_cmd_entry (mi_cmd_up command);
+
 #endif
diff --git a/gdb/python/py-micmd.c b/gdb/python/py-micmd.c
new file mode 100644
index 0000000..b5d2967
--- /dev/null
+++ b/gdb/python/py-micmd.c
@@ -0,0 +1,293 @@
+/* gdb MI commands implemented in Python  */
+
+#include <string.h>
+
+#include "defs.h"
+#include "arch-utils.h"
+#include "value.h"
+#include "python-internal.h"
+#include "charset.h"
+#include "gdbcmd.h"
+#include "cli/cli-decode.h"
+#include "completer.h"
+#include "language.h"
+#include "mi/mi-cmds.h"
+
+struct micmdpy_object
+{
+  PyObject_HEAD
+};
+
+typedef struct micmdpy_object micmdpy_object;
+
+static PyObject *invoke_cst;
+
+extern PyTypeObject micmdpy_object_type
+  CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("micmdpy_object");
+
+/* If the command invoked returns a list, this function parses it and create an
+   appropriate MI out output.
+
+   The returned values must be Python string, and can be contained within Python
+   lists and dictionaries. It is possible to have a multiple levels of lists
+   and/or dictionaries.  */
+
+static void
+parse_mi_result (PyObject *result, char *field_name)
+{
+  struct ui_out *uiout = current_uiout;
+
+  if(!field_name)
+    field_name = "default";
+
+  if (PyString_Check(result))
+    {
+      const char *string = gdbpy_obj_to_string (result).release ();
+      uiout->field_string (field_name, string);
+      xfree ( (void *)string);
+    }
+  else if (PyList_Check (result))
+    {
+      PyObject *item;
+      Py_ssize_t i = 0;
+      struct cleanup *cleanups = make_cleanup_ui_out_list_begin_end (uiout, field_name);
+      for(i = 0; i < PyList_GET_SIZE (result); ++i)
+	{
+	  struct cleanup *cleanup_item = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
+	  item = PyList_GetItem (result, i);
+	  parse_mi_result (item, NULL);
+	  do_cleanups (cleanup_item);
+	}
+      do_cleanups (cleanups);
+    }
+  else if ( PyDict_Check (result))
+    {
+      PyObject *key, *value;
+      Py_ssize_t pos = 0;
+      while ( PyDict_Next (result, &pos, &key, &value) )
+	{
+	  char *key_string = gdbpy_obj_to_string (key).release ();
+	  parse_mi_result (value, key_string);
+	  xfree ( (void *) key_string);
+	}
+    }
+}
+
+/* Called from mi_command_py's invoke to invoke the command.  */
+
+void
+py_mi_invoke (void *py_obj, char **argv, int argc)
+{
+  micmdpy_object *obj = (micmdpy_object *) py_obj;
+  PyObject *argobj, *result,  **strings;
+  int i;
+
+  gdbpy_enter enter_py (get_current_arch (), current_language);
+
+  if (! obj)
+    error(_("Invalid invocation of Python micommand object."));
+
+  if (! PyObject_HasAttr ((PyObject *) obj, invoke_cst))
+    {
+      error (_("Python command object missing 'invoke' method."));
+    }
+
+  strings = (PyObject **) malloc (sizeof(PyObject *) * argc);
+  argobj = PyList_New (argc);
+  if ( !argobj)
+    {
+      gdbpy_print_stack ();
+      error (_("Failed to create the python arguments list."));
+    }
+
+  for (i = 0; i < argc; ++i)
+    {
+      strings[i] = PyUnicode_Decode (argv[i], strlen(argv[i]), host_charset (), NULL);
+      if (PyList_SetItem (argobj, i, strings[i]) != 0)
+	{
+	  error (_("Failed to create the python arguments list."));
+	}
+    }
+
+  result = PyObject_CallMethodObjArgs ((PyObject *) obj, invoke_cst, argobj,
+				       NULL);
+
+  if (result)
+    parse_mi_result (result, NULL);
+
+  Py_DECREF (result);
+  Py_DECREF (argobj);
+  for (i = 0; i < argc; ++i)
+    {
+      Py_DECREF (strings[i]);
+    }
+  free (strings);
+}
+
+/* Parse the name of the MI command to register.
+
+   This function returns the xmalloc()d name of the new command. On error
+   sets the Python error and returns NULL.  */
+
+static char *
+micmdpy_parse_command_name (const char *name)
+{
+  int len = strlen (name);
+  int i, lastchar;
+  char *result;
+
+  /* Skip trailing whitespaces. */
+  for (i = len - 1; i >= 0 && (name[i] == ' ' || name[i] == '\t'); --i)
+    ;
+  if (i < 0)
+    {
+      PyErr_SetString (PyExc_RuntimeError, _("No command name found."));
+      return NULL;
+    }
+  lastchar = i;
+
+  /* Skip preceding whitespaces. */
+  /* Find first character of the final word.  */
+   for (; i > 0 && (isalnum (name[i - 1])
+ 		   || name[i - 1] == '-'
+ 		   || name[i - 1] == '_');
+        --i)
+     ;
+   /* Skip the first dash to have to command name only.
+    * i.e. -thread-info -> thread-info
+    */
+   if(name[i] == '-' && i < len - 2)
+     i++;
+
+   if( i == lastchar)
+    {
+      PyErr_SetString (PyExc_RuntimeError, _("No command name found."));
+      return NULL;
+    }
+
+  result = (char *) xmalloc (lastchar - i + 2);
+  memcpy(result, &name[i], lastchar - i + 1);
+  result[lastchar - i + 1] = '\0';
+
+  return result;
+}
+
+/* Object initializer; sets up gdb-side structures for MI command.
+
+   Use: __init__(NAME).
+
+   NAME is the name of the MI command to register. It should starts with a dash
+   as a traditional MI command does.  */
+
+static int
+micmdpy_init (PyObject *self, PyObject *args, PyObject *kw)
+{
+  micmdpy_object *obj = (micmdpy_object *) self;
+  static char *keywords[] = { "name", NULL };
+  const char *name;
+  char *cmd_name;
+  struct mi_cmd *cmd = NULL;
+
+  if(! PyArg_ParseTupleAndKeywords (args, kw, "s",
+				    keywords, &name))
+    return -1;
+
+  cmd_name = micmdpy_parse_command_name (name);
+  if (! cmd_name)
+    return -1;
+
+  Py_INCREF (self);
+
+  TRY
+  {
+    mi_command *micommand = new mi_command_py (cmd_name, NULL, (void *) self);
+
+    bool result = insert_mi_cmd_entry (mi_cmd_up (micommand));
+
+    if (! result)
+      {
+	PyErr_Format (PyExc_RuntimeError,
+		      _("Unable to insert command. The name might already be in use."));
+	return -1;
+      }
+  }
+  CATCH (except, RETURN_MASK_ALL)
+  {
+    xfree (cmd_name);
+    Py_DECREF (self);
+    PyErr_Format (except.reason == RETURN_QUIT
+		    ? PyExc_KeyboardInterrupt : PyExc_RuntimeError,
+		    "%s", except.message);
+    return -1;
+  }
+  END_CATCH
+
+  xfree (cmd_name);
+  return 0;
+}
+
+/* Initialize the MI command object.  */
+
+int
+gdbpy_initialize_micommands(void)
+{
+  micmdpy_object_type.tp_new = PyType_GenericNew;
+  if (PyType_Ready (&micmdpy_object_type) < 0)
+    return -1;
+
+  if (gdb_pymodule_addobject (gdb_module, "MICommand",
+  			      (PyObject *) &micmdpy_object_type) < 0)
+      return -1;
+
+  invoke_cst = PyString_FromString("invoke");
+  if (invoke_cst == NULL)
+    return -1;
+
+  return 0;
+}
+
+static PyMethodDef micmdpy_object_methods[] =
+    {
+	{ 0 }
+    };
+
+PyTypeObject micmdpy_object_type =
+{
+  PyVarObject_HEAD_INIT (NULL, 0)
+  "gdb.MICommand",		  /*tp_name*/
+  sizeof (micmdpy_object),	  /*tp_basicsize*/
+  0,				  /*tp_itemsize*/
+  0,				  /*tp_dealloc*/
+  0,				  /*tp_print*/
+  0,				  /*tp_getattr*/
+  0,				  /*tp_setattr*/
+  0,				  /*tp_compare*/
+  0,				  /*tp_repr*/
+  0,				  /*tp_as_number*/
+  0,				  /*tp_as_sequence*/
+  0,				  /*tp_as_mapping*/
+  0,				  /*tp_hash */
+  0,				  /*tp_call*/
+  0,				  /*tp_str*/
+  0,				  /*tp_getattro*/
+  0,				  /*tp_setattro*/
+  0,				  /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+  "GDB mi-command object",		  /* tp_doc */
+  0,				  /* tp_traverse */
+  0,				  /* tp_clear */
+  0,				  /* tp_richcompare */
+  0,				  /* tp_weaklistoffset */
+  0,				  /* tp_iter */
+  0,				  /* tp_iternext */
+  micmdpy_object_methods,	  /* tp_methods */
+  0,				  /* tp_members */
+  0,				  /* tp_getset */
+  0,				  /* tp_base */
+  0,				  /* tp_dict */
+  0,				  /* tp_descr_get */
+  0,				  /* tp_descr_set */
+  0,				  /* tp_dictoffset */
+  micmdpy_init,			  /* tp_init */
+  0,				  /* tp_alloc */
+};
diff --git a/gdb/python/py-micmd.h b/gdb/python/py-micmd.h
new file mode 100644
index 0000000..98f5305
--- /dev/null
+++ b/gdb/python/py-micmd.h
@@ -0,0 +1,6 @@
+#ifndef PY_MICMDS_H
+#define PY_MICMDS_H
+
+void py_mi_invoke (void *py_obj, char **argv, int argc);
+
+#endif
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index e2ebc1b..dafe273 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -504,6 +504,8 @@ int gdbpy_initialize_xmethods (void)
   CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
 int gdbpy_initialize_unwind (void)
   CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
+int gdbpy_initialize_micommands (void)
+  CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
 
 /* Called before entering the Python interpreter to install the
    current language and architecture to be used for Python values.
diff --git a/gdb/python/python.c b/gdb/python/python.c
index ab5a6a4..0995e4f 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -1728,7 +1728,8 @@ message == an error message without a stack will be printed."),
       || gdbpy_initialize_clear_objfiles_event ()  < 0
       || gdbpy_initialize_arch () < 0
       || gdbpy_initialize_xmethods () < 0
-      || gdbpy_initialize_unwind () < 0)
+      || gdbpy_initialize_unwind () < 0
+      || gdbpy_initialize_micommands () < 0)
     goto fail;
 
   gdbpy_to_string_cst = PyString_FromString ("to_string");
-- 
1.9.1

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/2] Use std::hashmap and MI commands classes in mi-cmds.c
  2017-02-10 18:19       ` Didier Nadeau
  2017-02-10 20:41         ` [PATCH] Create MI commands using python Didier Nadeau
@ 2017-02-11  5:01         ` Didier Nadeau
  2017-03-08 17:36           ` Didier Nadeau
  1 sibling, 1 reply; 10+ messages in thread
From: Didier Nadeau @ 2017-02-11  5:01 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

Hi,

The third patch has been sent. However I send it in another thread by
mistake, it is the patch titled "Create MI commands using Python" sent
on Friday 10 of February.

Thanks,
Didier Nadeau

2017-02-10 13:18 GMT-05:00 Didier Nadeau <didier.nadeau@gmail.com>:
> Hi,
>
> I have signed the assignment with the FSF. I am working on the third
> patch for MI commands in Python.
>
> Thanks,
> Didier Nadeau
>
> 2017-02-06 13:23 GMT-05:00 Pedro Alves <palves@redhat.com>:
>> On 02/06/2017 05:53 PM, Didier Nadeau wrote:
>>
>>> I do not have an assignment with the FSF yet.
>>
>> I sent the forms offlist.
>>
>> Thanks,
>> Pedro Alves
>>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/2] Use std::hashmap and MI commands classes in mi-cmds.c
  2017-02-11  5:01         ` [PATCH 0/2] Use std::hashmap and MI commands classes in mi-cmds.c Didier Nadeau
@ 2017-03-08 17:36           ` Didier Nadeau
  0 siblings, 0 replies; 10+ messages in thread
From: Didier Nadeau @ 2017-03-08 17:36 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

ping

2017-02-11 0:01 GMT-05:00 Didier Nadeau <didier.nadeau@gmail.com>:
> Hi,
>
> The third patch has been sent. However I send it in another thread by
> mistake, it is the patch titled "Create MI commands using Python" sent
> on Friday 10 of February.
>
> Thanks,
> Didier Nadeau
>
> 2017-02-10 13:18 GMT-05:00 Didier Nadeau <didier.nadeau@gmail.com>:
>> Hi,
>>
>> I have signed the assignment with the FSF. I am working on the third
>> patch for MI commands in Python.
>>
>> Thanks,
>> Didier Nadeau
>>
>> 2017-02-06 13:23 GMT-05:00 Pedro Alves <palves@redhat.com>:
>>> On 02/06/2017 05:53 PM, Didier Nadeau wrote:
>>>
>>>> I do not have an assignment with the FSF yet.
>>>
>>> I sent the forms offlist.
>>>
>>> Thanks,
>>> Pedro Alves
>>>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Create MI commands using python.
  2017-02-10 20:41         ` [PATCH] Create MI commands using python Didier Nadeau
@ 2017-03-17 15:38           ` Pedro Alves
  0 siblings, 0 replies; 10+ messages in thread
From: Pedro Alves @ 2017-03-17 15:38 UTC (permalink / raw)
  To: Didier Nadeau; +Cc: gdb-patches

Hi Didier, sorry for the delay.

On 02/10/2017 08:40 PM, Didier Nadeau wrote:
> This commit allows an user to create custom MI commands using Python
> similarly to what is possible for Python CLI commands.
> 
> A new subclass of mi_command is defined for Python MI commands,
> mi_command_py. A new file, py-micmd.c contains the logic for Python
> MI commands.

Thanks for posting the Python patch.  I suppose nobody
else commented thus far because this is missing a few things,
without which it is hard to review / understand / accept the patch.

#1 - An introduction.

 Some kind of rationale for why this is a desirable feature.  "Sell" 
 the feature, Make us way to "buy" it.  What is the intended use case?
 What do scripts supposedly look like?  How are scripts going to
 emit MI?  I suppose they'll build the MI output "manually" ?

#2 - Manual.

 A change to the manual to document the new APIs, and intended use cases.

#3 - Testsuite.

 New tests covering the new API.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2017-03-17 15:38 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-03  5:46 [PATCH 0/2] Use std::hashmap and MI commands classes in mi-cmds.c didier.nadeau
2017-02-03  5:46 ` [PATCH 2/2] Use classes to represent MI Command instead of structures didier.nadeau
2017-02-03  5:46 ` [PATCH 1/2] Use std::map for MI commands in mi-cmds.c didier.nadeau
2017-02-06 15:58 ` [PATCH 0/2] Use std::hashmap and MI commands classes " Pedro Alves
     [not found]   ` <CAK0EQJEOg0PA2xghH+89JvQr7ikf=nUBYJ9LvUvRY1RTkWGB_A@mail.gmail.com>
2017-02-06 18:23     ` Pedro Alves
2017-02-10 18:19       ` Didier Nadeau
2017-02-10 20:41         ` [PATCH] Create MI commands using python Didier Nadeau
2017-03-17 15:38           ` Pedro Alves
2017-02-11  5:01         ` [PATCH 0/2] Use std::hashmap and MI commands classes in mi-cmds.c Didier Nadeau
2017-03-08 17:36           ` Didier Nadeau

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).