@@ -29,6 +29,7 @@
#include "cli/cli-cmds.h"
#include "cli/cli-decode.h"
#include "cli/cli-script.h"
+#include "cli/cli-style.h"
#include "extension.h"
#include "interps.h"
@@ -1443,10 +1444,22 @@ do_define_command (const char *comname, int from_tty,
else
cmds = *commands;
- newc = add_cmd (comname, class_user, user_defined_command,
- (c && c->theclass == class_user)
- ? c->doc : xstrdup ("User-defined."), list);
- newc->user_commands = std::move (cmds);
+ {
+ struct cmd_list_element **c_prefixlist = c ? c->prefixlist : nullptr;
+ const char *c_prefixname = c ? c->prefixname : nullptr;
+
+ newc = add_cmd (comname, class_user, user_defined_command,
+ (c && c->theclass == class_user)
+ ? c->doc : xstrdup ("User-defined."), list);
+ newc->user_commands = std::move (cmds);
+
+ if (c_prefixlist != nullptr)
+ {
+ newc->prefixlist = c_prefixlist;
+ newc->prefixname = c_prefixname;
+ newc->allow_unknown = newc->user_commands.get () != nullptr;
+ }
+ }
/* If this new command is a hook, then mark both commands as being
tied. */
@@ -1521,6 +1534,52 @@ document_command (const char *comname, int from_tty)
c->doc = doc;
}
}
+
+/* Implementation of the "prefix-define" command. */
+
+static void
+prefix_define_command (const char *comname, int from_tty)
+{
+ struct cmd_list_element *c, **list;
+ const char *tem;
+ const char *comfull;
+ char *prefixname;
+
+ comfull = comname;
+ list = validate_comname (&comname);
+
+ /* Look it up, and verify that we got an exact match. */
+ tem = comname;
+ c = lookup_cmd (&tem, *list, "", -1, 1);
+ if (c && strcmp (comname, c->name) != 0)
+ c = nullptr;
+
+ if (c && c->theclass != class_user)
+ error (_("Command \"%s\" is built-in."), comfull);
+
+ if (c && c->prefixlist != nullptr)
+ {
+ /* c is already a user defined prefix command. */
+ return;
+ }
+
+ if (c == nullptr)
+ {
+ comname = xstrdup (comname);
+ c = add_cmd (comname, class_user, user_defined_command,
+ xstrdup ("User-defined."), list);
+ }
+
+ c->prefixlist = new struct cmd_list_element*;
+ *(c->prefixlist) = nullptr;
+ prefixname = (char *) xmalloc (strlen (comfull) + 2);
+ prefixname[0] = 0;
+ strcat (prefixname, comfull);
+ strcat (prefixname, " ");
+ c->prefixname = prefixname;
+ c->allow_unknown = c->user_commands.get () != nullptr;
+}
+
/* Used to implement source_command. */
@@ -1561,7 +1620,21 @@ void
show_user_1 (struct cmd_list_element *c, const char *prefix, const char *name,
struct ui_file *stream)
{
- struct command_line *cmdlines;
+ if (cli_user_command_p (c))
+ {
+ struct command_line *cmdlines = c->user_commands.get ();
+
+ fprintf_filtered (stream, "User %scommand \"",
+ c->prefixlist == NULL ? "" : "prefix ");
+ fprintf_styled (stream, title_style.style (), "%s%s",
+ prefix, name);
+ fprintf_filtered (stream, "\":\n");
+ if (cmdlines)
+ {
+ print_command_lines (current_uiout, cmdlines, 1);
+ fputs_filtered ("\n", stream);
+ }
+ }
if (c->prefixlist != NULL)
{
@@ -1570,25 +1643,23 @@ show_user_1 (struct cmd_list_element *c, const char *prefix, const char *name,
for (c = *c->prefixlist; c != NULL; c = c->next)
if (c->theclass == class_user || c->prefixlist != NULL)
show_user_1 (c, prefixname, c->name, gdb_stdout);
- return;
}
- cmdlines = c->user_commands.get ();
- fprintf_filtered (stream, "User command \"%s%s\":\n", prefix, name);
-
- if (!cmdlines)
- return;
- print_command_lines (current_uiout, cmdlines, 1);
- fputs_filtered ("\n", stream);
}
void
_initialize_cli_script (void)
{
- add_com ("document", class_support, document_command, _("\
+ struct cmd_list_element *c;
+
+ /* "document", "define" and "prefix-define" use command_completer,
+ as this helps the user to either type the command name and/or
+ its prefixes. */
+ c = add_com ("document", class_support, document_command, _("\
Document a user-defined command.\n\
Give command name as argument. Give documentation on following lines.\n\
End with a line of just \"end\"."));
+ set_cmd_completer (c, command_completer);
define_cmd_element = add_com ("define", class_support, define_command, _("\
Define a new command name. Command name is argument.\n\
Definition appears on following lines, one command per line.\n\
@@ -1597,6 +1668,14 @@ Use the \"document\" command to give documentation for the new command.\n\
Commands defined in this way may accept an unlimited number of arguments\n\
accessed via $arg0 .. $argN. $argc tells how many arguments have\n\
been passed."));
+ set_cmd_completer (define_cmd_element, command_completer);
+ c = add_com ("prefix-define", class_support, prefix_define_command,
+ _("\
+Define or mark a command as a user-defined prefix command.\n\
+User defined prefix commands can be used as prefix commands for\n\
+other user defined commands.\n\
+If the command already exists, it is changed to a prefix command."));
+ set_cmd_completer (c, command_completer);
while_cmd_element = add_com ("while", class_support, while_command, _("\
Execute nested commands WHILE the conditional expression is non zero.\n\
@@ -613,6 +613,16 @@ execute_command (const char *p, int from_tty)
/* c->user_commands would be NULL in the case of a python command. */
if (c->theclass == class_user && c->user_commands)
execute_user_command (c, arg);
+ else if (c->theclass == class_user
+ && c->prefixlist && !c->allow_unknown)
+ /* If this is a user defined prefix that does not allow unknown,
+ report the list of subcommands. */
+ {
+ printf_unfiltered
+ ("\"%.*s\" must be followed by the name of an %s command.\n",
+ (int) strlen (c->prefixname) - 1, c->prefixname, c->name);
+ help_list (*c->prefixlist, c->prefixname, all_commands, gdb_stdout);
+ }
else if (c->type == set_cmd)
do_set_command (arg, from_tty, c);
else if (c->type == show_cmd)
--
2.20.1
From ca10c3a9a7a55b3fc048ac33153743d858d0c999 Mon Sep 17 00:00:00 2001
From: Philippe Waroquiers <philippe.waroquiers@skynet.be>
Date: Sun, 8 Sep 2019 19:22:35 +0200
Subject: [PATCH 2/4] Test prefix-define.
Adds a test testing the new prefix-define command.
2019-08-03 Philippe Waroquiers <philippe.waroquiers@skynet.be>
* gdb.base/prefix-define.exp: New file.
---
gdb/testsuite/gdb.base/prefix-define.exp | 144 +++++++++++++++++++++++
1 file changed, 144 insertions(+)
create mode 100644 gdb/testsuite/gdb.base/prefix-define.exp
new file mode 100644
@@ -0,0 +1,144 @@
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2019 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+# This test verifies the "prefix-define" command.
+
+gdb_start
+
+# disable pagination
+gdb_test_no_output "set height 0" "disable pagination"
+
+####################
+# Verify the definition of user defined prefix commands.
+# Test the definition of a command using these prefixes.
+
+# Define an empty prefix command.
+gdb_test_no_output "prefix-define abc-prefix"
+
+# Verify an empty prefix command cannot be used as a command.
+gdb_test "abc-prefix" \
+ "\"abc-prefix\" must be followed by the name of an abc-prefix command.*" \
+ "An empty user defined prefix command cannot be executed"
+
+# Define a sub-prefix command.
+gdb_test_no_output "prefix-define abc-prefix def-prefix"
+
+# Define ghi-cmd using the prefixes.
+gdb_test_multiple "define abc-prefix def-prefix ghi-cmd" \
+ "define user command: abc-prefix def-prefix ghi-cmd" {
+ -re "Type commands for definition of \"abc-prefix def-prefix ghi-cmd\".\r\nEnd with a line saying just \"end\".\r\n>$" {
+ gdb_test "echo command ghi-cmd\\n\nend" "" \
+ "define user command: ghi-cmd"
+ }
+ }
+# Verify ghi-cmd works.
+gdb_test "abc-prefix def-prefix ghi-cmd" \
+ "command ghi-cmd" \
+ "use user command: ghi-cmd"
+
+
+####################
+# Verify an existing (empty) command can be marked as a prefix command.
+# Then verify an empty prefix command can be transformed into an executable command.
+
+# Define ghi-prefix-cmd as an empty command.
+gdb_test_multiple "define abc-prefix def-prefix ghi-prefix-cmd" \
+ "define user command: abc-prefix def-prefix ghi-prefix-cmd" {
+ -re "Type commands for definition of \"abc-prefix def-prefix ghi-prefix-cmd\".\r\nEnd with a line saying just \"end\".\r\n>$" {
+ gdb_test "end" "" \
+ "define user command: ghi-prefix-cmd"
+ }
+ }
+gdb_test_no_output "prefix-define abc-prefix def-prefix ghi-prefix-cmd"
+
+# Verify an empty prefix command cannot be used as a command.
+gdb_test "abc-prefix def-prefix ghi-prefix-cmd" \
+ "\"abc-prefix def-prefix ghi-prefix-cmd\" must be followed by the name of an ghi-prefix-cmd command.*" \
+ "An empty user defined prefix command cannot be executed"
+
+# Define jkl-cmd command.
+gdb_test_multiple "define abc-prefix def-prefix ghi-prefix-cmd jkl-cmd" \
+ "define user command: abc-prefix def-prefix ghi-prefix-cmd jkl-cmd" {
+ -re "Type commands for definition of \"abc-prefix def-prefix ghi-prefix-cmd jkl-cmd\".\r\nEnd with a line saying just \"end\".\r\n>$" {
+ gdb_test "echo command jkl-cmd\\n\nend" "" \
+ "define user command: jkl-cmd"
+ }
+ }
+# Verify jkl-cmd command works.
+gdb_test "abc-prefix def-prefix ghi-prefix-cmd jkl-cmd" \
+ "command jkl-cmd" \
+ "use user command: jkl-cmd"
+
+# Define alternate-jkl-cmd and check it works.
+# Define alternate-jkl-cmd command.
+gdb_test_multiple "define abc-prefix def-prefix ghi-prefix-cmd alternate-jkl-cmd" \
+ "define user command: abc-prefix def-prefix ghi-prefix-cmd alternate-jkl-cmd" {
+ -re "Type commands for definition of \"abc-prefix def-prefix ghi-prefix-cmd alternate-jkl-cmd\".\r\nEnd with a line saying just \"end\".\r\n>$" {
+ gdb_test "echo command alternate-jkl-cmd\\n\nend" "" \
+ "define user command: alternate-jkl-cmd"
+ }
+ }
+# Verify alternate-jkl-cmd command works.
+gdb_test "abc-prefix def-prefix ghi-prefix-cmd alternate-jkl-cmd" \
+ "command alternate-jkl-cmd" \
+ "use user command: alternate-jkl-cmd"
+
+
+
+# Now redefine ghi-prefix-cmd as a real command, and check it is working.
+send_gdb "define abc-prefix def-prefix ghi-prefix-cmd\n"
+gdb_expect {
+ -re "Redefine command \"ghi-prefix-cmd\".*y or n. $"\
+ {send_gdb "y\n"
+ gdb_expect {
+ -re "Type commands for definition of \"abc-prefix def-prefix ghi-prefix-cmd\".\r\nEnd with a line saying just \"end\".\r\n>$"\
+ {send_gdb "echo redefined command ghi-prefix-cmd\\n\nend\n"
+ gdb_expect {
+ -re "$gdb_prompt $"\
+ {pass "redefine user command: ghi-prefix-cmd"}
+ timeout {fail "(timeout) redefine user command: ghi-prefix-cmd"}
+ }
+ }
+ timeout {fail "(timeout) redefine user command: ghi-prefix-cmd"}
+ }
+ }
+ -re "$gdb_prompt $"\
+ {fail "redefine user command: ghi-prefix-cmd"}
+ timeout {fail "(timeout) redefine user command: ghi-prefix-cmd"}
+}
+
+# Verify ghi-prefix-cmd command works.
+gdb_test "abc-prefix def-prefix ghi-prefix-cmd" \
+ "redefined command ghi-prefix-cmd" \
+ "use redefined user command: ghi-prefix-cmd"
+
+# Check jkl-cmd still works.
+gdb_test "abc-prefix def-prefix ghi-prefix-cmd jkl-cmd" \
+ "command jkl-cmd" \
+ "use user command after redefining ghi-prefix-cmd: jkl-cmd"
+
+# Check alternate-jkl-cmd still works.
+gdb_test "abc-prefix def-prefix ghi-prefix-cmd alternate-jkl-cmd" \
+ "command alternate-jkl-cmd" \
+ "use user command after redefining ghi-prefix-cmd: alternate-jkl-cmd"
+
+####################
+# Check error behaviour.
+
+gdb_test "prefix-define print" ".* is built-in.*"
+
--
2.20.1
From 4575e31727ae020f3ddf5e7b4b99dfe3934e7f6b Mon Sep 17 00:00:00 2001
From: Philippe Waroquiers <philippe.waroquiers@skynet.be>
Date: Sun, 8 Sep 2019 21:54:18 +0200
Subject: [PATCH 3/4] Allow . character as part of command names.
gdb/ChangeLog
YYYY-MM-DD Philippe Waroquiers <philippe.waroquiers@skynet.be>
* command.h (valid_cmd_char_p): Declare.
* cli/cli-decode.c (valid_cmd_char_p): New function factorizing
the check of valid command char.
(find_command_name_length, valid_user_defined_cmd_name_p): Use
valid_cmd_char_p.
* cli/cli-script.c (validate_comname): Likewise.
* completer.c (gdb_completer_command_word_break_characters):
Do not remove . from the word break char, update comments.
(complete_line_internal_1): Use valid_cmd_char_p.
* guile/scm-cmd.c (gdbscm_parse_command_name): Likewise.
* python/py-cmd.c (gdbpy_parse_command_name): Likewise.
gdb/testsuite/ChangeLog
YYYY-MM-DD Philippe Waroquiers <philippe.waroquiers@skynet.be>
* gdb.base/define.exp: Test . in command names.
* gdb.base/setshow.exp: Update test, as . is now part of
command name.
---
gdb/cli/cli-decode.c | 24 ++++++++++++++----------
gdb/cli/cli-script.c | 2 +-
gdb/command.h | 8 ++++++++
gdb/completer.c | 10 +++++-----
gdb/guile/scm-cmd.c | 5 +----
gdb/python/py-cmd.c | 5 +----
gdb/testsuite/gdb.base/define.exp | 25 +++++++++++++++++++++++++
gdb/testsuite/gdb.base/setshow.exp | 2 +-
8 files changed, 56 insertions(+), 25 deletions(-)
@@ -1372,7 +1372,7 @@ find_command_name_length (const char *text)
if (*p == '!' || *p == '|')
return 1;
- while (isalnum (*p) || *p == '-' || *p == '_'
+ while (valid_cmd_char_p (*p)
/* Characters used by TUI specific commands. */
|| *p == '+' || *p == '<' || *p == '>' || *p == '$')
p++;
@@ -1380,9 +1380,18 @@ find_command_name_length (const char *text)
return p - text;
}
-/* Return TRUE if NAME is a valid user-defined command name.
- This is a stricter subset of all gdb commands,
- see find_command_name_length. */
+/* See command.h. */
+
+bool
+valid_cmd_char_p (int c)
+{
+ /* Alas "42" is a legitimate user-defined command.
+ In the interests of not breaking anything we preserve that. */
+
+ return isalnum (c) || c == '-' || c == '_' || c == '.';
+}
+
+/* See command.h. */
bool
valid_user_defined_cmd_name_p (const char *name)
@@ -1392,14 +1401,9 @@ valid_user_defined_cmd_name_p (const char *name)
if (*name == '\0')
return false;
- /* Alas "42" is a legitimate user-defined command.
- In the interests of not breaking anything we preserve that. */
-
for (p = name; *p != '\0'; ++p)
{
- if (isalnum (*p)
- || *p == '-'
- || *p == '_')
+ if (valid_cmd_char_p (*p))
; /* Ok. */
else
return false;
@@ -1339,7 +1339,7 @@ validate_comname (const char **comname)
p = *comname;
while (*p)
{
- if (!isalnum (*p) && *p != '-' && *p != '_')
+ if (!valid_cmd_char_p (*p))
error (_("Junk in argument list: \"%s\""), p);
p++;
}
@@ -133,8 +133,16 @@ extern struct cli_suppress_notification cli_suppress_notification;
/* API to the manipulation of command lists. */
+/* Return TRUE if NAME is a valid user-defined command name.
+ This is a stricter subset of all gdb commands,
+ see find_command_name_length. */
+
extern bool valid_user_defined_cmd_name_p (const char *name);
+/* Return TRUE if C is a valid command character. */
+
+extern bool valid_cmd_char_p (int c);
+
/* Const-correct variant of the above. */
extern struct cmd_list_element *add_cmd (const char *, enum command_class,
@@ -102,13 +102,13 @@ enum explicit_location_match_type
/* Variables which are necessary for fancy command line editing. */
-/* When completing on command names, we remove '-' from the list of
+/* When completing on command names, we remove '-' and '.' from the list of
word break characters, since we use it in command names. If the
readline library sees one in any of the current completion strings,
it thinks that the string needs to be quoted and automatically
supplies a leading quote. */
static const char gdb_completer_command_word_break_characters[] =
-" \t\n!@#$%^&*()+=|~`}{[]\"';:?/>.<,";
+" \t\n!@#$%^&*()+=|~`}{[]\"';:?/><,";
/* When completing on file names, we remove from the list of word
break characters any characters that are commonly used in file
@@ -1301,7 +1301,7 @@ complete_line_internal_1 (completion_tracker &tracker,
on command strings (as opposed to strings supplied by the
individual command completer functions, which can be any string)
then we will switch to the special word break set for command
- strings, which leaves out the '-' character used in some
+ strings, which leaves out the '-' and '.' character used in some
commands. */
set_rl_completer_word_break_characters
(current_language->la_word_break_characters());
@@ -1364,7 +1364,7 @@ complete_line_internal_1 (completion_tracker &tracker,
/* lookup_cmd_1 advances p up to the first ambiguous thing, but
doesn't advance over that thing itself. Do so now. */
q = p;
- while (*q && (isalnum (*q) || *q == '-' || *q == '_'))
+ while (valid_cmd_char_p (*q))
++q;
if (q != tmp_command + point)
{
@@ -1452,7 +1452,7 @@ complete_line_internal_1 (completion_tracker &tracker,
q = p;
while (q > tmp_command)
{
- if (isalnum (q[-1]) || q[-1] == '-' || q[-1] == '_')
+ if (valid_cmd_char_p (q[-1]))
--q;
else
break;
@@ -492,10 +492,7 @@ gdbscm_parse_command_name (const char *name,
lastchar = i;
/* Find first character of the final word. */
- for (; i > 0 && (isalnum (name[i - 1])
- || name[i - 1] == '-'
- || name[i - 1] == '_');
- --i)
+ for (; i > 0 && valid_cmd_char_p (name[i - 1]); --i)
;
result = (char *) xmalloc (lastchar - i + 2);
memcpy (result, &name[i], lastchar - i + 1);
@@ -375,10 +375,7 @@ gdbpy_parse_command_name (const char *name,
lastchar = i;
/* Find first character of the final word. */
- for (; i > 0 && (isalnum (name[i - 1])
- || name[i - 1] == '-'
- || name[i - 1] == '_');
- --i)
+ for (; i > 0 && valid_cmd_char_p (name[i - 1]); --i)
;
result = (char *) xmalloc (lastchar - i + 2);
memcpy (result, &name[i], lastchar - i + 1);
@@ -130,6 +130,31 @@ gdb_test "help nextwhere" \
" A next command that first shows you where you're stepping from.*" \
"preserve whitespace in help string"
+# Verify that GDB allows a user to use . in a command name.
+#
+gdb_test_multiple "define dot.command" "define user command: dot.command" {
+ -re "Type commands for definition of \"dot.command\".\r\nEnd with a line saying just \"end\".\r\n>$" {
+ gdb_test "echo dot command\\n\nend" "" \
+ "define user command: dot.command"
+ }
+}
+
+# Verify that dot.command works.
+#
+gdb_test "dot.command" \
+ "dot command" \
+ "full name dot.command"
+gdb_test "dot" \
+ "dot command" \
+ "partial name dot"
+gdb_test "dot." \
+ "dot command" \
+ "partial name dot."
+gdb_test "dot.c" \
+ "dot command" \
+ "partial name dot.c"
+
+
# Verify that the command parser doesn't require a space after an 'if'
# command in a user defined function.
#
@@ -287,7 +287,7 @@ gdb_test_no_output "set verbose off" "set verbose off"
gdb_test "show verbose" "Verbosity is off..*" "show verbose (off)"
#test argument must be preceded by space
foreach x {"history file" "solib-search-path" "data-directory"} {
- foreach y {"/home/" "." "~/home" "=home"} {
+ foreach y {"/home/" "~/home" "=home"} {
gdb_test "set $x$y" "Argument must be preceded by space." \
"$x is not set to $y"
}
--
2.20.1
From 0c71a62c4224552f53b71770f64b1fa57c0d49d9 Mon Sep 17 00:00:00 2001
From: Philippe Waroquiers <philippe.waroquiers@skynet.be>
Date: Sat, 28 Sep 2019 19:30:08 +0200
Subject: [PATCH 4/4] Document prefix-define command and the use of . in
command names.
gdb/ChangeLog
YYYY-MM-DD Philippe Waroquiers <philippe.waroquiers@skynet.be>
* NEWS: Mention prefix-define. Tell that command names can now
contain a . character.
gdb/doc/ChangeLog
YYYY-MM-DD Philippe Waroquiers <philippe.waroquiers@skynet.be>
* gdb.texinfo (Define): Indicate that user-defined prefix can
be used in 'define' command. Document 'prefix-define' command.
---
gdb/NEWS | 6 ++++++
gdb/doc/gdb.texinfo | 36 ++++++++++++++++++++++++++++++++++--
2 files changed, 40 insertions(+), 2 deletions(-)
@@ -27,6 +27,9 @@
provide the exitcode or exit status of the shell commands launched by
GDB commands such as "shell", "pipe" and "make".
+* User defined commands can now be defined using user defined prefix commands
+ Command names can now use the . character.
+
* The RX port now supports XML target descriptions.
* GDB now shows the Ada task names at more places, e.g. in task switching
@@ -81,6 +84,9 @@ pipe -d DELIM COMMAND DELIM SHELL_COMMAND
With no COMMAND, repeat the last executed command
and send its output to SHELL_COMMAND.
+prefix-define COMMAND
+ Define or mark a command as a user-defined prefix command.
+
with SETTING [VALUE] [-- COMMAND]
w SETTING [VALUE] [-- COMMAND]
Temporarily set SETTING, run COMMAND, and restore SETTING.
@@ -26367,8 +26367,9 @@ end
Define a command named @var{commandname}. If there is already a command
by that name, you are asked to confirm that you want to redefine it.
The argument @var{commandname} may be a bare command name consisting of letters,
-numbers, dashes, and underscores. It may also start with any predefined
-prefix command. For example, @samp{define target my-target} creates
+numbers, dashes, dots, and underscores. It may also start with any
+predefined or user-defined prefix command.
+For example, @samp{define target my-target} creates
a user-defined @samp{target my-target} command.
The definition of the command is made up of other @value{GDBN} command lines,
@@ -26389,6 +26390,37 @@ You may use the @code{document} command again to change the
documentation of a command. Redefining the command with @code{define}
does not change the documentation.
+@kindex prefix-define
+@item prefix-define @var{commandname}
+Define or mark the command @var{commandname} as a user-defined prefix
+command. Once marked, @var{commandname} can be used as prefix command
+by the @code{define} command.
+Note that @code{prefix-define} can be used with a not yet defined
+@var{commandname}. In such a case, @var{commandname} is defined as
+an empty user-defined command.
+
+Example:
+@example
+(gdb) prefix-define abc
+(gdb) prefix-define abc def
+(gdb) define abc def ghi
+Type commands for definition of "abc def ghi".
+End with a line saying just "end".
+>echo command ghi\n
+>end
+(gdb) define abc def
+Redefine command "def"? (y or n) y
+Type commands for definition of "abc def".
+End with a line saying just "end".
+>echo command def\n
+>end
+(gdb) abc def ghi
+command ghi
+(gdb) abc def
+command def
+(gdb)
+@end example
+
@kindex dont-repeat
@cindex don't repeat command
@item dont-repeat