@@ -51,6 +51,7 @@
#include "cli/cli-cmds.h"
#include "cli/cli-style.h"
#include "cli/cli-utils.h"
+#include "cli/cli-style.h"
#include "extension.h"
#include "gdbsupport/pathstuff.h"
@@ -231,6 +232,7 @@ with_command_1 (const char *set_cmd_prefix,
nested_cmd = repeat_previous ();
cmd_list_element *set_cmd = lookup_cmd (&args, setlist, set_cmd_prefix,
+ nullptr,
/*allow_unknown=*/ 0,
/*ignore_help_classes=*/ 1);
gdb_assert (set_cmd != nullptr);
@@ -325,6 +327,146 @@ with_command_completer (struct cmd_list_element *ignore,
with_command_completer_1 ("set ", tracker, text);
}
+/* Completer for the "set|show leading-args" commands. */
+
+static void
+leading_args_cmd_completer (struct cmd_list_element *ignore,
+ completion_tracker &tracker,
+ const char *text, const char *word)
+{
+ tracker.set_use_custom_word_point (true);
+
+ complete_nested_command_line (tracker, text);
+}
+
+/* Look up the contents of TEXT as a command usable with leading args.
+ Throws an error if no such command is found.
+ Return the found command and advances TEXT past the found command.
+ If the found command is a postfix command, set *PREFIX_CMD to its prefix command. */
+
+static struct cmd_list_element *
+lookup_cmd_for_leading_args (const char **text,
+ struct cmd_list_element **prefix_cmd)
+{
+ const char *orig_text = *text;
+ struct cmd_list_element *lcmd, *alias, *cmd;
+
+ if (*text == nullptr || skip_spaces (*text) == nullptr)
+ error (_("COMMAND missing."));
+
+ /* We first use lookup_cmd to verify TEXT unambiguously identifies
+ a command. */
+ lcmd = lookup_cmd (text, cmdlist, "", NULL,
+ /*allow_unknown=*/ 0,
+ /*ignore_help_classes=*/ 1);
+
+ /* Note that we accept leading args for prefix commands,
+ as a prefix command can also be a valid usable
+ command accepting some arguments.
+ For example, "thread apply" applies a command to a
+ list of thread ids, and is also the prefix command for
+ thread apply all. */
+
+ /* We have an unambiguous command for which leading args
+ can be specified. What remains after having fond LCMD
+ is either spaces, or the leading args character. */
+
+ /* We then use lookup_cmd_composition to detect if the user
+ has specified an alias, and find the possible prefix_cmd
+ of cmd. */
+ lookup_cmd_composition
+ (std::string (orig_text, *text - orig_text).c_str (),
+ &alias, prefix_cmd, &cmd);
+ gdb_assert (cmd != nullptr);
+ gdb_assert (cmd == lcmd);
+ if (alias != nullptr)
+ cmd = alias;
+
+ return cmd;
+}
+
+/* Implementation of the "set leading-args" command. */
+
+static void
+set_leading_args_command (const char *arg, int from_tty)
+{
+ struct cmd_list_element *prefix_cmd;
+ struct cmd_list_element *cmd = lookup_cmd_for_leading_args (&arg, &prefix_cmd);
+
+ const char *leading_args = skip_spaces (arg);
+
+ if (*leading_args == '\0')
+ leading_args = nullptr;
+
+ if (cmd->leading_args)
+ xfree ((char *) cmd->leading_args);
+ if (leading_args == nullptr)
+ cmd->leading_args = nullptr;
+ else
+ cmd->leading_args = xstrdup (leading_args);
+}
+
+/* Print a message showing C's name and its leading args or <no leading args>
+ if C has no leading args.
+ If SILENT_FOR_NO_LEADING_ARGS, does nothing if C has no leading args. */
+
+static void
+show_leading_args (struct cmd_list_element *c,
+ const char *prefix,
+ bool silent_for_no_leading_args)
+{
+ if (c->leading_args != nullptr || !silent_for_no_leading_args)
+ {
+ fputs_filtered ("leading-args ", gdb_stdout);
+ fprintf_styled (gdb_stdout, title_style.style (),
+ "%s%s",
+ prefix == nullptr ? "" : prefix, c->name);
+ fprintf_filtered (gdb_stdout, " = %s\n",
+ c->leading_args == nullptr
+ ? "<no leading args>" : c->leading_args);
+ }
+}
+
+/* Recursively traverse COMMANDLIST and prints a message showing
+ the leading-args of the commands that have non-null leading args.
+ PREFIX is the prefix that led to COMMANDLIST. */
+
+static void
+show_leading_args_command_1 (struct cmd_list_element *commandlist,
+ const char *prefix)
+{
+ /* Walk through the commands. */
+ for (cmd_list_element *c = commandlist; c; c = c->next)
+ {
+ show_leading_args (c, prefix, true);
+ /* If C has subcommands, recursively search if its subcommands
+ have leading args.
+ Do not recurse for abbreviations to avoid duplicates
+ in the output. */
+ if (c->prefixlist != NULL && !c->abbrev_flag)
+ show_leading_args_command_1 (*c->prefixlist, c->prefixname);
+ }
+}
+
+/* Implementation of the "show leading-args" command. */
+
+static void
+show_leading_args_command (const char *arg, int from_tty)
+{
+ if (skip_spaces (arg) != nullptr)
+ {
+ struct cmd_list_element *prefix_cmd;
+ struct cmd_list_element *c = lookup_cmd_for_leading_args (&arg,
+ &prefix_cmd);
+
+ show_leading_args (c,
+ prefix_cmd == nullptr ? "" : prefix_cmd->prefixname,
+ false);
+ }
+ else
+ show_leading_args_command_1 (cmdlist, "");
+}
+
/* Provide documentation on command or list given by COMMAND. FROM_TTY
is ignored. */
@@ -1543,7 +1685,7 @@ show_user (const char *args, int from_tty)
{
const char *comname = args;
- c = lookup_cmd (&comname, cmdlist, "", 0, 1);
+ c = lookup_cmd (&comname, cmdlist, "", NULL, 0, 1);
if (!cli_user_command_p (c))
error (_("Not a user command."));
show_user_1 (c, "", args, gdb_stdout);
@@ -1575,6 +1717,71 @@ apropos_command (const char *arg, int from_tty)
apropos_cmd (gdb_stdout, cmdlist, verbose, pattern, "");
}
+/* The options for the "alias" command. */
+
+struct alias_opts
+{
+ /* For "-a". */
+ bool abbrev_flag = 0;
+};
+
+static const gdb::option::option_def alias_option_defs[] = {
+
+ gdb::option::flag_option_def<alias_opts> {
+ "a",
+ [] (alias_opts *opts) { return &opts->abbrev_flag; },
+ N_("Specify that ALIAS is an abbreviation of COMMAND.\n\
+Abbreviations are not shown in command lists displayed by the 'help' command."),
+ },
+
+};
+
+/* Create an option_def_group for the "alias" options, with
+ A_OPTS as context. */
+
+static inline gdb::option::option_def_group
+make_alias_options_def_group (alias_opts *a_opts)
+{
+ return {{alias_option_defs}, a_opts};
+}
+
+/* Completer for the "alias_command". */
+
+static void
+alias_command_completer (struct cmd_list_element *ignore,
+ completion_tracker &tracker,
+ const char *text, const char *word)
+{
+ const auto grp = make_alias_options_def_group (nullptr);
+
+ tracker.set_use_custom_word_point (true);
+
+ if (gdb::option::complete_options
+ (tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, grp))
+ return;
+
+ const char *delim = strstr (text, "=");
+
+ /* If we're past the "=" delimiter, complete the
+ "alias ALIAS = COMMAND [LEADING-ARGS...]" as if the user is
+ typing COMMAND LEADING-ARGS... */
+ if (delim != text
+ && delim != nullptr
+ && isspace (delim[-1])
+ && (isspace (delim[1]) || delim[1] == '\0'))
+ {
+ std::string new_text = std::string (delim + 1);
+
+ tracker.advance_custom_word_point_by (delim + 1 - text);
+ complete_nested_command_line (tracker, new_text.c_str ());
+ return;
+ }
+
+ /* We're not yet past the "=" delimiter. Complete a command, as
+ the user might type an alias following a prefix command. */
+ complete_nested_command_line (tracker, text);
+}
+
/* Subroutine of alias_command to simplify it.
Return the first N elements of ARGV flattened back to a string
with a space separating each element.
@@ -1609,7 +1816,7 @@ valid_command_p (const char *command)
{
struct cmd_list_element *c;
- c = lookup_cmd_1 (& command, cmdlist, NULL, 1);
+ c = lookup_cmd_1 (& command, cmdlist, NULL, NULL, 1);
if (c == NULL || c == (struct cmd_list_element *) -1)
return false;
@@ -1627,7 +1834,7 @@ valid_command_p (const char *command)
static void
alias_usage_error (void)
{
- error (_("Usage: alias [-a] [--] ALIAS = COMMAND"));
+ error (_("Usage: alias [-a] [--] ALIAS = COMMAND [LEADING-ARGS...]"));
}
/* Make an alias of an existing command. */
@@ -1635,8 +1842,13 @@ alias_usage_error (void)
static void
alias_command (const char *args, int from_tty)
{
+ alias_opts a_opts;
+
+ auto grp = make_alias_options_def_group (&a_opts);
+ gdb::option::process_options
+ (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, grp);
+
int i, alias_argc, command_argc;
- int abbrev_flag = 0;
const char *equals;
const char *alias, *command;
@@ -1647,24 +1859,18 @@ alias_command (const char *args, int from_tty)
std::string args2 (args, equals - args);
gdb_argv built_alias_argv (args2.c_str ());
- gdb_argv command_argv (equals + 1);
+
+ const char *leading_args = equals + 1;
+ struct cmd_list_element *c_command_prefix;
+
+ lookup_cmd_for_leading_args (&leading_args, &c_command_prefix);
+ std::string command_argv_str (equals + 1,
+ leading_args == nullptr
+ ? strlen (equals + 1)
+ : leading_args - equals - 1);
+ gdb_argv command_argv (command_argv_str.c_str ());
char **alias_argv = built_alias_argv.get ();
- while (alias_argv[0] != NULL)
- {
- if (strcmp (alias_argv[0], "-a") == 0)
- {
- ++alias_argv;
- abbrev_flag = 1;
- }
- else if (strcmp (alias_argv[0], "--") == 0)
- {
- ++alias_argv;
- break;
- }
- else
- break;
- }
if (alias_argv[0] == NULL || command_argv[0] == NULL
|| *alias_argv[0] == '\0' || *command_argv[0] == '\0')
@@ -1699,6 +1905,8 @@ alias_command (const char *args, int from_tty)
if (valid_command_p (alias))
error (_("Alias already exists: %s"), alias);
+ struct cmd_list_element *alias_cmd;
+
/* If ALIAS is one word, it is an alias for the entire COMMAND.
Example: alias spe = set print elements
@@ -1711,8 +1919,8 @@ alias_command (const char *args, int from_tty)
if (alias_argc == 1)
{
/* add_cmd requires *we* allocate space for name, hence the xstrdup. */
- add_com_alias (xstrdup (alias_argv[0]), command, class_alias,
- abbrev_flag);
+ alias_cmd = add_com_alias (xstrdup (alias_argv[0]), command, class_alias,
+ a_opts.abbrev_flag);
}
else
{
@@ -1732,19 +1940,30 @@ alias_command (const char *args, int from_tty)
alias_prefix = alias_prefix_string.c_str ();
command_prefix = command_prefix_string.c_str ();
- c_command = lookup_cmd_1 (& command_prefix, cmdlist, NULL, 1);
+ c_command = lookup_cmd_1 (& command_prefix, cmdlist, NULL, NULL, 1);
/* We've already tried to look up COMMAND. */
gdb_assert (c_command != NULL
&& c_command != (struct cmd_list_element *) -1);
gdb_assert (c_command->prefixlist != NULL);
- c_alias = lookup_cmd_1 (& alias_prefix, cmdlist, NULL, 1);
+ c_alias = lookup_cmd_1 (& alias_prefix, cmdlist, NULL, NULL, 1);
if (c_alias != c_command)
error (_("ALIAS and COMMAND prefixes do not match."));
/* add_cmd requires *we* allocate space for name, hence the xstrdup. */
- add_alias_cmd (xstrdup (alias_argv[alias_argc - 1]),
- command_argv[command_argc - 1],
- class_alias, abbrev_flag, c_command->prefixlist);
+ alias_cmd = add_alias_cmd (xstrdup (alias_argv[alias_argc - 1]),
+ command_argv[command_argc - 1],
+ class_alias, a_opts.abbrev_flag,
+ c_command->prefixlist);
+ }
+
+ gdb_assert (alias_cmd);
+ gdb_assert (alias_cmd->leading_args == nullptr);
+ if (leading_args != nullptr)
+ {
+ leading_args = skip_spaces (leading_args);
+
+ if (*leading_args != '\0')
+ alias_cmd->leading_args = xstrdup (leading_args);
}
}
@@ -2059,6 +2278,26 @@ You can supply a command number to start with, or a `+' to start after\n\
the previous command number shown."),
&showlist);
+ c = add_cmd ("leading-args", class_support, set_leading_args_command, _("\
+Set or clear leading args automatically prepended to a command or alias.\n\
+Usage: set leading-args COMMAND [LEADING-ARGS...]\n\
+Set or clear the leading arguments automatically prepended\n\
+to the arguments the user provides when COMMAND is run.\n\
+Note that COMMAND can be an alias. Commands and their aliases\n\
+do not share their leading arguments, so you can specify different\n\
+leading arguments for a command and for each of its aliases.\n\
+Without the [= LEADING-ARGS...], clears COMMAND leading arguments."),
+ &setlist);
+ set_cmd_completer_handle_brkchars (c, leading_args_cmd_completer);
+
+ c = add_cmd ("leading-args", class_support, show_leading_args_command, _("\
+Show the leading args of a command, or of all commands.\n\
+Usage: show leading-args [COMMAND]\n\
+Show the leading args of COMMAND. Without COMMAND, show the leading args\n\
+of all commands."),
+ &showlist);
+ set_cmd_completer_handle_brkchars (c, leading_args_cmd_completer);
+
add_cmd ("version", no_set_class, show_version,
_("Show what version of GDB this is."), &showlist);
@@ -2210,19 +2449,37 @@ When 'on', each command is displayed as it is executed."),
NULL,
&setlist, &showlist);
- c = add_com ("alias", class_support, alias_command, _("\
+ const auto alias_opts = make_alias_options_def_group (nullptr);
+
+ static std::string alias_help
+ = gdb::option::build_help (_("\
Define a new command that is an alias of an existing command.\n\
-Usage: alias [-a] [--] ALIAS = COMMAND\n\
+Usage: alias [-a] [--] ALIAS = COMMAND [LEADING-ARGS...]\n\
ALIAS is the name of the alias command to create.\n\
COMMAND is the command being aliased to.\n\
-If \"-a\" is specified, the command is an abbreviation,\n\
-and will not appear in help command list output.\n\
+\n\
+Options:\n\
+%OPTIONS%\
+You can optionally provide LEADING-ARGS to define at the same time\n\
+ALIAS and its leading args. This is the equivalent of:\n\
+ alias ALIAS = COMMAND\n\
+ set leading-args ALIAS LEADING-ARGS...\n\
\n\
Examples:\n\
Make \"spe\" an alias of \"set print elements\":\n\
- alias spe = set print elements\n\
+ alias spe set print elements\n\
Make \"elms\" an alias of \"elements\" in the \"set print\" command:\n\
- alias -a set print elms = set print elements"));
+ alias -a set print elms set print elements\n\
+Make \"btf\" an alias of \"backtrace -full -past-entry -past-main\" :\n\
+ alias btf = backtrace -full -past-entry -past-main\n\
+Make \"wLapPeu\" an alias of 2 nested \"with\":\n\
+ alias wLapPeu = with language pascal -- with print elements unlimited --"),
+ alias_opts);
+
+ c = add_com ("alias", class_support, alias_command,
+ alias_help.c_str ());
+
+ set_cmd_completer_handle_brkchars (c, alias_command_completer);
const char *source_help_text = xstrprintf (_("\
Read commands from a file named FILE.\n\
@@ -343,7 +343,7 @@ add_alias_cmd (const char *name, const char *oldname,
struct cmd_list_element *old;
tmp = oldname;
- old = lookup_cmd (&tmp, *list, "", 1, 1);
+ old = lookup_cmd (&tmp, *list, "", NULL, 1, 1);
return add_alias_cmd (name, old, theclass, abbrev_flag, list);
}
@@ -1045,6 +1045,7 @@ void
help_cmd (const char *command, struct ui_file *stream)
{
struct cmd_list_element *c;
+ const char *initial_command = command;
if (!command)
{
@@ -1058,7 +1059,7 @@ help_cmd (const char *command, struct ui_file *stream)
return;
}
- c = lookup_cmd (&command, cmdlist, "", 0, 0);
+ c = lookup_cmd (&command, cmdlist, "", NULL, 0, 0);
if (c == 0)
return;
@@ -1078,6 +1079,41 @@ help_cmd (const char *command, struct ui_file *stream)
fputs_filtered (c->doc, stream);
fputs_filtered ("\n", stream);
+ if (c->func != nullptr)
+ {
+ /* Print the leading args of the command if it has some.
+ Use lookup_cmd_composition to find if help was requested for
+ an alias. In this case, rather print the alias leading_args. */
+
+ struct cmd_list_element *alias, *prefix_cmd, *cmd;
+ const char *name, *leading_args;
+
+ lookup_cmd_composition (initial_command,
+ &alias, &prefix_cmd, &cmd);
+ gdb_assert (cmd != nullptr);
+ gdb_assert (cmd == c);
+
+ if (alias == nullptr)
+ {
+ name = c->name;
+ leading_args = c->leading_args;
+ }
+ else
+ {
+ name = alias->name;
+ leading_args = alias->leading_args;
+ }
+ if (leading_args != nullptr)
+ {
+ fputs_filtered ("leading-args ", stream);
+ fprintf_styled (stream, title_style.style (),
+ "%s%s",
+ prefix_cmd == nullptr ? "" : prefix_cmd->prefixname,
+ name);
+ fprintf_filtered (stream, " = %s\n", leading_args);
+ }
+ }
+
if (c->prefixlist == 0 && c->func != NULL)
return;
fprintf_filtered (stream, "\n");
@@ -1271,6 +1307,13 @@ print_help_for_command (struct cmd_list_element *c, const char *prefix,
fputs_filtered (" -- ", stream);
print_doc_line (stream, c->doc, false);
fputs_filtered ("\n", stream);
+ if (c->leading_args != nullptr)
+ {
+ fputs_filtered (" leading-args ", stream);
+ fprintf_styled (stream, title_style.style (),
+ "%s%s", prefix, c->name);
+ fprintf_filtered (stream, " = %s\n", c->leading_args);
+ }
if (recurse
&& c->prefixlist != 0
@@ -1418,8 +1461,12 @@ valid_user_defined_cmd_name_p (const char *name)
the list in which there are ambiguous choices (and *TEXT will be set to
the ambiguous text string).
+ if LEADING_ARGS is not null and the found command has leading args defined,
+ then *LEADING_ARGS points at these leading args.
+
If the located command was an abbreviation, this routine returns the base
- command of the abbreviation.
+ command of the abbreviation. Note that *LEADING_ARGS will point at the
+ leading args defined for the alias.
It does no error reporting whatsoever; control will always return
to the superior routine.
@@ -1446,11 +1493,13 @@ valid_user_defined_cmd_name_p (const char *name)
struct cmd_list_element *
lookup_cmd_1 (const char **text, struct cmd_list_element *clist,
- struct cmd_list_element **result_list, int ignore_help_classes)
+ struct cmd_list_element **result_list, const char **leading_args,
+ int ignore_help_classes)
{
char *command;
int len, nfound;
struct cmd_list_element *found, *c;
+ bool found_alias = false;
const char *line = *text;
while (**text == ' ' || **text == '\t')
@@ -1486,6 +1535,8 @@ lookup_cmd_1 (const char **text, struct cmd_list_element *clist,
/* Will be modified in calling routine
if we know what the prefix command is. */
*result_list = 0;
+ if (leading_args != NULL)
+ *leading_args = nullptr;
return CMD_LIST_AMBIGUOUS; /* Ambiguous. */
}
@@ -1501,22 +1552,30 @@ lookup_cmd_1 (const char **text, struct cmd_list_element *clist,
are warning about the alias, we may also warn about the command
itself and we will adjust the appropriate DEPRECATED_WARN_USER
flags. */
-
+
if (found->deprecated_warn_user)
deprecated_cmd_warning (line);
+
+ /* Return the leading_args of the alias, not the leading_args
+ of the command it is pointing to. */
+ if (leading_args != NULL)
+ *leading_args = found->leading_args;
found = found->cmd_pointer;
+ found_alias = true;
}
/* If we found a prefix command, keep looking. */
if (found->prefixlist)
{
c = lookup_cmd_1 (text, *found->prefixlist, result_list,
- ignore_help_classes);
+ leading_args, ignore_help_classes);
if (!c)
{
/* Didn't find anything; this is as far as we got. */
if (result_list != NULL)
*result_list = clist;
+ if (!found_alias && leading_args != NULL)
+ *leading_args = found->leading_args;
return found;
}
else if (c == CMD_LIST_AMBIGUOUS)
@@ -1531,6 +1590,9 @@ lookup_cmd_1 (const char **text, struct cmd_list_element *clist,
at the top of this function to clarify what is
supposed to be going on. */
*result_list = found;
+ /* For ambiguous commands, do not return any leading_args args. */
+ if (leading_args != nullptr)
+ *leading_args = nullptr;
return c;
}
else
@@ -1543,6 +1605,8 @@ lookup_cmd_1 (const char **text, struct cmd_list_element *clist,
{
if (result_list != NULL)
*result_list = clist;
+ if (!found_alias && leading_args != NULL)
+ *leading_args = found->leading_args;
return found;
}
}
@@ -1562,21 +1626,28 @@ undef_cmd_error (const char *cmdtype, const char *q)
/* Look up the contents of *LINE as a command in the command list LIST.
LIST is a chain of struct cmd_list_element's.
- If it is found, return the struct cmd_list_element for that command
- and update *LINE to point after the command name, at the first argument.
+ If it is found, return the struct cmd_list_element for that command,
+ update *LINE to point after the command name, at the first argument
+ and update *LEADING_ARGS (if LEADING_ARGS is not null) to point at
+ the leading args to prepend to the user provided args when running
+ the command.
+ Note that if the found cmd_list_element is found via an alias,
+ the leading args of the alias are returned.
+
If not found, call error if ALLOW_UNKNOWN is zero
otherwise (or if error returns) return zero.
Call error if specified command is ambiguous,
unless ALLOW_UNKNOWN is negative.
CMDTYPE precedes the word "command" in the error message.
- If INGNORE_HELP_CLASSES is nonzero, ignore any command list
+ If IGNORE_HELP_CLASSES is nonzero, ignore any command list
elements which are actually help classes rather than commands (i.e.
the function field of the struct cmd_list_element is 0). */
struct cmd_list_element *
lookup_cmd (const char **line, struct cmd_list_element *list,
const char *cmdtype,
+ const char **leading_args,
int allow_unknown, int ignore_help_classes)
{
struct cmd_list_element *last_list = 0;
@@ -1588,7 +1659,7 @@ lookup_cmd (const char **line, struct cmd_list_element *list,
if (!*line)
error (_("Lack of needed %scommand"), cmdtype);
- c = lookup_cmd_1 (line, list, &last_list, ignore_help_classes);
+ c = lookup_cmd_1 (line, list, &last_list, leading_args, ignore_help_classes);
if (!c)
{
@@ -69,6 +69,8 @@ struct cmd_list_element
{
if (doc && doc_allocated)
xfree ((char *) doc);
+ if (leading_args)
+ xfree ((char *) leading_args);
}
DISABLE_COPY_AND_ASSIGN (cmd_list_element);
@@ -176,6 +178,10 @@ struct cmd_list_element
/* Hook for another command to be executed after this command. */
struct cmd_list_element *hook_post = nullptr;
+ /* Leading arguments to automatically prepend to the user
+ provided arguments when running this command or alias. */
+ const char *leading_args = nullptr;
+
/* Nonzero identifies a prefix command. For them, the address
of the variable containing the list of subcommands. */
struct cmd_list_element **prefixlist = nullptr;
@@ -970,7 +970,7 @@ process_next_line (const char *p, struct command_line **command,
/* Resolve command abbreviations (e.g. 'ws' for 'while-stepping'). */
const char *cmd_name = p;
struct cmd_list_element *cmd
- = lookup_cmd_1 (&cmd_name, cmdlist, NULL, 1);
+ = lookup_cmd_1 (&cmd_name, cmdlist, NULL, NULL, 1);
cmd_name = skip_spaces (cmd_name);
bool inline_cmd = *cmd_name != '\0';
@@ -1327,7 +1327,7 @@ validate_comname (const char **comname)
std::string prefix (*comname, last_word - 1);
const char *tem = prefix.c_str ();
- c = lookup_cmd (&tem, cmdlist, "", 0, 1);
+ c = lookup_cmd (&tem, cmdlist, "", NULL, 0, 1);
if (c->prefixlist == NULL)
error (_("\"%s\" is not a prefix command."), prefix.c_str ());
@@ -1383,7 +1383,7 @@ do_define_command (const char *comname, int from_tty,
/* Look it up, and verify that we got an exact match. */
tem = comname;
- c = lookup_cmd (&tem, *list, "", -1, 1);
+ c = lookup_cmd (&tem, *list, "", NULL, -1, 1);
if (c && strcmp (comname, c->name) != 0)
c = 0;
@@ -1418,7 +1418,7 @@ do_define_command (const char *comname, int from_tty,
{
/* Look up cmd it hooks, and verify that we got an exact match. */
tem = comname + hook_name_size;
- hookc = lookup_cmd (&tem, *list, "", -1, 0);
+ hookc = lookup_cmd (&tem, *list, "", NULL, -1, 0);
if (hookc && strcmp (comname + hook_name_size, hookc->name) != 0)
hookc = 0;
if (!hookc && commands == nullptr)
@@ -1487,7 +1487,7 @@ document_command (const char *comname, int from_tty)
list = validate_comname (&comname);
tem = comname;
- c = lookup_cmd (&tem, *list, "", 0, 1);
+ c = lookup_cmd (&tem, *list, "", NULL, 0, 1);
if (c->theclass != class_user)
error (_("Command \"%s\" is built-in."), comfull);
@@ -244,11 +244,13 @@ extern enum cmd_types cmd_type (struct cmd_list_element *cmd);
extern struct cmd_list_element *lookup_cmd (const char **,
struct cmd_list_element *,
const char *,
+ const char **,
int, int);
extern struct cmd_list_element *lookup_cmd_1 (const char **,
struct cmd_list_element *,
struct cmd_list_element **,
+ const char **,
int);
extern struct cmd_list_element *deprecate_cmd (struct cmd_list_element *,
@@ -1341,7 +1341,7 @@ complete_line_internal_1 (completion_tracker &tracker,
}
else
{
- c = lookup_cmd_1 (&p, cmdlist, &result_list, ignore_help_classes);
+ c = lookup_cmd_1 (&p, cmdlist, &result_list, NULL, ignore_help_classes);
}
/* Move p up to the next interesting thing. */
@@ -515,7 +515,7 @@ gdbscm_parse_command_name (const char *name,
prefix_text[i + 1] = '\0';
prefix_text2 = prefix_text;
- elt = lookup_cmd_1 (&prefix_text2, *start_list, NULL, 1);
+ elt = lookup_cmd_1 (&prefix_text2, *start_list, NULL, NULL, 1);
if (elt == NULL || elt == CMD_LIST_AMBIGUOUS)
{
msg = xstrprintf (_("could not find command prefix '%s'"), prefix_text);
@@ -466,13 +466,13 @@ add_setshow_generic (enum var_types param_type, enum command_class cmd_class,
/* Lookup created parameter, and register Scheme object against the
parameter context. Perform this task against both lists. */
tmp_name = cmd_name;
- param = lookup_cmd (&tmp_name, *show_list, "", 0, 1);
+ param = lookup_cmd (&tmp_name, *show_list, "", NULL, 0, 1);
gdb_assert (param != NULL);
set_cmd_context (param, self);
*set_cmd = param;
tmp_name = cmd_name;
- param = lookup_cmd (&tmp_name, *set_list, "", 0, 1);
+ param = lookup_cmd (&tmp_name, *set_list, "", NULL, 0, 1);
gdb_assert (param != NULL);
set_cmd_context (param, self);
*show_cmd = param;
@@ -969,7 +969,7 @@ pascm_parameter_defined_p (const char *name, struct cmd_list_element *list)
{
struct cmd_list_element *c;
- c = lookup_cmd_1 (&name, list, NULL, 1);
+ c = lookup_cmd_1 (&name, list, NULL, NULL, 1);
/* If the name is ambiguous that's ok, it's a new parameter still. */
return c != NULL && c != CMD_LIST_AMBIGUOUS;
@@ -3146,7 +3146,7 @@ is restored."),
show_inferior_tty_command,
&setlist, &showlist);
cmd_name = "inferior-tty";
- c = lookup_cmd (&cmd_name, setlist, "", -1, 1);
+ c = lookup_cmd (&cmd_name, setlist, "", NULL, -1, 1);
gdb_assert (c != NULL);
add_alias_cmd ("tty", c, class_alias, 0, &cmdlist);
@@ -3159,7 +3159,7 @@ Follow this command with any number of args, to be passed to the program."),
set_args_command,
show_args_command,
&setlist, &showlist);
- c = lookup_cmd (&cmd_name, setlist, "", -1, 1);
+ c = lookup_cmd (&cmd_name, setlist, "", NULL, -1, 1);
gdb_assert (c != NULL);
set_cmd_completer (c, filename_completer);
@@ -3178,7 +3178,7 @@ working directory."),
set_cwd_command,
show_cwd_command,
&setlist, &showlist);
- c = lookup_cmd (&cmd_name, setlist, "", -1, 1);
+ c = lookup_cmd (&cmd_name, setlist, "", NULL, -1, 1);
gdb_assert (c != NULL);
set_cmd_completer (c, filename_completer);
@@ -84,12 +84,12 @@ Show the debugger's behaviour regarding auto-loaded Python scripts, "
NULL, NULL, show_auto_load_python_scripts,
&setlist, &showlist);
cmd_name = "auto-load-scripts";
- cmd = lookup_cmd (&cmd_name, setlist, "", -1, 1);
+ cmd = lookup_cmd (&cmd_name, setlist, "", NULL, -1, 1);
deprecate_cmd (cmd, "set auto-load python-scripts");
/* It is needed because lookup_cmd updates the CMD_NAME pointer. */
cmd_name = "auto-load-scripts";
- cmd = lookup_cmd (&cmd_name, showlist, "", -1, 1);
+ cmd = lookup_cmd (&cmd_name, showlist, "", NULL, -1, 1);
deprecate_cmd (cmd, "show auto-load python-scripts");
add_cmd ("python-scripts", class_info, info_auto_load_python_scripts,
@@ -396,7 +396,7 @@ gdbpy_parse_command_name (const char *name,
std::string prefix_text (name, i + 1);
prefix_text2 = prefix_text.c_str ();
- elt = lookup_cmd_1 (&prefix_text2, *start_list, NULL, 1);
+ elt = lookup_cmd_1 (&prefix_text2, *start_list, NULL, NULL, 1);
if (elt == NULL || elt == CMD_LIST_AMBIGUOUS)
{
PyErr_Format (PyExc_RuntimeError, _("Could not find command prefix %s."),
@@ -569,12 +569,12 @@ add_setshow_generic (int parmclass, enum command_class cmdclass,
/* Lookup created parameter, and register Python object against the
parameter context. Perform this task against both lists. */
tmp_name = cmd_name;
- param = lookup_cmd (&tmp_name, *show_list, "", 0, 1);
+ param = lookup_cmd (&tmp_name, *show_list, "", NULL, 0, 1);
if (param)
set_cmd_context (param, self);
tmp_name = cmd_name;
- param = lookup_cmd (&tmp_name, *set_list, "", 0, 1);
+ param = lookup_cmd (&tmp_name, *set_list, "", NULL, 0, 1);
if (param)
set_cmd_context (param, self);
}
@@ -14294,10 +14294,10 @@ If set, a break, instead of a cntrl-c, is sent to the remote target."),
set_remotebreak, show_remotebreak,
&setlist, &showlist);
cmd_name = "remotebreak";
- cmd = lookup_cmd (&cmd_name, setlist, "", -1, 1);
+ cmd = lookup_cmd (&cmd_name, setlist, "", NULL, -1, 1);
deprecate_cmd (cmd, "set remote interrupt-sequence");
cmd_name = "remotebreak"; /* needed because lookup_cmd updates the pointer */
- cmd = lookup_cmd (&cmd_name, showlist, "", -1, 1);
+ cmd = lookup_cmd (&cmd_name, showlist, "", NULL, -1, 1);
deprecate_cmd (cmd, "show remote interrupt-sequence");
add_setshow_enum_cmd ("interrupt-sequence", class_support,
@@ -533,6 +533,11 @@ set_repeat_arguments (const char *args)
repeat_arguments = args;
}
+/* Flag for whether we want to use the configured leading args.
+ Default is yes. */
+
+static bool enable_leading_args_var = true;
+
/* Execute the line P as a command, in the current user context.
Pass FROM_TTY as second argument to the defining function. */
@@ -561,6 +566,8 @@ execute_command (const char *p, int from_tty)
{
const char *cmd = p;
const char *arg;
+ const char *leading_args;
+ std::string leading_args_and_arg;
int was_sync = current_ui->prompt_state == PROMPT_BLOCKED;
line = p;
@@ -568,15 +575,27 @@ execute_command (const char *p, int from_tty)
/* If trace-commands is set then this will print this command. */
print_command_trace ("%s", p);
- c = lookup_cmd (&cmd, cmdlist, "", 0, 1);
+ c = lookup_cmd (&cmd, cmdlist, "", &leading_args, 0, 1);
p = cmd;
scoped_restore save_repeat_args
= make_scoped_restore (&repeat_arguments, nullptr);
const char *args_pointer = p;
- /* Pass null arg rather than an empty one. */
- arg = *p ? p : 0;
+ if (leading_args != nullptr && enable_leading_args_var)
+ {
+ if (*p)
+ leading_args_and_arg = std::string (leading_args)
+ + ' ' + std::string (p);
+ else
+ leading_args_and_arg = std::string (leading_args);
+ arg = leading_args_and_arg.c_str ();
+ }
+ else
+ {
+ /* Pass null arg rather than an empty one. */
+ arg = *p ? p : 0;
+ }
/* FIXME: cagney/2002-02-02: The c->type test is pretty dodgy
while the is_complete_command(cfunc) test is just plain
@@ -1883,7 +1902,7 @@ set_verbose (const char *args, int from_tty, struct cmd_list_element *c)
const char *cmdname = "verbose";
struct cmd_list_element *showcmd;
- showcmd = lookup_cmd_1 (&cmdname, showlist, NULL, 1);
+ showcmd = lookup_cmd_1 (&cmdname, showlist, NULL, NULL, 1);
gdb_assert (showcmd != NULL && showcmd != CMD_LIST_AMBIGUOUS);
if (c->doc && c->doc_allocated)
@@ -2113,6 +2132,19 @@ EMACS-like or VI-like commands like control-P or ESC."),
show_editing,
&setlist, &showlist);
+ add_setshow_boolean_cmd ("enable-leading-args", class_support,
+ &enable_leading_args_var, _("\
+Set whether GDB prepends leading args when running a command.\n\
+The leading args for a command are configured using\n\
+\"set leading-args COMMAND = LEADING-ARGS..."), _("\
+Show whether GDB prepends leading args when running a command."), _("\
+Use \"on\" to enable the usage of the configured leading args,\n\
+and \"off\" to disable it.\n\
+Without an argument, leading args usage is enabled."),
+ NULL,
+ NULL,
+ &setlist, &showlist);
+
add_setshow_boolean_cmd ("save", no_class, &write_history_p, _("\
Set saving of the history record on exit."), _("\
Show saving of the history record on exit."), _("\
@@ -651,7 +651,7 @@ validate_actionline (const char *line, struct breakpoint *b)
if (*p == '#') /* comment line */
return;
- c = lookup_cmd (&p, cmdlist, "", -1, 1);
+ c = lookup_cmd (&p, cmdlist, "", NULL, -1, 1);
if (c == 0)
error (_("`%s' is not a tracepoint action, or is ambiguous."), p);
@@ -1309,7 +1309,7 @@ encode_actions_1 (struct command_line *action,
action_exp = action->line;
action_exp = skip_spaces (action_exp);
- cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
+ cmd = lookup_cmd (&action_exp, cmdlist, "", NULL, -1, 1);
if (cmd == 0)
error (_("Bad action list item: %s"), action_exp);
@@ -2679,7 +2679,7 @@ trace_dump_actions (struct command_line *action,
if (*action_exp == '#') /* comment line */
continue;
- cmd = lookup_cmd (&action_exp, cmdlist, "", -1, 1);
+ cmd = lookup_cmd (&action_exp, cmdlist, "", NULL, -1, 1);
if (cmd == 0)
error (_("Bad action list item: %s"), action_exp);
--
2.20.1
From 90dcc6725bfc1d4d3e285e902c2fb3863002c53a Mon Sep 17 00:00:00 2001
From: Philippe Waroquiers <philippe.waroquiers@skynet.be>
Date: Sun, 23 Jun 2019 23:13:57 +0200
Subject: [PATCH 2/3] Add tests for new leading-args related commands and
arguments.
Test the new leading-args behaviour and completion.
Note that gdb.base/leading-args.exp is somewhat copied from
with.exp (the test of the with command), while leading-exp.c
is a plain copy of with.c.
gdb/testsuite/ChangeLog
2019-09-15 Philippe Waroquiers <philippe.waroquiers@skynet.be>
* gdb.base/leading-args.exp: New test.
* gdb.base/leading.c: New file.
* gdb.base/alias.exp: Update expected error msg for alias foo=bar.
---
gdb/testsuite/gdb.base/alias.exp | 2 +-
gdb/testsuite/gdb.base/leading-args.c | 41 +++++++
gdb/testsuite/gdb.base/leading-args.exp | 151 ++++++++++++++++++++++++
3 files changed, 193 insertions(+), 1 deletion(-)
create mode 100644 gdb/testsuite/gdb.base/leading-args.c
create mode 100644 gdb/testsuite/gdb.base/leading-args.exp
@@ -56,7 +56,7 @@ test_abbrev_alias set6 "alias -a -- set6 = set" 46
test_abbrev_alias -a "alias -a -- -a = set" 47
gdb_test "alias set2=set" "already exists: set2"
-gdb_test "alias foo=bar" "Invalid command to alias to: bar"
+gdb_test "alias foo=bar" "Undefined command: \"bar\". Try \"help\"."
gdb_test_no_output "alias spe = set p elem"
gdb_test_no_output "spe 50"
new file mode 100644
@@ -0,0 +1,41 @@
+/* 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/>. */
+
+int xxx1 = 123;
+
+struct S
+{
+ int a;
+ int b;
+ int c;
+};
+
+struct S g_s = {1, 2, 3};
+
+static void
+inc ()
+{
+ g_s.a++;;
+}
+
+int
+main ()
+{
+ inc ();
+
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,151 @@
+# 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/>.
+
+# Test the "leading-args" related commands and arguments.
+
+load_lib completion-support.exp
+
+standard_testfile .c
+
+if {[build_executable "failed to prepare" $testfile $srcfile debug]} {
+ return -1
+}
+
+clean_restart $binfile
+
+# Basic/core tests using user-visible commands.
+with_test_prefix "basics" {
+ # Define an alias to pretty print something.
+ gdb_test "print g_s" " = {a = 1, b = 2, c = 3}" "simple print"
+ gdb_test_no_output "alias PP = print -pretty --" "alias PP"
+ gdb_test "show leading-args PP" "leading-args PP = -pretty --"
+ gdb_test "PP g_s" \
+ [multi_line \
+ " = {" \
+ " a = 1," \
+ " b = 2," \
+ " c = 3" \
+ "}"]
+
+ # Define leading-args for "inspect", should not impact "print".
+ gdb_test_no_output "set leading-args inspect -pretty --" "inspect -pretty"
+ gdb_test "show leading-args inspect" "leading-args inspect = -pretty --"
+ gdb_test "print g_s" " = {a = 1, b = 2, c = 3}" "simple print not impacted"
+ gdb_test "inspect g_s" \
+ [multi_line \
+ " = {" \
+ " a = 1," \
+ " b = 2," \
+ " c = 3" \
+ "}"]
+
+ # Set hex as default FMT for print.
+ gdb_test_no_output "set leading-args print -- /x" "print hex"
+ gdb_test "inspect g_s" \
+ [multi_line \
+ " = {" \
+ " a = 1," \
+ " b = 2," \
+ " c = 3" \
+ "}"] "inspect g_s still pretty"
+ gdb_test "print g_s" " = {a = 0x1, b = 0x2, c = 0x3}" "simple print hex"
+
+ # Test disabling leading args.
+ gdb_test "show enable-leading-args" \
+ "Whether GDB prepends leading args when running a command is on\."
+ gdb_test_no_output "set enable-leading-args off"
+ gdb_test "print g_s" " = {a = 1, b = 2, c = 3}" \
+ "simple print with enable-leading-args off"
+ gdb_test_no_output "set enable-leading-args on"
+
+
+ # Define leading-args for an alias of frame apply all
+ gdb_test_no_output "alias frame apply tout = frame apply all -past-entry -past-main" \
+ "alias frame apply tout"
+ gdb_test "show leading-args frame apply tout" \
+ "leading-args frame apply tout = -past-entry -past-main"
+
+ # Show all leading args.
+ gdb_test "show leading-args" \
+ [multi_line \
+ "leading-args PP = -pretty --" \
+ "leading-args frame apply tout = -past-entry -past-main" \
+ "leading-args inspect = -pretty --" \
+ "leading-args print = -- /x"] "show leading-args"
+
+ # Clear the leading-args of "inspect".
+ gdb_test_no_output "set leading-args inspect" "clear inspect leading-args"
+ gdb_test "show leading-args inspect" "leading-args inspect = <no leading args>"
+ gdb_test "inspect g_s" " = {a = 1, b = 2, c = 3}" "simple inspect"
+
+}
+
+# Check errors.
+with_test_prefix "errors" {
+ # Try an unknown root setting.
+ gdb_test "set leading-args xxxx yyyy -someoption" \
+ "Undefined command: \"xxxx\". Try \"help\"\\."
+
+ # Try ambiguous command.
+ gdb_test "set leading-args a" \
+ "Ambiguous command \"a\":.*" "ambiguous a"
+ gdb_test "set leading-args frame a" \
+ "Ambiguous frame command \"a\":.*" "ambiguous frame a"
+}
+
+
+# Check completion.
+with_test_prefix "completion" {
+ test_gdb_complete_unique \
+ "alias set pri" \
+ "alias set print"
+
+ test_gdb_complete_unique \
+ "alias set print items = set pri" \
+ "alias set print items = set print"
+
+ test_gdb_complete_unique \
+ "alias set print items = set print ele" \
+ "alias set print items = set print elements"
+
+ test_gdb_complete_unique \
+ "alias btfu = backt" \
+ "alias btfu = backtrace"
+
+ test_gdb_complete_unique \
+ "alias btfu = backtrace -fu" \
+ "alias btfu = backtrace -full"
+
+ test_gdb_complete_unique \
+ "alias btfu = backtrace -full -past-e" \
+ "alias btfu = backtrace -full -past-entry"
+
+ gdb_test_no_output "alias btfu = backtrace -full -past-entry" \
+ "alias btfu"
+
+ # Test completion of 'set leading-args' (sharing most
+ # of the code that alias command uses to complete after
+ # the first =.
+ test_gdb_complete_unique \
+ "set leading-args btf" \
+ "set leading-args btfu"
+
+ test_gdb_complete_unique \
+ "set leading-args btfu -frame-a" \
+ "set leading-args btfu -frame-arguments"
+
+}
--
2.20.1
From 65bd84e184d6d8f82cf6f12312db3718b2cb08ee Mon Sep 17 00:00:00 2001
From: Philippe Waroquiers <philippe.waroquiers@skynet.be>
Date: Tue, 25 Jun 2019 00:50:29 +0200
Subject: [PATCH 3/3] NEWS and documentation for leading-args related concept
and commands.
gdb/ChangeLog
2019-09-15 Philippe Waroquiers <philippe.waroquiers@skynet.be>
* NEWS: Mention new leading-args commands. Mention change
to the alias command.
gdb/doc/ChangeLog
2019-09-15 Philippe Waroquiers <philippe.waroquiers@skynet.be>
* gdb.texinfo (Command leading args): New node documenting
'set|show leading-args' and 'set|show enable-leading-args'.
(Aliases): Document the new 'LEADING-ARGS...' option.
---
gdb/NEWS | 18 +++++++
gdb/doc/gdb.texinfo | 126 +++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 143 insertions(+), 1 deletion(-)
@@ -96,6 +96,18 @@ w SETTING [VALUE] [-- COMMAND]
maint with SETTING [VALUE] [-- COMMAND]
Like "with", but works with "maintenance set" settings.
+set leading-args COMMAND [LEADING-ARGS...]
+show leading-args [COMMAND]
+set enable-leading-args [on|off]
+show enable-leading-args
+ GDB can now automatically prepend leading args to a command or alias.
+ This allows to set default arguments or options for the GDB commands
+ or define easier to use aliases.
+ For example, 'set leading-args backtrace -full -frame-arguments all'
+ ensures that backtrace will automatically use the options -full
+ -frame-arguments all, without having to retype them for each backtrace
+ command.
+
set may-call-functions [on|off]
show may-call-functions
This controls whether GDB will attempt to call functions in
@@ -174,6 +186,12 @@ info sources [-dirname | -basename] [--] [REGEXP]
allow to restrict matching respectively to the dirname and basename
parts of the files.
+alias [-a] [--] ALIAS = COMMAND [LEADING-ARGS...]
+ The alias command can now directly define leading-args
+ to prepend to arguments provided by the user on the command line.
+ See 'set leading-args COMMAND [LEADING-ARGS...]' for more
+ information about leading args concept.
+
show style
The "show style" and its subcommands are now styling
a style name in their output using its own style, to help
@@ -1564,6 +1564,7 @@ show you the alternatives available, if there is more than one possibility).
* Command Settings:: How to change default behavior of commands
* Completion:: Command completion
* Command Options:: Command options
+* Command leading args:: Automatically prepend arguments to commands and aliases
* Help:: How to ask @value{GDBN} for help
@end menu
@@ -1984,6 +1985,116 @@ uppercase.
(For more on using the @code{print} command, see @ref{Data, ,Examining
Data}.)
+@node Command leading args
+@section Automatically prepend arguments to commands and aliases
+
+You can tell @value{GDBN} to always add some default options or
+arguments to a command.
+
+@cindex command options, automatically prepend
+@cindex command, default arguments
+
+@table @code
+@kindex set leading-args
+@item set leading-args @var{command} [@var{leading-args@dots{}}]
+
+If you repetitively use the same arguments or options for a command,
+you can tell @value{GDBN} to automatically prepend these arguments
+or options to the arguments you type explicitely.
+
+For example, if you always want to have the command @code{thread apply all}
+working on the threads in ascending order and to continue in case it
+encounters an error, you can tell @value{GDBN} to automatically preprend
+the @code{-ascending} and @code{-c} options by using:
+
+@smallexample
+(@value{GDBP}) set leading-args thread apply all -ascending -c
+@end smallexample
+
+Once you have set these leading args, any time you type
+the @code{thread apply all} followed by @code{some arguments},
+@value{GDBN} will execute @code{thread apply all -ascending -c some arguments}.
+
+As usual, unambiguous abbreviations can be used for @var{command}
+and @var{leading-args}.
+
+Commands and their aliases do not share their leading args.
+So, for example, you can configure the commands @code{bt}, @code{where},
+@code{backtrace} and @code{info stack} to output different levels
+of information and define a new alias @code{bt_ALL} showing all possible
+information using:
+@smallexample
+(@value{GDBP}) set leading-args bt -entry-values no -frame-arguments none
+(@value{GDBP}) set leading-args where -entry-values no -frame-argu scalars
+(@value{GDBP}) set leading-args backtrace -entry-values no -frame-argu all
+(@value{GDBP}) set leading-args info stack -entry-val both -fr all
+(@value{GDBP}) alias bt_ALL = backtrace
+(@value{GDBP}) set leading-args bt_ALL -entry-values both -frame-arg all \
+-past-main -past-entry -full
+@end smallexample
+
+You can define an alias and specify its leading args in one command using the shorter to type:
+@smallexample
+(@value{GDBP}) alias bt_ALL = backtrace -entry-values both -frame-arg all \
+-past-main -past-entry -full
+@end smallexample
+(For more on using the @code{alias} command, see @ref{Aliases}.)
+
+Leading args are not limited to the arguments and options of @var{command},
+but can specify nested commands if @var{command} accepts such a nested command
+as argument.
+For example, the below defines @code{faalocalsoftype} that can be used to list
+the frames having locals of a certain type, together with the matching local
+vars:
+@smallexample
+(@value{GDBP}) alias faalocalsoftype = frame apply all info locals -q -t
+(@value{GDBP}) faalocalsoftype int
+#1 0x55554f5e in sleeper_or_burner (v=0xdf50) at sleepers.c:86
+i = 0
+ret = 21845
+@end smallexample
+
+This is also very useful to define an alias for a set of nested @code{with}
+commands to have a particular combination of temporary settings. For example,
+the below defines the alias @code{pp10} that pretty prints an expression
+argument, with a maximum of 10 elements if the expression is a string or
+an array:
+@smallexample
+(@value{GDBP}) alias pp10 = with print pretty -- with print elem 10 -- print
+@end smallexample
+
+
+Use @code{set leading-args @var{command}} (without giving @var{LEADING-ARGS})
+to clear the leading args of @var{command}.
+
+@item show leading-args [@var{command}]
+
+Use @code{show leading-args @var{command}} to show the current values of
+the leading args for @var{command}. For example:
+@smallexample
+(@value{GDBP}) show leading-args backtrace
+leading-args backtrace = -entry-values no -frame-arguments all
+(@value{GDBP}) show leading-args break
+leading-args break = <no leading args>
+@end smallexample
+
+To show all the commands and aliases that have some leading args configured,
+use the command
+@code{show leading-args} without giving a @var{command} argument.
+
+@item set enable-leading-args @r{[}on|off@r{]}
+@itemx show enable-leading-args
+By default, @value{GDBN} will use the configured leading args.
+This can be disabled using @code{set enable-leading-args off}.
+The leading args of all commands are not cleared, but
+will not be used till you do @code{set enable-leading-args on}.
+This can be useful in user defined commands to ensure only the specified
+set of options are used by a command launched by the user-defined command.
+You can also use this setting in the @code{with} command, to temporarily
+run a command without its possibly configured leading args.
+
+@end table
+
@node Help
@section Getting Help
@cindex online documentation
@@ -27150,7 +27261,7 @@ You can define a new alias with the @samp{alias} command.
@table @code
@kindex alias
-@item alias [-a] [--] @var{ALIAS} = @var{COMMAND}
+@item alias [-a] [--] @var{ALIAS} = @var{COMMAND} [LEADING-ARGS...]
@end table
@@ -27168,6 +27279,19 @@ lists displayed by the @samp{help} command.
The @samp{--} option specifies the end of options,
and is useful when @var{ALIAS} begins with a dash.
+You can specify @var{leading-args} for your alias.
+These @var{leading-args} will be automatically added before the alias
+arguments typed explicitely on the command line.
+
+For example, the below defines an alias @code{btfullall} that shows all local
+variables and all frame arguments:
+@smallexample
+(@value{GDBP}) alias btfullall = backtrace -full -frame-arguments all
+@end smallexample
+
+For more information about @var{leading-args}, see @ref{Command leading args,
+,Automatically prepend arguments to commands and aliases}
+
Here is a simple example showing how to make an abbreviation
of a command so that there is less to type.
Suppose you were tired of typing @samp{disas}, the current