[RFA, doc RFA] Add gdb.add_command_alias

Doug Evans dje@google.com
Fri Sep 9 19:25:00 GMT 2011


Hi.

Per discussion on IRC, here is a patch to add support for adding
command aliases.

Ok to check in?

valid_cmd_name_p is more restrictive than it could be.
E.g. gdb allows a user-defined command named "42", but
"it's easier to relax restrictions than it is to impose them after the fact",
so I'm going with this.

2011-09-09  Doug Evans  <dje@google.com>

	Add support for adding command aliases from python.
	* NEWS: Mention gdb.add_command_alias.
	* command.h (valid_cmd_name_p): Declare.
	* cli/cli-decode.c (valid_cmd_name_p): New function.
	* python/py-cmd.c (gdbpy_add_com_alias): New function.
	* python/python-internal.h (gdbpy_add_com_alias): Declare.
	* python/python.c (GdbMethods): Add add_command_alias.

	doc/
	* gdb.texinfo (Commands In Python): Document add_command_alias.

	testsuite/
	* gdb.python/py-cmd.exp: Add tests for gdb.add_command_alias.

Index: NEWS
===================================================================
RCS file: /cvs/src/src/gdb/NEWS,v
retrieving revision 1.452
diff -u -p -r1.452 NEWS
--- NEWS	4 Sep 2011 17:48:51 -0000	1.452
+++ NEWS	9 Sep 2011 18:07:50 -0000
@@ -38,6 +38,8 @@
 
   ** Symbols now provide the "type" attribute, the type of the symbol.
 
+  ** Command aliases can now be defined with the add_command_alias function.
+
 * libthread-db-search-path now supports two special values: $sdir and $pdir.
   $sdir specifies the default system locations of shared libraries.
   $pdir specifies the directory where the libpthread used by the application
Index: command.h
===================================================================
RCS file: /cvs/src/src/gdb/command.h,v
retrieving revision 1.74
diff -u -p -r1.74 command.h
--- command.h	14 Feb 2011 23:41:33 -0000	1.74
+++ command.h	9 Sep 2011 18:07:50 -0000
@@ -106,6 +106,8 @@ struct cmd_list_element;
 
 /* Forward-declarations of the entry-points of cli/cli-decode.c.  */
 
+extern int valid_cmd_name_p (const char *name);
+
 extern struct cmd_list_element *add_cmd (char *, enum command_class,
 					 void (*fun) (char *, int), char *,
 					 struct cmd_list_element **);
Index: cli/cli-decode.c
===================================================================
RCS file: /cvs/src/src/gdb/cli/cli-decode.c,v
retrieving revision 1.97
diff -u -p -r1.97 cli-decode.c
--- cli/cli-decode.c	8 Sep 2011 17:20:43 -0000	1.97
+++ cli/cli-decode.c	9 Sep 2011 18:07:50 -0000
@@ -126,6 +126,38 @@ set_cmd_completer (struct cmd_list_eleme
   cmd->completer = completer; /* Ok.  */
 }
 
+/* Return TRUE if NAME is a valid command name.
+
+   NOTE: TUI has a few special commands, +, <, >.
+   We don't watch for those here.  */
+
+int
+valid_cmd_name_p (const char *name)
+{
+  const char *p;
+
+  /* First character must be a letter, -, or _.  */
+  if (*name == '\0')
+    return FALSE;
+  if (isalpha (*name)
+      || *name == '-'
+      || *name == '_')
+    ; /* Ok.  */
+  else
+    return FALSE;
+
+  for (p = name + 1; *p != '\0'; ++p)
+    {
+      if (isalnum (*p)
+	  || *p == '-'
+	  || *p == '_')
+	; /* Ok.  */
+      else
+	return FALSE;
+    }
+
+  return TRUE;
+}
 
 /* Add element named NAME.
    Space for NAME and DOC must be allocated by the caller.
Index: doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.858
diff -u -p -r1.858 gdb.texinfo
--- doc/gdb.texinfo	4 Sep 2011 17:08:56 -0000	1.858
+++ doc/gdb.texinfo	9 Sep 2011 18:07:51 -0000
@@ -22668,6 +22668,35 @@ registration of the command with @value{
 Python code is read into @value{GDBN}, you may need to import the
 @code{gdb} module explicitly.
 
+@findex gdb.add_command_alias
+@defun add_command_alias name aliased_name command_class abbrev_flag
+Command aliases can be defined with the @code{gdb.add_command_alias} function.
+This is useful, for example, when you want to be able to type a command
+with a long name using fewer characters, and the contraction is otherwise
+ambiguous.  It can also we used when you want to give a command an alternate
+spelling.
+
+@var{name} is the name of the new command.
+@var{aliased_name} is the name of the command that is being aliased.
+Command names must begin with a letter, dash or underscore,
+and must consist of letters, numbers, dashes and underscores.
+
+@var{command_class} should be one of the @samp{COMMAND_} constants.
+
+@var{abbrev_flag} is a boolean flag specifying whether to treat the alias
+as an abbreviation of the original command or not.
+If the alias is an abbreviation it will not appear in @code{help}
+command list output.
+
+Here is an example where we make @code{e} an alternate spelling of the
+@code{x} command.
+
+@smallexample
+(gdb) python gdb.add_command_alias ("e", "x", gdb.COMMAND_DATA, 0)
+(gdb) e/10i main
+@end smallexample
+@end defun
+
 @node Parameters In Python
 @subsubsection Parameters In Python
 
Index: python/py-cmd.c
===================================================================
RCS file: /cvs/src/src/gdb/python/py-cmd.c,v
retrieving revision 1.16
diff -u -p -r1.16 py-cmd.c
--- python/py-cmd.c	8 Sep 2011 19:51:27 -0000	1.16
+++ python/py-cmd.c	9 Sep 2011 18:07:51 -0000
@@ -698,3 +698,34 @@ gdbpy_string_to_argv (PyObject *self, Py
 
   return py_argv;
 }
+
+
+
+/* Wrapper around add_com_alias.  */
+
+PyObject *
+gdbpy_add_com_alias (PyObject *self, PyObject *args, PyObject *kw)
+{
+  static char *keywords[] = {
+    "name", "aliased_name", "command_class", "abbrev_flag", NULL
+  };
+  char *name, *aliased_name;
+  int command_class, abbrev_flag;
+
+  if (! PyArg_ParseTupleAndKeywords (args, kw, "ssii", keywords,
+				     &name, &aliased_name,
+				     &command_class, &abbrev_flag))
+    return NULL;
+
+  if (! valid_cmd_name_p (name))
+    return PyErr_Format (PyExc_RuntimeError,
+			 _("Invalid command name `%s'."), name);
+  if (! valid_cmd_name_p (aliased_name))
+    return PyErr_Format (PyExc_RuntimeError,
+			 _("Invalid aliased command name `%s'."), aliased_name);
+
+  /* add_cmd requires *we* allocate space for name, hence the xstrdup.  */
+  add_com_alias (xstrdup (name), aliased_name, command_class, abbrev_flag);
+
+  Py_RETURN_NONE;
+}
Index: python/python-internal.h
===================================================================
RCS file: /cvs/src/src/gdb/python/python-internal.h,v
retrieving revision 1.47
diff -u -p -r1.47 python-internal.h
--- python/python-internal.h	8 Sep 2011 19:51:27 -0000	1.47
+++ python/python-internal.h	9 Sep 2011 18:07:52 -0000
@@ -152,6 +152,7 @@ PyObject *gdbpy_create_lazy_string_objec
 PyObject *gdbpy_inferiors (PyObject *unused, PyObject *unused2);
 PyObject *gdbpy_selected_thread (PyObject *self, PyObject *args);
 PyObject *gdbpy_string_to_argv (PyObject *self, PyObject *args);
+PyObject *gdbpy_add_com_alias (PyObject *self, PyObject *args, PyObject *kw);
 PyObject *gdbpy_parameter (PyObject *self, PyObject *args);
 PyObject *gdbpy_parameter_value (enum var_types type, void *var);
 char *gdbpy_parse_command_name (const char *name,
Index: python/python.c
===================================================================
RCS file: /cvs/src/src/gdb/python/python.c,v
retrieving revision 1.71
diff -u -p -r1.71 python.c
--- python/python.c	6 Sep 2011 14:49:00 -0000	1.71
+++ python/python.c	9 Sep 2011 18:07:52 -0000
@@ -1426,6 +1426,10 @@ Return the selected thread object." },
   { "inferiors", gdbpy_inferiors, METH_NOARGS,
     "inferiors () -> (gdb.Inferior, ...).\n\
 Return a tuple containing all inferiors." },
+  { "add_command_alias", (PyCFunction)gdbpy_add_com_alias,
+    METH_VARARGS | METH_KEYWORDS,
+    "Add an alias for an existing command." },
+
   {NULL, NULL, 0, NULL}
 };
 
Index: testsuite/gdb.python/py-cmd.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.python/py-cmd.exp,v
retrieving revision 1.6
diff -u -p -r1.6 py-cmd.exp
--- testsuite/gdb.python/py-cmd.exp	10 Jan 2011 11:00:23 -0000	1.6
+++ testsuite/gdb.python/py-cmd.exp	9 Sep 2011 18:07:52 -0000
@@ -45,6 +45,20 @@ gdb_py_test_multiple "input simple comma
 
 gdb_test "test_cmd ugh" "test_cmd output, arg = ugh" "call simple command"
 
+# Test an alias command.
+
+gdb_test_no_output "python gdb.add_command_alias (\"test_alias_cmd\", \"test_cmd\", gdb.COMMAND_OBSCURE, 0)" "add_command_alias"
+
+gdb_test "test_alias_cmd ugh" "test_cmd output, arg = ugh" "call alias command"
+
+gdb_test "python gdb.add_command_alias (\"(bad name)\", \"test_cmd\", gdb.COMMAND_OBSCURE, 0)" \
+  "RuntimeError: Invalid command name.*" \
+  "bad alias command name"
+
+gdb_test "python gdb.add_command_alias (\"test_alias_cmd\", \"(bad name)\", gdb.COMMAND_OBSCURE, 0)" \
+  "RuntimeError: Invalid aliased command name.*" \
+  "bad aliased command name"
+
 # Test a prefix command, and a subcommand within it.
 
 gdb_py_test_multiple "input prefix command" \



More information about the Gdb-patches mailing list