public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [RFAv5 0/3] Allow the user to define default args for commands and aliases
@ 2020-03-07 13:14 Philippe Waroquiers
  2020-03-07 13:14 ` [RFAv5 1/3] default-args: allow to define default command/alias arguments Philippe Waroquiers
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Philippe Waroquiers @ 2020-03-07 13:14 UTC (permalink / raw)
  To: gdb-patches

Allow the user to define default args for commands and aliases.

This patch series implements, tests and documents the following commands:

  set default-args COMMAND [DEFAULT-ARGS...]
  show default-args [COMMAND]
  set enable-default-args [on|off]
  show enable-default-args


It also changes the alias command to be:
  alias [-a] [--] ALIAS = COMMAND [DEFAULT-ARGS...]


Using the above default-args commands and arguments, you can
define default arguments for commands or define powerful aliases.

For example:

  alias bt_ALL = backtrace -entry-values both -frame-arg all -past-main -past-entry -full

defines the alias bt_ALL that will give as much information as possible
in a backtrace.

Default args can usefully be combined with the 'with' command, such as:

Make "wLapPeu" an alias of 2 nested "with":
  alias wLapPeu = with language pascal -- with print elements unlimited --

or have an alias pp10 to pretty print an expression with a maximum of
10 elements:

  alias pp10 = with print pretty -- with print elem 10 -- print

This patch series also adds a completer for 'alias'.


This is the version 5 of the patch series.
Compared the version 4, the changes are handling the comments of
Christian and Eli:
  * Declarations are moved close to their first use.
  * strchr (text, '='); used instead of strstr.
  * More consistent use of nullptr instead of NULL
  * std::string default_args used instead of const char *default_args
  * Updated/clarified NEWS and gdb.texinfo, as commented by Eli.

Previous versions handled various comments of Pedro and Tom.

For what concerns changing 'alias -a' to 'alias -abbreviation":
This can for sure be done (and be backward compatible).  This can however
be done as a separate patch (I still also need to do a similar change
for the 'qcs' flags).

Note 1: a preliminary version of this idea (using a command called
'add-args') was discussed in
https://sourceware.org/ml/gdb-patches/2019-06/msg00395.html
where Tom suggested to make it more GDB like, using 'set' command.

Note 2: Following another comment of Tom, there is no '=' character
to separate COMMAND from its default args.
If ever this would be ambiguous in some cases, we could introduce
an optional '=' character to separate COMMAND from its DEFAULT-ARGS.
Similarly, the alias command has no separator between COMMAND
and its DEFAULT-ARGS.




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

* [RFAv5 1/3] default-args: allow to define default command/alias arguments
  2020-03-07 13:14 [RFAv5 0/3] Allow the user to define default args for commands and aliases Philippe Waroquiers
@ 2020-03-07 13:14 ` Philippe Waroquiers
  2020-03-29 15:29   ` Simon Marchi
  2020-03-30  2:14   ` Simon Marchi
  2020-03-07 13:14 ` [RFAv5 2/3] Add tests for new default-args related commands and arguments Philippe Waroquiers
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 10+ messages in thread
From: Philippe Waroquiers @ 2020-03-07 13:14 UTC (permalink / raw)
  To: gdb-patches

Currently, a user can define an alias, but cannot have default
arguments for this alias.

This patch provides the following:

* A new command 'set default-args' that defines default args
  to prepend to the list of arguments explicitely given by the user.
  Note that default args can be used for an alias and nicely
  combine nested "with" (see below the changes for the alias command).

        (gdb) help set default-args
        Set or clear default args automatically prepended to the explicitely
        provided list of arguments of a command or alias.
        Usage: set default-args COMMAND [DEFAULT-ARGS...]
        Set or clear the default arguments automatically prepended
        to the list of arguments the user explicitely provides when COMMAND is run.
        Note that COMMAND can be an alias.  Commands and their aliases
        do not share their default arguments, so you can specify different
        default arguments for a command and for each of its aliases.
        Without DEFAULT-ARGS..., clears COMMAND default arguments.

  Note that 'set default-args' command has a completer to help typing
  COMMAND and its default-args.

* A new command 'show default-args'.

        (gdb) help show default-args
        Show the default args of a command, or of all commands.
        Usage: show default-args [COMMAND]
        Show the default args of COMMAND.  Without COMMAND, show the default args
        of all commands.

* The 'alias' command is modified so as to directly accept default-args.

        (gdb) help alias
        Define a new command that is an alias of an existing command.
        Usage: alias [-a] [--] ALIAS = COMMAND [DEFAULT-ARGS...]
        ALIAS is the name of the alias command to create.
        COMMAND is the command being aliased to.

        Options:
          -a
            Specify that ALIAS is an abbreviation of COMMAND.
            Abbreviations are not shown in command lists displayed by the 'help' command.
        You can optionally provide DEFAULT-ARGS to define at the same time
        ALIAS and its default args.  This is the equivalent of:
          alias ALIAS = COMMAND
          set default-args ALIAS DEFAULT-ARGS...

        Examples:
        Make "spe" an alias of "set print elements":
          alias spe set print elements
        Make "elms" an alias of "elements" in the "set print" command:
          alias -a set print elms set print elements
        Make "btf" an alias of "backtrace -full -past-entry -past-main" :
          alias btf = backtrace -full -past-entry -past-main
        Make "wLapPeu" an alias of 2 nested "with":
          alias wLapPeu = with language pascal -- with print elements unlimited --

* 'alias' command now has a completer that helps to complete:
     - ALIAS (if the user defines an alias after a prefix),
     - the aliased COMMAND
     - the possible options for the aliased COMMAND.

* A new setting 'set enable-default-args'.  This can be used if the
  user wants to temporarily disable the usage of default args.
  'show enable-default-args' shows the value of 'enable-default-args'.
  The main intended usage of this setting is to use it in the "with"
  command: as 'set default-args' can add arguments to standard GDB commands,
  it is useful (e.g. in user defined commands) to be able to go back
  to the 'standard' behaviour of a command.

gdb/ChangeLog
YYYY-MM-DD  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* cli/cli-cmds.c (default_args_cmd_completer)
	(lookup_cmd_for_default_args, set_default_args_command)
	(show_default_args, show_default_args_command_1)
	(show_default_args_command, alias_command_completer)
	(make_alias_options_def_group): New functions.
	(alias_opts, alias_option_defs): New struct and array.
	(alias_usage_error): Update usage.
	(alias_command): Handles optional DEFAULT-ARGS... arguments.
	Use option framework.
	(_initialize_cli_cmds): Install 'set|show default-args' commands.
	Update alias command help.
	(show_user, valid_command_p):
	Add NULL for new default_args lookup_cmd argument.
	* cli/cli-decode.c (help_cmd): Show default args if command has
	some.
	(lookup_cmd_1, lookup_cmd): New argument default_args.
	(add_alias_cmd):
	Add NULL for new default_args lookup_cmd argument.
	(print_help_for_command): Show default args.
	* cli/cli-decode.h (struct cmd_list_element): New member default_args.
	xfree default_args in destructor.
	* cli/cli-script.c (process_next_line, do_define_command):
	Add NULL for new default_args lookup_cmd argument.
	* command.h: Declare new default_args argument in lookup_cmd
	and lookup_cmd_1.
	* completer.c (complete_line_internal_1):
	Add NULL for new default_args lookup_cmd or lookup_cmd_1 argument.
	* guile/scm-cmd.c (gdbscm_parse_command_name): Likewise.
	* guile/scm-param.c (add_setshow_generic, pascm_parameter_defined_p):
	Likewise.
	* infcmd.c (_initialize_infcmd): Likewise.
	* python/py-auto-load.c (gdbpy_initialize_auto_load): Likewise.
	* python/py-cmd.c (gdbpy_parse_command_name): Likewise.
	* python/py-param.c (add_setshow_generic): Likewise.
	* remote.c (_initialize_remote): Likewise.
	* top.c (enable_default_args_var): New flag.
	(execute_command): Prepend default_args if command has some.
	(set_verbose):
	Add NULL for new default_args lookup_cmd or  lookup_cmd_1 argument.
	(init_main): Install 'set|show enable-default-args.
	* tracepoint.c (validate_actionline, encode_actions_1):
	Add NULL for new default_args lookup_cmd or lookup_cmd_1 argument.
---
 gdb/cli/cli-cmds.c        | 317 ++++++++++++++++++++++++++++++++++----
 gdb/cli/cli-decode.c      |  97 ++++++++++--
 gdb/cli/cli-decode.h      |   4 +
 gdb/cli/cli-script.c      |  12 +-
 gdb/command.h             |   2 +
 gdb/completer.c           |   2 +-
 gdb/guile/scm-cmd.c       |   2 +-
 gdb/guile/scm-param.c     |   6 +-
 gdb/infcmd.c              |   6 +-
 gdb/python/py-auto-load.c |   4 +-
 gdb/python/py-cmd.c       |   2 +-
 gdb/python/py-param.c     |   4 +-
 gdb/remote.c              |   4 +-
 gdb/top.c                 |  39 ++++-
 gdb/tracepoint.c          |   6 +-
 15 files changed, 432 insertions(+), 75 deletions(-)

diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index 6f324410e1..2fdd9b4fb0 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -50,6 +50,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"
@@ -230,6 +231,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);
@@ -324,6 +326,138 @@ with_command_completer (struct cmd_list_element *ignore,
   with_command_completer_1 ("set ", tracker,  text);
 }
 
+/* Completer for the "set|show default-args" commands.  */
+
+static void
+default_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 default 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_default_args (const char **text,
+			     struct cmd_list_element **prefix_cmd)
+{
+  const char *orig_text = *text;
+  struct cmd_list_element *lcmd;
+
+  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 default 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 default args
+     can be specified.  What remains after having fond LCMD
+     is either spaces, or the default 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.  */
+  struct cmd_list_element *alias, *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 default-args" command.  */
+
+static void
+set_default_args_command (const char *arg, int from_tty)
+{
+  struct cmd_list_element *prefix_cmd;
+  struct cmd_list_element *cmd = lookup_cmd_for_default_args (&arg, &prefix_cmd);
+
+  const char *default_args = skip_spaces (arg);
+  cmd->default_args = default_args;
+}
+
+/* Print a message showing C's name and its default args or <no default args>
+   if C has no default args.
+   If SILENT_FOR_NO_DEFAULT_ARGS, does nothing if C has no default args.  */
+
+static void
+show_default_args (struct cmd_list_element *c,
+		   const char *prefix,
+		   bool silent_for_no_default_args)
+{
+  if (!c->default_args.empty () || !silent_for_no_default_args)
+    {
+      fputs_filtered ("default-args ", gdb_stdout);
+      fprintf_styled (gdb_stdout, title_style.style (),
+		      "%s%s",
+		      prefix == nullptr ? "" : prefix, c->name);
+      fprintf_filtered (gdb_stdout, " = %s\n",
+			c->default_args.empty ()
+			? "<no default args>" : c->default_args.c_str ());
+    }
+}
+
+/* Recursively traverse COMMANDLIST and prints a message showing
+   the default-args of the commands that have non-null default args.
+   PREFIX is the prefix that led to COMMANDLIST.  */
+
+static void
+show_default_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_default_args (c, prefix, true);
+      /* If C has subcommands, recursively search if its subcommands
+	 have default args.
+	 Do not recurse for abbreviations to avoid duplicates
+	 in the output.  */
+      if (c->prefixlist != NULL && !c->abbrev_flag)
+	show_default_args_command_1 (*c->prefixlist, c->prefixname);
+    }
+}
+
+/* Implementation of the "show default-args" command.  */
+
+static void
+show_default_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_default_args (&arg,
+								&prefix_cmd);
+
+      show_default_args (c,
+			 prefix_cmd == nullptr ? "" : prefix_cmd->prefixname,
+			 false);
+    }
+  else
+    show_default_args_command_1 (cmdlist, "");
+}
+
 \f
 /* Provide documentation on command or list given by COMMAND.  FROM_TTY
    is ignored.  */
@@ -1550,7 +1684,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);
@@ -1582,6 +1716,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 = strchr (text, '=');
+
+  /* If we're past the "=" delimiter, complete the
+     "alias ALIAS = COMMAND [DEFAULT-ARGS...]" as if the user is
+     typing COMMAND DEFAULT-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.
@@ -1616,7 +1815,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;
@@ -1634,7 +1833,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 [DEFAULT-ARGS...]"));
 }
 
 /* Make an alias of an existing command.  */
@@ -1642,8 +1841,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;
 
@@ -1654,24 +1858,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 *default_args = equals + 1;
+  struct cmd_list_element *c_command_prefix;
+
+  lookup_cmd_for_default_args (&default_args, &c_command_prefix);
+  std::string command_argv_str (equals + 1,
+				default_args == nullptr
+				? strlen (equals + 1)
+				: default_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')
@@ -1706,6 +1904,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
 
@@ -1718,8 +1918,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
     {
@@ -1739,19 +1939,29 @@ 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->default_args.empty ());
+  if (default_args != nullptr)
+    {
+      default_args = skip_spaces (default_args);
+
+      alias_cmd->default_args = default_args;
     }
 }
 \f
@@ -1940,7 +2150,7 @@ setting_cmd (const char *fnname, struct cmd_list_element *showlist,
     error (_("First argument of %s must be a string."), fnname);
 
   const char *a0 = (const char *) value_contents (argv[0]);
-  cmd_list_element *cmd = lookup_cmd (&a0, showlist, "", -1, 0);
+  cmd_list_element *cmd = lookup_cmd (&a0, showlist, "", NULL, -1, 0);
 
   if (cmd == nullptr || cmd_type (cmd) != show_cmd)
     error (_("First argument of %s must be a "
@@ -2299,6 +2509,27 @@ You can supply a command number to start with, or a `+' to start after\n\
 the previous command number shown."),
 	   &showlist);
 
+  c = add_cmd ("default-args", class_support, set_default_args_command, _("\
+Set or clear default args automatically prepended to the explicitely\n\
+provided list of arguments of a command or alias.\n\
+Usage: set default-args COMMAND [DEFAULT-ARGS...]\n\
+Set or clear the default arguments automatically prepended\n\
+to the list of arguments the user explicitely provides when COMMAND is run.\n\
+Note that COMMAND can be an alias.  Commands and their aliases\n\
+do not share their default arguments, so you can specify different\n\
+default arguments for a command and for each of its aliases.\n\
+Without DEFAULT-ARGS..., clears COMMAND default arguments."),
+	   &setlist);
+  set_cmd_completer_handle_brkchars (c, default_args_cmd_completer);
+
+  c = add_cmd ("default-args", class_support, show_default_args_command, _("\
+Show the default args of a command, or of all commands.\n\
+Usage: show default-args [COMMAND]\n\
+Show the default args of COMMAND.  Without COMMAND, show the default args\n\
+of all commands."),
+	   &showlist);
+  set_cmd_completer_handle_brkchars (c, default_args_cmd_completer);
+
   add_cmd ("version", no_set_class, show_version,
 	   _("Show what version of GDB this is."), &showlist);
 
@@ -2450,19 +2681,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 [DEFAULT-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%\n\
+You can optionally provide DEFAULT-ARGS to define at the same time\n\
+ALIAS and its default args.  This is the equivalent of:\n\
+  alias ALIAS = COMMAND\n\
+  set default-args ALIAS DEFAULT-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\
diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c
index 7aecd9897e..123d31dcfb 100644
--- a/gdb/cli/cli-decode.c
+++ b/gdb/cli/cli-decode.c
@@ -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,42 @@ help_cmd (const char *command, struct ui_file *stream)
   fputs_filtered (c->doc, stream);
   fputs_filtered ("\n", stream);
 
+  if (c->func != nullptr)
+    {
+      /* Print the default 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 default_args.  */
+
+      struct cmd_list_element *alias, *prefix_cmd, *cmd;
+      const char *name;
+      std::string default_args;
+
+      lookup_cmd_composition (initial_command,
+			      &alias, &prefix_cmd, &cmd);
+      gdb_assert (cmd != nullptr);
+      gdb_assert (cmd == c);
+
+      if (alias == nullptr)
+	{
+	  name = c->name;
+	  default_args = c->default_args;
+	}
+      else
+	{
+	  name = alias->name;
+	  default_args = alias->default_args;
+	}
+      if (!default_args.empty ())
+	{
+	  fputs_filtered ("default-args ", stream);
+	  fprintf_styled (stream, title_style.style (),
+			  "%s%s",
+			  prefix_cmd == nullptr ? "" : prefix_cmd->prefixname,
+			  name);
+	  fprintf_filtered (stream, " = %s\n", default_args.c_str ());
+	}
+    }
+
   if (c->prefixlist == 0 && c->func != NULL)
     return;
   fprintf_filtered (stream, "\n");
@@ -1271,6 +1308,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->default_args.empty ())
+    {
+      fputs_filtered ("  default-args ", stream);
+      fprintf_styled (stream, title_style.style (),
+		      "%s%s", prefix, c->name);
+      fprintf_filtered (stream, " = %s\n", c->default_args.c_str ());
+    }
 
   if (recurse
       && c->prefixlist != 0
@@ -1422,8 +1466,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 DEFAULT_ARGS is not null, *DEFAULT_ARGS is set to the found command 
+   default args (possibly empty).
+
    If the located command was an abbreviation, this routine returns the base
-   command of the abbreviation.
+   command of the abbreviation.  Note that *DEFAULT_ARGS will contain the
+   default args defined for the alias.
 
    It does no error reporting whatsoever; control will always return
    to the superior routine.
@@ -1450,11 +1498,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, std::string *default_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,10 +1536,12 @@ lookup_cmd_1 (const char **text, struct cmd_list_element *clist,
 
   if (nfound > 1)
     {
-      if (result_list != NULL)
+      if (result_list != nullptr)
 	/* Will be modified in calling routine
 	   if we know what the prefix command is.  */
 	*result_list = 0;
+      if (default_args != nullptr)
+	*default_args = std::string ();
       return CMD_LIST_AMBIGUOUS;	/* Ambiguous.  */
     }
 
@@ -1505,22 +1557,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 default_args of the alias, not the default_args
+	 of the command it is pointing to.  */
+      if (default_args != nullptr)
+	*default_args = found->default_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);
+			default_args, ignore_help_classes);
       if (!c)
 	{
 	  /* Didn't find anything; this is as far as we got.  */
-	  if (result_list != NULL)
+	  if (result_list != nullptr)
 	    *result_list = clist;
+	  if (!found_alias && default_args != nullptr)
+	    *default_args = found->default_args;
 	  return found;
 	}
       else if (c == CMD_LIST_AMBIGUOUS)
@@ -1528,13 +1588,16 @@ lookup_cmd_1 (const char **text, struct cmd_list_element *clist,
 	  /* We've gotten this far properly, but the next step is
 	     ambiguous.  We need to set the result list to the best
 	     we've found (if an inferior hasn't already set it).  */
-	  if (result_list != NULL)
+	  if (result_list != nullptr)
 	    if (!*result_list)
 	      /* This used to say *result_list = *found->prefixlist.
 	         If that was correct, need to modify the documentation
 	         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 default_args args.  */
+	  if (default_args != nullptr)
+	    *default_args = std::string ();
 	  return c;
 	}
       else
@@ -1545,8 +1608,10 @@ lookup_cmd_1 (const char **text, struct cmd_list_element *clist,
     }
   else
     {
-      if (result_list != NULL)
+      if (result_list != nullptr)
 	*result_list = clist;
+      if (!found_alias && default_args != nullptr)
+	*default_args = found->default_args;
       return found;
     }
 }
@@ -1566,8 +1631,13 @@ 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 *DEFAULT_ARGS (if DEFAULT_ARGS is not null) to the default
+   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 default 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,
@@ -1581,6 +1651,7 @@ undef_cmd_error (const char *cmdtype, const char *q)
 struct cmd_list_element *
 lookup_cmd (const char **line, struct cmd_list_element *list,
 	    const char *cmdtype,
+	    std::string *default_args,
 	    int allow_unknown, int ignore_help_classes)
 {
   struct cmd_list_element *last_list = 0;
@@ -1592,7 +1663,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, default_args, ignore_help_classes);
 
   if (!c)
     {
diff --git a/gdb/cli/cli-decode.h b/gdb/cli/cli-decode.h
index 4f7c7701e4..fc864b78ff 100644
--- a/gdb/cli/cli-decode.h
+++ b/gdb/cli/cli-decode.h
@@ -183,6 +183,10 @@ struct cmd_list_element
     /* Hook for another command to be executed after this command.  */
     struct cmd_list_element *hook_post = nullptr;
 
+    /* Default arguments to automatically prepend to the user
+       provided arguments when running this command or alias.  */
+    std::string default_args;
+
     /* Nonzero identifies a prefix command.  For them, the address
        of the variable containing the list of subcommands.  */
     struct cmd_list_element **prefixlist = nullptr;
diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c
index c9d2378906..e912613785 100644
--- a/gdb/cli/cli-script.c
+++ b/gdb/cli/cli-script.c
@@ -974,7 +974,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';
 
@@ -1331,7 +1331,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 ());
 
@@ -1387,7 +1387,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;
 
@@ -1432,7 +1432,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)
@@ -1518,7 +1518,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);
@@ -1567,7 +1567,7 @@ define_prefix_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 != nullptr && strcmp (comname, c->name) != 0)
     c = nullptr;
 
diff --git a/gdb/command.h b/gdb/command.h
index 7f436c72c9..14ab62fb2c 100644
--- a/gdb/command.h
+++ b/gdb/command.h
@@ -252,11 +252,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 *,
+					    std::string *,
 					    int, int);
 
 extern struct cmd_list_element *lookup_cmd_1 (const char **,
 					      struct cmd_list_element *,
 					      struct cmd_list_element **,
+					      std::string *,
 					      int);
 
 extern struct cmd_list_element *deprecate_cmd (struct cmd_list_element *,
diff --git a/gdb/completer.c b/gdb/completer.c
index 619fb8a028..5e9b13aa90 100644
--- a/gdb/completer.c
+++ b/gdb/completer.c
@@ -1324,7 +1324,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.  */
diff --git a/gdb/guile/scm-cmd.c b/gdb/guile/scm-cmd.c
index ec1adffa25..8fd2772df4 100644
--- a/gdb/guile/scm-cmd.c
+++ b/gdb/guile/scm-cmd.c
@@ -512,7 +512,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);
diff --git a/gdb/guile/scm-param.c b/gdb/guile/scm-param.c
index b72766523a..62e2108740 100644
--- a/gdb/guile/scm-param.c
+++ b/gdb/guile/scm-param.c
@@ -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;
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index b4b128b287..d801180fa1 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -3192,7 +3192,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);
 
@@ -3205,7 +3205,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);
 
@@ -3224,7 +3224,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);
 
diff --git a/gdb/python/py-auto-load.c b/gdb/python/py-auto-load.c
index 2084fc43ff..56db946463 100644
--- a/gdb/python/py-auto-load.c
+++ b/gdb/python/py-auto-load.c
@@ -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,
diff --git a/gdb/python/py-cmd.c b/gdb/python/py-cmd.c
index b822c14004..b8e2c365ee 100644
--- a/gdb/python/py-cmd.c
+++ b/gdb/python/py-cmd.c
@@ -390,7 +390,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."),
diff --git a/gdb/python/py-param.c b/gdb/python/py-param.c
index 7b183cfa55..fb39187b18 100644
--- a/gdb/python/py-param.c
+++ b/gdb/python/py-param.c
@@ -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);
 }
diff --git a/gdb/remote.c b/gdb/remote.c
index 9b73faf9a3..be9ae16c1d 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -14394,10 +14394,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,
diff --git a/gdb/top.c b/gdb/top.c
index e2432489dc..2e179019e7 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -551,6 +551,11 @@ set_repeat_arguments (const char *args)
   repeat_arguments = args;
 }
 
+/* Flag for whether we want to use the configured default args.
+   Default is yes.  */
+
+static bool enable_default_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.  */
 
@@ -579,6 +584,8 @@ execute_command (const char *p, int from_tty)
     {
       const char *cmd = p;
       const char *arg;
+      std::string default_args;
+      std::string default_args_and_arg;
       int was_sync = current_ui->prompt_state == PROMPT_BLOCKED;
 
       line = p;
@@ -586,15 +593,26 @@ 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, "", &default_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 (!default_args.empty () && enable_default_args_var)
+	{
+	  if (*p)
+	    default_args_and_arg = default_args + ' ' + p;
+	  else
+	    default_args_and_arg = default_args;
+	  arg = default_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
@@ -1972,7 +1990,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)
@@ -2212,6 +2230,19 @@ EMACS-like or VI-like commands like control-P or ESC."),
 			   show_editing,
 			   &setlist, &showlist);
 
+  add_setshow_boolean_cmd ("enable-default-args", class_support,
+			   &enable_default_args_var, _("\
+Set whether GDB prepends default args when running a command.\n\
+The default args for a command are configured using\n\
+\"set default-args COMMAND DEFAULT-ARGS..."), _("\
+Show whether GDB prepends default args when running a command."), _("\
+Use \"on\" to enable the usage of the configured default args,\n\
+and \"off\" to disable it.\n\
+Without an argument, default 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."), _("\
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index aa6bea4a8f..26df3e0f61 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -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);
 
@@ -1303,7 +1303,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);
 
@@ -2673,7 +2673,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


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

* [RFAv5 2/3] Add tests for new default-args related commands and arguments.
  2020-03-07 13:14 [RFAv5 0/3] Allow the user to define default args for commands and aliases Philippe Waroquiers
  2020-03-07 13:14 ` [RFAv5 1/3] default-args: allow to define default command/alias arguments Philippe Waroquiers
@ 2020-03-07 13:14 ` Philippe Waroquiers
  2020-03-07 13:14 ` [RFAv5 3/3] NEWS and documentation for default-args related concept and commands Philippe Waroquiers
  2020-03-15 13:14 ` PING. Re: [RFAv5 0/3] Allow the user to define default args for commands and aliases Philippe Waroquiers
  3 siblings, 0 replies; 10+ messages in thread
From: Philippe Waroquiers @ 2020-03-07 13:14 UTC (permalink / raw)
  To: gdb-patches

Test the new default-args behaviour and completion.
Note that gdb.base/default-args.exp is somewhat copied from
with.exp (the test of the with command), while default-exp.c
is a plain copy of with.c.

gdb/testsuite/ChangeLog
YYYY-MM-DD  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* gdb.base/default-args.exp: New test.
	* gdb.base/default.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/default-args.c   |  41 +++++++
 gdb/testsuite/gdb.base/default-args.exp | 151 ++++++++++++++++++++++++
 3 files changed, 193 insertions(+), 1 deletion(-)
 create mode 100644 gdb/testsuite/gdb.base/default-args.c
 create mode 100644 gdb/testsuite/gdb.base/default-args.exp

diff --git a/gdb/testsuite/gdb.base/alias.exp b/gdb/testsuite/gdb.base/alias.exp
index be78d9e936..d98c3a38f1 100644
--- a/gdb/testsuite/gdb.base/alias.exp
+++ b/gdb/testsuite/gdb.base/alias.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"
diff --git a/gdb/testsuite/gdb.base/default-args.c b/gdb/testsuite/gdb.base/default-args.c
new file mode 100644
index 0000000000..c6426625d4
--- /dev/null
+++ b/gdb/testsuite/gdb.base/default-args.c
@@ -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;
+}
diff --git a/gdb/testsuite/gdb.base/default-args.exp b/gdb/testsuite/gdb.base/default-args.exp
new file mode 100644
index 0000000000..3b486a6c7a
--- /dev/null
+++ b/gdb/testsuite/gdb.base/default-args.exp
@@ -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 "default-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 default-args PP" "default-args PP = -pretty --"
+    gdb_test "PP g_s" \
+	[multi_line  \
+	     " = {" \
+	     "  a = 1," \
+	     "  b = 2," \
+	     "  c = 3" \
+	     "}"]
+
+    # Define default-args for "inspect", should not impact "print".
+    gdb_test_no_output "set default-args inspect -pretty --" "inspect -pretty"
+    gdb_test "show default-args inspect" "default-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 default-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 default args.
+    gdb_test "show enable-default-args" \
+	"Whether GDB prepends default args when running a command is on\."
+    gdb_test_no_output "set enable-default-args off"
+    gdb_test "print g_s" " = {a = 1, b = 2, c = 3}" \
+	"simple print with enable-default-args off"
+    gdb_test_no_output "set enable-default-args on"
+    
+
+    # Define default-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 default-args frame apply tout" \
+	"default-args frame apply tout = -past-entry -past-main"
+
+    # Show all default args.
+    gdb_test "show default-args" \
+	[multi_line  \
+	     "default-args PP = -pretty --" \
+	     "default-args frame apply tout = -past-entry -past-main" \
+	     "default-args inspect = -pretty --" \
+	     "default-args print = -- /x"] "show default-args"
+
+    # Clear the default-args of "inspect".
+    gdb_test_no_output "set default-args inspect" "clear inspect default-args"
+    gdb_test "show default-args inspect" "default-args inspect = <no default 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 default-args xxxx yyyy -someoption" \
+	"Undefined command: \"xxxx\".  Try \"help\"\\."
+
+    # Try ambiguous command.
+    gdb_test "set default-args a" \
+	"Ambiguous command \"a\":.*" "ambiguous a"
+    gdb_test "set default-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 default-args' (sharing most
+    # of the code that alias command uses to complete after
+    # the first =.
+    test_gdb_complete_unique \
+	"set default-args btf" \
+	"set default-args btfu"
+
+    test_gdb_complete_unique \
+	"set default-args btfu -frame-a" \
+	"set default-args btfu -frame-arguments"
+
+}
-- 
2.20.1


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

* [RFAv5 3/3] NEWS and documentation for default-args related concept and commands.
  2020-03-07 13:14 [RFAv5 0/3] Allow the user to define default args for commands and aliases Philippe Waroquiers
  2020-03-07 13:14 ` [RFAv5 1/3] default-args: allow to define default command/alias arguments Philippe Waroquiers
  2020-03-07 13:14 ` [RFAv5 2/3] Add tests for new default-args related commands and arguments Philippe Waroquiers
@ 2020-03-07 13:14 ` Philippe Waroquiers
  2020-03-07 14:37   ` Eli Zaretskii
  2020-03-15 13:14 ` PING. Re: [RFAv5 0/3] Allow the user to define default args for commands and aliases Philippe Waroquiers
  3 siblings, 1 reply; 10+ messages in thread
From: Philippe Waroquiers @ 2020-03-07 13:14 UTC (permalink / raw)
  To: gdb-patches

gdb/ChangeLog
YYYY-MM-DD  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* NEWS: Mention new default-args commands.  Mention change
	to the alias command.

gdb/doc/ChangeLog
YYYY-MM-DD  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* gdb.texinfo (Command default args): New node documenting
	'set|show default-args' and 'set|show enable-default-args'.
	(Aliases): Document the new 'DEFAULT-ARGS...' option.
---
 gdb/NEWS            |  29 +++++++++
 gdb/doc/gdb.texinfo | 139 +++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 167 insertions(+), 1 deletion(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 6657f6fadc..62dea7e983 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -55,10 +55,39 @@ show exec-file-mismatch -- Show exec-file-mismatch handling (ask|warn|off).
   whether to load the process executable file; if 'warn', just display
   a warning; if 'off', don't attempt to detect a mismatch.
 
+set default-args COMMAND [DEFAULT-ARGS...]
+show default-args [COMMAND]
+set enable-default-args [on|off]
+show enable-default-args
+  GDB can now automatically prepend default arguments to the argument list
+  provided explicitely by the user.
+  This allows to set default arguments or options for the GDB commands
+  or define easily more specialised aliases.
+  For example, 'set default-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.
+
 tui new-layout NAME WINDOW WEIGHT [WINDOW WEIGHT]...
   Define a new TUI layout, specifying its name and the windows that
   will be displayed.
 
+* Changed commands
+
+alias [-a] [--] ALIAS = COMMAND [DEFAULT-ARGS...]
+  The alias command can now directly define default-args
+  to prepend to the argument list provided explicitely by the user.
+  For example, to have a backtrace with full details, you can define
+  an alias 'bt_ALL' as
+  'alias bt_ALL = backtrace -entry-values both -frame-arg all
+     -past-main -past-entry -full'.
+  Alias default arguments can also use a set of nested 'with' commands,
+  e.g. 'alias pp10 = with print pretty -- with print elem 10 -- print'
+  defines the alias pp10 that will pretty print a maximum of 10 elements
+  of the given expression (if the expression is an array).
+  See 'set default-args COMMAND [DEFAULT-ARGS...]' for more
+  information about default args concept.
+
 * New targets
 
 GNU/Linux/RISC-V (gdbserver)	riscv*-*-linux*
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 385c832f22..c0fdb25ce2 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -1577,6 +1577,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 default args::        Automatically prepend default arguments to commands and aliases
 * Help::                        How to ask @value{GDBN} for help
 @end menu
 
@@ -1997,6 +1998,129 @@ uppercase.
 (For more on using the @code{print} command, see @ref{Data, ,Examining
 Data}.)
 
+@node Command default args
+@section Automatically prepend default arguments to commands and aliases
+
+You can tell @value{GDBN} to always prependd some default arguments to
+the list of arguments provided explicitely by the user.
+
+@cindex command options, automatically prepend
+@cindex command, default arguments
+
+@table @code
+@kindex set default-args
+@item set default-args @var{command} [@var{default-args@dots{}}]
+
+If you repeatedly use the same arguments or options for a command,
+you can tell @value{GDBN} to automatically prepend these arguments
+or options to the list of 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 default-args thread apply all -ascending -c
+@end smallexample
+
+Once you have set these default 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{default-args}.
+
+Commands and their aliases do not share their default 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 default-args bt -entry-values no -frame-arguments none
+(@value{GDBP}) set default-args where -entry-values no -frame-argu scalars
+(@value{GDBP}) set default-args backtrace -entry-values no -frame-argu all
+(@value{GDBP}) set default-args info stack -entry-val both -fr all
+(@value{GDBP}) alias bt_ALL = backtrace
+(@value{GDBP}) set default-args bt_ALL -entry-values both -frame-arg all \
+   -past-main -past-entry -full
+@end smallexample
+
+You can define an alias and specify its default 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}.)
+
+Default 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 elements 10 -- print
+@end smallexample
+This defines the alias  @code{pp10} as being a sequence of 3 commands.
+The first part @code{with print pretty --} temporarily activates the setting
+@code{set print pretty}, then launches the command that follows the separator
+@code{--}.
+The command following the first part is also a @code{with} command that
+temporarily changes the setting @code{set print elements} to 10, then
+launches the command that follows the second separator @code{--}.
+The third part @code{print} is the command the @code{pp10} alias will launch,
+using the temporary values of the settings and the arguments explicitely given
+by the user.
+For more information about the @code{with} command usage,
+see @ref{Command Settings}.
+
+Use @code{set default-args @var{command}} (without giving @var{default-args})
+to clear the default args of @var{command}.
+
+@item show default-args [@var{command}]
+
+Use @code{show default-args @var{command}} to show the current values of
+the default args for @var{command}.  For example:
+@smallexample
+(@value{GDBP}) show default-args backtrace
+default-args backtrace = -entry-values no -frame-arguments all
+(@value{GDBP}) show default-args break
+default-args break = <no default args>
+@end smallexample
+
+To show all the commands and aliases that have some default args configured,
+use the command
+@code{show default-args} without giving a @var{command} argument. 
+
+@item set enable-default-args @r{[}on|off@r{]}
+@itemx show enable-default-args
+By default, @value{GDBN} will use the configured default args.  This
+can be disabled using @code{set enable-default-args off}.  The default
+args of all commands are not cleared by @code{set enable-default-args
+off}, but will not be used till you do @code{set enable-default-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 default args.
+
+@end table
+
 @node Help
 @section Getting Help
 @cindex online documentation
@@ -27500,7 +27624,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} [DEFAULT-ARGS...]
 
 @end table
 
@@ -27518,6 +27642,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{default-args} for your alias.
+These @var{default-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{default-args}, see @ref{Command default args,
+,Automatically prepend default 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
-- 
2.20.1


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

* Re: [RFAv5 3/3] NEWS and documentation for default-args related concept and commands.
  2020-03-07 13:14 ` [RFAv5 3/3] NEWS and documentation for default-args related concept and commands Philippe Waroquiers
@ 2020-03-07 14:37   ` Eli Zaretskii
  0 siblings, 0 replies; 10+ messages in thread
From: Eli Zaretskii @ 2020-03-07 14:37 UTC (permalink / raw)
  To: Philippe Waroquiers; +Cc: gdb-patches

> From: Philippe Waroquiers <philippe.waroquiers@skynet.be>
> Date: Sat,  7 Mar 2020 14:14:28 +0100
> 
> gdb/ChangeLog
> YYYY-MM-DD  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
> 
> 	* NEWS: Mention new default-args commands.  Mention change
> 	to the alias command.
> 
> gdb/doc/ChangeLog
> YYYY-MM-DD  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
> 
> 	* gdb.texinfo (Command default args): New node documenting
> 	'set|show default-args' and 'set|show enable-default-args'.
> 	(Aliases): Document the new 'DEFAULT-ARGS...' option.

This is OK, but ...

> +For more information about @var{default-args}, see @ref{Command default args,
> +,Automatically prepend default arguments to commands and aliases}

That cross-reference needs a period after the right brace.

Thanks.

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

* PING. Re: [RFAv5 0/3] Allow the user to define default args for commands and aliases
  2020-03-07 13:14 [RFAv5 0/3] Allow the user to define default args for commands and aliases Philippe Waroquiers
                   ` (2 preceding siblings ...)
  2020-03-07 13:14 ` [RFAv5 3/3] NEWS and documentation for default-args related concept and commands Philippe Waroquiers
@ 2020-03-15 13:14 ` Philippe Waroquiers
  2020-03-22 18:05   ` PING^2. " Philippe Waroquiers
  3 siblings, 1 reply; 10+ messages in thread
From: Philippe Waroquiers @ 2020-03-15 13:14 UTC (permalink / raw)
  To: gdb-patches

Any additional comments ?

Thanks

Philippe


On Sat, 2020-03-07 at 14:14 +0100, Philippe Waroquiers wrote:
> Allow the user to define default args for commands and aliases.
> 
> This patch series implements, tests and documents the following commands:
> 
>   set default-args COMMAND [DEFAULT-ARGS...]
>   show default-args [COMMAND]
>   set enable-default-args [on|off]
>   show enable-default-args
> 
> 
> It also changes the alias command to be:
>   alias [-a] [--] ALIAS = COMMAND [DEFAULT-ARGS...]
> 
> 
> Using the above default-args commands and arguments, you can
> define default arguments for commands or define powerful aliases.
> 
> For example:
> 
>   alias bt_ALL = backtrace -entry-values both -frame-arg all -past-main -past-entry -full
> 
> defines the alias bt_ALL that will give as much information as possible
> in a backtrace.
> 
> Default args can usefully be combined with the 'with' command, such as:
> 
> Make "wLapPeu" an alias of 2 nested "with":
>   alias wLapPeu = with language pascal -- with print elements unlimited --
> 
> or have an alias pp10 to pretty print an expression with a maximum of
> 10 elements:
> 
>   alias pp10 = with print pretty -- with print elem 10 -- print
> 
> This patch series also adds a completer for 'alias'.
> 
> 
> This is the version 5 of the patch series.
> Compared the version 4, the changes are handling the comments of
> Christian and Eli:
>   * Declarations are moved close to their first use.
>   * strchr (text, '='); used instead of strstr.
>   * More consistent use of nullptr instead of NULL
>   * std::string default_args used instead of const char *default_args
>   * Updated/clarified NEWS and gdb.texinfo, as commented by Eli.
> 
> Previous versions handled various comments of Pedro and Tom.
> 
> For what concerns changing 'alias -a' to 'alias -abbreviation":
> This can for sure be done (and be backward compatible).  This can however
> be done as a separate patch (I still also need to do a similar change
> for the 'qcs' flags).
> 
> Note 1: a preliminary version of this idea (using a command called
> 'add-args') was discussed in
> https://sourceware.org/ml/gdb-patches/2019-06/msg00395.html
> where Tom suggested to make it more GDB like, using 'set' command.
> 
> Note 2: Following another comment of Tom, there is no '=' character
> to separate COMMAND from its default args.
> If ever this would be ambiguous in some cases, we could introduce
> an optional '=' character to separate COMMAND from its DEFAULT-ARGS.
> Similarly, the alias command has no separator between COMMAND
> and its DEFAULT-ARGS.
> 
> 
> 


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

* Re: PING^2. Re: [RFAv5 0/3] Allow the user to define default args for commands and aliases
  2020-03-15 13:14 ` PING. Re: [RFAv5 0/3] Allow the user to define default args for commands and aliases Philippe Waroquiers
@ 2020-03-22 18:05   ` Philippe Waroquiers
  2020-03-29 13:45     ` PING^3. " Philippe Waroquiers
  0 siblings, 1 reply; 10+ messages in thread
From: Philippe Waroquiers @ 2020-03-22 18:05 UTC (permalink / raw)
  To: gdb-patches

Ping^2?

Note that this series went under several review cycles since August last year.
So I would assume it is now reasonably close to be ready to be pushed

thanks
Philippe



On Sun, 2020-03-15 at 14:14 +0100, Philippe Waroquiers via Gdb-patches wrote:
> Any additional comments ?
> 
> Thanks
> 
> Philippe
> 
> 
> On Sat, 2020-03-07 at 14:14 +0100, Philippe Waroquiers wrote:
> > Allow the user to define default args for commands and aliases.
> > 
> > This patch series implements, tests and documents the following commands:
> > 
> >   set default-args COMMAND [DEFAULT-ARGS...]
> >   show default-args [COMMAND]
> >   set enable-default-args [on|off]
> >   show enable-default-args
> > 
> > 
> > It also changes the alias command to be:
> >   alias [-a] [--] ALIAS = COMMAND [DEFAULT-ARGS...]
> > 
> > 
> > Using the above default-args commands and arguments, you can
> > define default arguments for commands or define powerful aliases.
> > 
> > For example:
> > 
> >   alias bt_ALL = backtrace -entry-values both -frame-arg all -past-main -past-entry -full
> > 
> > defines the alias bt_ALL that will give as much information as possible
> > in a backtrace.
> > 
> > Default args can usefully be combined with the 'with' command, such as:
> > 
> > Make "wLapPeu" an alias of 2 nested "with":
> >   alias wLapPeu = with language pascal -- with print elements unlimited --
> > 
> > or have an alias pp10 to pretty print an expression with a maximum of
> > 10 elements:
> > 
> >   alias pp10 = with print pretty -- with print elem 10 -- print
> > 
> > This patch series also adds a completer for 'alias'.
> > 
> > 
> > This is the version 5 of the patch series.
> > Compared the version 4, the changes are handling the comments of
> > Christian and Eli:
> >   * Declarations are moved close to their first use.
> >   * strchr (text, '='); used instead of strstr.
> >   * More consistent use of nullptr instead of NULL
> >   * std::string default_args used instead of const char *default_args
> >   * Updated/clarified NEWS and gdb.texinfo, as commented by Eli.
> > 
> > Previous versions handled various comments of Pedro and Tom.
> > 
> > For what concerns changing 'alias -a' to 'alias -abbreviation":
> > This can for sure be done (and be backward compatible).  This can however
> > be done as a separate patch (I still also need to do a similar change
> > for the 'qcs' flags).
> > 
> > Note 1: a preliminary version of this idea (using a command called
> > 'add-args') was discussed in
> > https://sourceware.org/ml/gdb-patches/2019-06/msg00395.html
> > where Tom suggested to make it more GDB like, using 'set' command.
> > 
> > Note 2: Following another comment of Tom, there is no '=' character
> > to separate COMMAND from its default args.
> > If ever this would be ambiguous in some cases, we could introduce
> > an optional '=' character to separate COMMAND from its DEFAULT-ARGS.
> > Similarly, the alias command has no separator between COMMAND
> > and its DEFAULT-ARGS.
> > 
> > 
> > 


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

* Re: PING^3. Re: [RFAv5 0/3] Allow the user to define default args for commands and aliases
  2020-03-22 18:05   ` PING^2. " Philippe Waroquiers
@ 2020-03-29 13:45     ` Philippe Waroquiers
  0 siblings, 0 replies; 10+ messages in thread
From: Philippe Waroquiers @ 2020-03-29 13:45 UTC (permalink / raw)
  To: gdb-patches

If there are some comments, I have long week-ends at home to handle them :).
Thanks
Philippe

On Sun, 2020-03-22 at 19:05 +0100, Philippe Waroquiers via Gdb-patches wrote:
> Ping^2?
> 
> Note that this series went under several review cycles since August last year.
> So I would assume it is now reasonably close to be ready to be pushed
> 
> thanks
> Philippe
> 
> 
> 
> On Sun, 2020-03-15 at 14:14 +0100, Philippe Waroquiers via Gdb-patches wrote:
> > Any additional comments ?
> > 
> > Thanks
> > 
> > Philippe
> > 
> > 
> > On Sat, 2020-03-07 at 14:14 +0100, Philippe Waroquiers wrote:
> > > Allow the user to define default args for commands and aliases.
> > > 
> > > This patch series implements, tests and documents the following commands:
> > > 
> > >   set default-args COMMAND [DEFAULT-ARGS...]
> > >   show default-args [COMMAND]
> > >   set enable-default-args [on|off]
> > >   show enable-default-args
> > > 
> > > 
> > > It also changes the alias command to be:
> > >   alias [-a] [--] ALIAS = COMMAND [DEFAULT-ARGS...]
> > > 
> > > 
> > > Using the above default-args commands and arguments, you can
> > > define default arguments for commands or define powerful aliases.
> > > 
> > > For example:
> > > 
> > >   alias bt_ALL = backtrace -entry-values both -frame-arg all -past-main -past-entry -full
> > > 
> > > defines the alias bt_ALL that will give as much information as possible
> > > in a backtrace.
> > > 
> > > Default args can usefully be combined with the 'with' command, such as:
> > > 
> > > Make "wLapPeu" an alias of 2 nested "with":
> > >   alias wLapPeu = with language pascal -- with print elements unlimited --
> > > 
> > > or have an alias pp10 to pretty print an expression with a maximum of
> > > 10 elements:
> > > 
> > >   alias pp10 = with print pretty -- with print elem 10 -- print
> > > 
> > > This patch series also adds a completer for 'alias'.
> > > 
> > > 
> > > This is the version 5 of the patch series.
> > > Compared the version 4, the changes are handling the comments of
> > > Christian and Eli:
> > >   * Declarations are moved close to their first use.
> > >   * strchr (text, '='); used instead of strstr.
> > >   * More consistent use of nullptr instead of NULL
> > >   * std::string default_args used instead of const char *default_args
> > >   * Updated/clarified NEWS and gdb.texinfo, as commented by Eli.
> > > 
> > > Previous versions handled various comments of Pedro and Tom.
> > > 
> > > For what concerns changing 'alias -a' to 'alias -abbreviation":
> > > This can for sure be done (and be backward compatible).  This can however
> > > be done as a separate patch (I still also need to do a similar change
> > > for the 'qcs' flags).
> > > 
> > > Note 1: a preliminary version of this idea (using a command called
> > > 'add-args') was discussed in
> > > https://sourceware.org/ml/gdb-patches/2019-06/msg00395.html
> > > where Tom suggested to make it more GDB like, using 'set' command.
> > > 
> > > Note 2: Following another comment of Tom, there is no '=' character
> > > to separate COMMAND from its default args.
> > > If ever this would be ambiguous in some cases, we could introduce
> > > an optional '=' character to separate COMMAND from its DEFAULT-ARGS.
> > > Similarly, the alias command has no separator between COMMAND
> > > and its DEFAULT-ARGS.
> > > 
> > > 
> > > 


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

* Re: [RFAv5 1/3] default-args: allow to define default command/alias arguments
  2020-03-07 13:14 ` [RFAv5 1/3] default-args: allow to define default command/alias arguments Philippe Waroquiers
@ 2020-03-29 15:29   ` Simon Marchi
  2020-03-30  2:14   ` Simon Marchi
  1 sibling, 0 replies; 10+ messages in thread
From: Simon Marchi @ 2020-03-29 15:29 UTC (permalink / raw)
  To: Philippe Waroquiers, gdb-patches

Hi Philippe,

Just some code style stuff.  No need to send a new version just for that,
just integrate the changes locally if possible.

On 2020-03-07 8:14 a.m., Philippe Waroquiers wrote:
> @@ -1582,6 +1716,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;

 = false

> +};
> +
> +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

Remove `inline` here.

> @@ -1739,19 +1939,29 @@ 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);

alias_cmd != nullptr

> @@ -2299,6 +2509,27 @@ You can supply a command number to start with, or a `+' to start after\n\
>  the previous command number shown."),
>  	   &showlist);
>  
> +  c = add_cmd ("default-args", class_support, set_default_args_command, _("\
> +Set or clear default args automatically prepended to the explicitely\n\

explicitely -> explicitly

> +provided list of arguments of a command or alias.\n\
> +Usage: set default-args COMMAND [DEFAULT-ARGS...]\n\
> +Set or clear the default arguments automatically prepended\n\
> +to the list of arguments the user explicitely provides when COMMAND is run.\n\

explicitely -> explicitly

> @@ -586,15 +593,26 @@ 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, "", &default_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 (!default_args.empty () && enable_default_args_var)
> +	{
> +	  if (*p)

if (*p != '\0')

> +	    default_args_and_arg = default_args + ' ' + p;
> +	  else
> +	    default_args_and_arg = default_args;
> +	  arg = default_args_and_arg.c_str ();
> +	}
> +      else
> +	{
> +	  /* Pass null arg rather than an empty one.  */
> +	  arg = *p ? p : 0;

arg = *p != '\0' ? p : nullptr;

Simon

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

* Re: [RFAv5 1/3] default-args: allow to define default command/alias arguments
  2020-03-07 13:14 ` [RFAv5 1/3] default-args: allow to define default command/alias arguments Philippe Waroquiers
  2020-03-29 15:29   ` Simon Marchi
@ 2020-03-30  2:14   ` Simon Marchi
  1 sibling, 0 replies; 10+ messages in thread
From: Simon Marchi @ 2020-03-30  2:14 UTC (permalink / raw)
  To: Philippe Waroquiers, gdb-patches

On 2020-03-07 8:14 a.m., Philippe Waroquiers wrote:
> Currently, a user can define an alias, but cannot have default
> arguments for this alias.
> 
> This patch provides the following:
> 
> * A new command 'set default-args' that defines default args
>   to prepend to the list of arguments explicitely given by the user.
>   Note that default args can be used for an alias and nicely
>   combine nested "with" (see below the changes for the alias command).
> 
>         (gdb) help set default-args
>         Set or clear default args automatically prepended to the explicitely
>         provided list of arguments of a command or alias.
>         Usage: set default-args COMMAND [DEFAULT-ARGS...]
>         Set or clear the default arguments automatically prepended
>         to the list of arguments the user explicitely provides when COMMAND is run.
>         Note that COMMAND can be an alias.  Commands and their aliases
>         do not share their default arguments, so you can specify different
>         default arguments for a command and for each of its aliases.
>         Without DEFAULT-ARGS..., clears COMMAND default arguments.
> 
>   Note that 'set default-args' command has a completer to help typing
>   COMMAND and its default-args.
> 
> * A new command 'show default-args'.
> 
>         (gdb) help show default-args
>         Show the default args of a command, or of all commands.
>         Usage: show default-args [COMMAND]
>         Show the default args of COMMAND.  Without COMMAND, show the default args
>         of all commands.
> 
> * The 'alias' command is modified so as to directly accept default-args.
> 
>         (gdb) help alias
>         Define a new command that is an alias of an existing command.
>         Usage: alias [-a] [--] ALIAS = COMMAND [DEFAULT-ARGS...]
>         ALIAS is the name of the alias command to create.
>         COMMAND is the command being aliased to.
> 
>         Options:
>           -a
>             Specify that ALIAS is an abbreviation of COMMAND.
>             Abbreviations are not shown in command lists displayed by the 'help' command.
>         You can optionally provide DEFAULT-ARGS to define at the same time
>         ALIAS and its default args.  This is the equivalent of:
>           alias ALIAS = COMMAND
>           set default-args ALIAS DEFAULT-ARGS...
> 
>         Examples:
>         Make "spe" an alias of "set print elements":
>           alias spe set print elements
>         Make "elms" an alias of "elements" in the "set print" command:
>           alias -a set print elms set print elements
>         Make "btf" an alias of "backtrace -full -past-entry -past-main" :
>           alias btf = backtrace -full -past-entry -past-main
>         Make "wLapPeu" an alias of 2 nested "with":
>           alias wLapPeu = with language pascal -- with print elements unlimited --
> 
> * 'alias' command now has a completer that helps to complete:
>      - ALIAS (if the user defines an alias after a prefix),
>      - the aliased COMMAND
>      - the possible options for the aliased COMMAND.
> 
> * A new setting 'set enable-default-args'.  This can be used if the
>   user wants to temporarily disable the usage of default args.
>   'show enable-default-args' shows the value of 'enable-default-args'.
>   The main intended usage of this setting is to use it in the "with"
>   command: as 'set default-args' can add arguments to standard GDB commands,
>   it is useful (e.g. in user defined commands) to be able to go back
>   to the 'standard' behaviour of a command.

I have mentioned it to Philippe on IRC already, but I'll mention it here, so we can have
the discussion here instead of on IRC.

I think that to be able to add default arguments using the alias command is very useful.

I have a doubt about the "set default-args" command though, I am not convinced of its usefulness.
I'm thinking that if I want a specialized version of a command, I'll prefer to give it its own
unique name.

I think it can cause some confusing situations.  For example, before taking a look at the
implementation, I did this:

  (gdb) set default-args backtrace -past-main

Then, I instinctively used the bt command:

  (gdb) bt

and was surprised that the `-past-main` didn't apply.  I later realized that different aliases (even
the ones that come "built-in") don't share leading args.  It makes sense when looking at the implementation,
but in my user mind, `backtrace` and `bt` are the same and should behave the same.  We've been used to that
until now.

If the usefulness of that feature can be demonstrated, I'm not against it.  I just want to make sure that
it really adds value, since it comes with its maintenance burden and cognitive load for the user.

Simon

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

end of thread, other threads:[~2020-03-30  2:14 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-07 13:14 [RFAv5 0/3] Allow the user to define default args for commands and aliases Philippe Waroquiers
2020-03-07 13:14 ` [RFAv5 1/3] default-args: allow to define default command/alias arguments Philippe Waroquiers
2020-03-29 15:29   ` Simon Marchi
2020-03-30  2:14   ` Simon Marchi
2020-03-07 13:14 ` [RFAv5 2/3] Add tests for new default-args related commands and arguments Philippe Waroquiers
2020-03-07 13:14 ` [RFAv5 3/3] NEWS and documentation for default-args related concept and commands Philippe Waroquiers
2020-03-07 14:37   ` Eli Zaretskii
2020-03-15 13:14 ` PING. Re: [RFAv5 0/3] Allow the user to define default args for commands and aliases Philippe Waroquiers
2020-03-22 18:05   ` PING^2. " Philippe Waroquiers
2020-03-29 13:45     ` PING^3. " Philippe Waroquiers

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).