public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [RFAv6 0/3] Allow the user to define default args for aliases
@ 2020-05-16 17:19 Philippe Waroquiers
  2020-05-16 17:19 ` [RFAv6 1/3] default-args: allow to define default arguments " Philippe Waroquiers
                   ` (3 more replies)
  0 siblings, 4 replies; 11+ messages in thread
From: Philippe Waroquiers @ 2020-05-16 17:19 UTC (permalink / raw)
  To: gdb-patches

Allow the user to define default args for user-defined aliases.

This is version 6 of the patch series.
Compared to the previous version:
  * it handles the comment of Simon that default args should only
    be available for user-defined aliases and not for GDB commands
    and GDB pre-defined aliases.
    As default args are now only for user-defined aliases,
    the 'show/set enable-default-args [on|off]' commands have been
    removed.
  * documentation changed accordingly.
  * help and apropos now shows the full definition of the aliases having
    default args.

Previous versions handled the comments of Christian/Eli/Pedro/Tom/Simon.

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

  set default-args ALIAS [DEFAULT-ARGS...]
  show default-args [ALIAS]

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

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



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

* [RFAv6 1/3] default-args: allow to define default arguments for aliases
  2020-05-16 17:19 [RFAv6 0/3] Allow the user to define default args for aliases Philippe Waroquiers
@ 2020-05-16 17:19 ` Philippe Waroquiers
  2020-06-08 21:28   ` Simon Marchi
  2020-05-16 17:19 ` [RFAv6 2/3] Add tests for new default-args related commands and arguments Philippe Waroquiers
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 11+ messages in thread
From: Philippe Waroquiers @ 2020-05-16 17:19 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
  when using an alias.
  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 of an alias.
        Usage: set default-args ALIAS [DEFAULT-ARGS...]
        Set or clear the default arguments automatically prepended
        to the list of arguments the user explicitly provides when the user-defined
        ALIAS is run.
        The different aliases of a command do not share their default arguments:
        Each alias of a command can be configured with different values.
        Without DEFAULT-ARGS..., clears ALIAS default arguments.
        (gdb)

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

The way 'set default-args' is implemented makes it trivial to set default
args also for GDB commands (such as "backtrace") and for GDB pre-defined
aliases (such as "bt").  It was however deemed better to not allow to
define default arguments for pre-defined commands and aliases, to avoid
users believing that e.g. default args for "backtrace" would apply to "bt".
The default-args concept and related new commands are implemented in such
a way that if needed default args can be allowed for GDB predefined commands
and aliases without changing the user interface and with small code
changes.

* A new command 'show default-args'.

        (gdb) help show default-args
        Show the default args of an alias, or of all aliases.
        Usage: show default-args [ALIAS]
        Show the default args of ALIAS.  Without ALIAS, show the default args
        of all commands.

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

        (gdb) h 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.
        If "-a" is specified, the command is an abbreviation,
        and will not be used in command completion.

        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 --
        (gdb)

* '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.

* Help and apropos commands show the definitions of the aliases
  that have default arguments, e.g.
        (gdb) help backtrace
        backtrace, btf, where, bt
          alias btf = backtrace -full -past-entry -past-main
        Print backtrace of all stack frames, or innermost COUNT frames.
        Usage: backtrace [OPTION]... [QUALIFIER]... [COUNT | -COUNT]

        Options:
          -entry-values no|only|preferred|if-needed|both|compact|default
            Set printing of function arguments at function entry.
        ...

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.  Update aliases 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 under the layout
	  alias some_alias = some_aliased_cmd some_alias_default_arg.
	* 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 (execute_command): Prepend default_args if command has some.
	(set_verbose):
	Add NULL for new default_args lookup_cmd or  lookup_cmd_1 argument.
	* 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        | 328 ++++++++++++++++++++++++++++++++++----
 gdb/cli/cli-decode.c      | 135 +++++++++++++---
 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                 |  21 ++-
 gdb/tracepoint.c          |   6 +-
 15 files changed, 459 insertions(+), 79 deletions(-)

diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index eb6e32b046..7555b60d7a 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"
@@ -221,6 +222,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);
@@ -315,6 +317,150 @@ 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);
+
+  /* Currently, we only accept to set default args for user-defined aliases.
+     This is deemed to avoid some user confusion when e.g. setting
+     default args for the "backtrace" command but then wrongly expecting
+     the "bt" command (a predefined alias) to use the default args specified
+     for the "backtrace" command.  In other words, we assume the user is not
+     supposed to know the difference between a command and its predefined
+     aliases.  */
+  if (cmd->theclass != class_alias)
+    error (_("Default args can only be specified for user-defined aliases."));
+
+  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.  */
@@ -1541,7 +1687,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);
@@ -1573,6 +1719,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 = 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 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.
@@ -1607,7 +1818,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;
@@ -1625,7 +1836,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.  */
@@ -1633,8 +1844,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;
 
@@ -1645,24 +1861,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')
@@ -1718,6 +1928,8 @@ alias_command (const char *args, int from_tty)
   }
 
 
+  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
 
@@ -1730,8 +1942,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
     {
@@ -1751,19 +1963,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 != nullptr);
+  gdb_assert (alias_cmd->default_args.empty ());
+  if (default_args != nullptr)
+    {
+      default_args = skip_spaces (default_args);
+
+      alias_cmd->default_args = default_args;
     }
 }
 \f
@@ -1938,7 +2160,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 "
@@ -2128,7 +2350,7 @@ well documented as user commands."),
 	   &cmdlist);
   add_cmd ("obscure", class_obscure, _("Obscure features."), &cmdlist);
   add_cmd ("aliases", class_alias,
-	   _("Aliases of other commands."), &cmdlist);
+	   _("User-defined aliases of other commands."), &cmdlist);
   add_cmd ("user-defined", class_user, _("\
 User-defined commands.\n\
 The commands in this class are those defined by the user.\n\
@@ -2297,6 +2519,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 ("default-args", class_support, set_default_args_command, _("\
+Set or clear default args of an alias.\n\
+Usage: set default-args ALIAS [DEFAULT-ARGS...]\n\
+Set or clear the default arguments automatically prepended\n\
+to the list of arguments the user explicitly provides when the user-defined\n\
+ALIAS is run.\n\
+The different aliases of a command do not share their default arguments:\n\
+Each alias of a command can be configured with different values.\n\
+Without DEFAULT-ARGS..., clears ALIAS 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 an alias, or of all aliases.\n\
+Usage: show default-args [ALIAS]\n\
+Show the default args of ALIAS.  Without ALIAS, show the default args\n\
+of all aliases."),
+	   &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);
 
@@ -2448,19 +2690,39 @@ 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 be used in command completion.\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 a4ef93c62b..1568c4a96c 100644
--- a/gdb/cli/cli-decode.c
+++ b/gdb/cli/cli-decode.c
@@ -337,7 +337,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);
 }
@@ -1046,6 +1046,32 @@ fput_command_name_styled (struct cmd_list_element *c, struct ui_file *stream)
    If one or more names are printed, POSTFIX is printed after the last name.
 */
 
+/* Print the definition of alias C using title style for alias
+   and aliased command.  */
+
+static void
+fput_alias_definition_styled (struct cmd_list_element *c, struct ui_file *stream)
+{
+  gdb_assert (c->cmd_pointer != nullptr);
+  fputs_filtered ("  alias ", stream);
+  fput_command_name_styled (c, stream);
+  fprintf_filtered (stream, " = ");
+  fput_command_name_styled (c->cmd_pointer, stream);
+  fprintf_filtered (stream, " %s\n", c->default_args.c_str ());
+}
+
+/* Print the definition of the aliases of CMD that have default args.  */
+
+static void
+fput_aliases_definition_styled (struct cmd_list_element *cmd, struct ui_file *stream)
+{
+  if (cmd->aliases != nullptr)
+    for (cmd_list_element *iter = cmd->aliases; iter; iter = iter->alias_chain)
+      if (!iter->default_args.empty ())
+	fput_alias_definition_styled (iter, stream);
+}
+
+
 static void
 fput_command_names_styled (struct cmd_list_element *c,
 			   bool always_fput_c_name, const char *postfix,
@@ -1081,12 +1107,21 @@ print_doc_of_command (struct cmd_list_element *c, const char *prefix,
   if (verbose)
     fputs_filtered ("\n", stream);
 
-  fput_command_names_styled (c, true, " -- ", stream);
+  fput_command_names_styled (c, true,
+			     verbose ? "" : " -- ", stream);
   if (verbose)
-    fputs_highlighted (c->doc, highlight, stream);
+    {
+      fputs_filtered ("\n", stream);
+      fput_aliases_definition_styled (c, stream);
+      fputs_highlighted (c->doc, highlight, stream);
+      fputs_filtered ("\n", stream);
+    }
   else
-    print_doc_line (stream, c->doc, false);
-  fputs_filtered ("\n", stream);
+    {
+      print_doc_line (stream, c->doc, false);
+      fputs_filtered ("\n", stream);
+      fput_aliases_definition_styled (c, stream);
+    }
 }
 
 /* Recursively walk the commandlist structures, and print out the
@@ -1183,7 +1218,7 @@ help_cmd (const char *command, struct ui_file *stream)
     }
 
   const char *orig_command = command;
-  c = lookup_cmd (&command, cmdlist, "", 0, 0);
+  c = lookup_cmd (&command, cmdlist, "", NULL, 0, 0);
 
   if (c == 0)
     return;
@@ -1205,9 +1240,43 @@ help_cmd (const char *command, struct ui_file *stream)
   /* If the user asked 'help somecommand' and there is no alias,
      the false indicates to not output the (single) command name.  */
   fput_command_names_styled (c, false, "\n", stream);
+  fput_aliases_definition_styled (c, 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 the
+	 lookup_cmd_composition result to find if help was requested for an
+	 alias.  In this case, rather print the alias default_args.  */
+
+      const char *name;
+      std::string default_args;
+
+      gdb_assert (c_cmd != nullptr);
+      gdb_assert (c_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");
@@ -1341,7 +1410,7 @@ help_all (struct ui_file *stream)
 	      fprintf_filtered (stream, "\nUnclassified commands\n\n");
 	      seen_unclassified = 1;
 	    }
-	  print_help_for_command (c, 1, stream);
+	  print_help_for_command (c, true, stream);
 	}
     }
 
@@ -1399,6 +1468,9 @@ print_help_for_command (struct cmd_list_element *c,
   fput_command_names_styled (c, true, " -- ", stream);
   print_doc_line (stream, c->doc, false);
   fputs_filtered ("\n", stream);
+  if (!c->default_args.empty ())
+    fput_alias_definition_styled (c, stream);
+  fput_aliases_definition_styled (c, stream);
 
   if (recurse
       && c->prefixlist != 0
@@ -1582,8 +1654,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.
@@ -1610,11 +1686,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')
@@ -1646,10 +1724,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.  */
     }
 
@@ -1665,22 +1745,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)
@@ -1688,13 +1776,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
@@ -1705,8 +1796,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;
     }
 }
@@ -1726,8 +1819,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,
@@ -1741,6 +1839,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;
@@ -1752,7 +1851,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 f4719bfac4..f855ee5724 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 04a380cba4..39d48a6c2f 100644
--- a/gdb/command.h
+++ b/gdb/command.h
@@ -291,11 +291,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 d03dc77c65..cd077097dc 100644
--- a/gdb/completer.c
+++ b/gdb/completer.c
@@ -1385,7 +1385,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 32905a7b59..40e46db396 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -3178,7 +3178,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_run, 0, &cmdlist);
 
@@ -3191,7 +3191,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);
 
@@ -3210,7 +3210,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 3c1c566b0a..760208f52b 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 812ab8bc1b..ae9b177f2b 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -14425,10 +14425,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 c62eb57695..da9b805b47 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -579,6 +579,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 +588,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 ())
+	{
+	  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 == '\0' ? nullptr : p;
+	}
 
       /* FIXME: cagney/2002-02-02: The c->type test is pretty dodgy
          while the is_complete_command(cfunc) test is just plain
@@ -1957,7 +1970,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)
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index f4a208f616..00b7059be5 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] 11+ messages in thread

* [RFAv6 2/3] Add tests for new default-args related commands and arguments.
  2020-05-16 17:19 [RFAv6 0/3] Allow the user to define default args for aliases Philippe Waroquiers
  2020-05-16 17:19 ` [RFAv6 1/3] default-args: allow to define default arguments " Philippe Waroquiers
@ 2020-05-16 17:19 ` Philippe Waroquiers
  2020-05-16 17:19 ` [RFAv6 3/3] NEWS and documentation for default-args related concept and commands Philippe Waroquiers
  2020-05-24 18:53 ` [RFAv6 0/3] Allow the user to define default args for aliases Philippe Waroquiers
  3 siblings, 0 replies; 11+ messages in thread
From: Philippe Waroquiers @ 2020-05-16 17:19 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-args.c: New file.
	* gdb.base/alias.exp: Update expected error msg for alias foo=bar.
	* gdb.base/default.exp: Update to new help text and
	make test names unique.
	* gdb.base/help.exp: Likewise.
	* gdb.base/page.exp: Likewise.
	* gdb.base/style.exp: Likewise.
	* gdb.guile/guile.exp: Likewise.
	* gdb.python/python.exp: Likewise.
---
 gdb/testsuite/gdb.base/alias.exp        |   2 +-
 gdb/testsuite/gdb.base/default-args.c   |  41 ++++++++
 gdb/testsuite/gdb.base/default-args.exp | 124 ++++++++++++++++++++++++
 gdb/testsuite/gdb.base/default.exp      |   4 +-
 gdb/testsuite/gdb.base/help.exp         |   2 +-
 gdb/testsuite/gdb.base/page.exp         |   4 +-
 gdb/testsuite/gdb.base/style.exp        |   8 +-
 gdb/testsuite/gdb.guile/guile.exp       |   5 +-
 gdb/testsuite/gdb.python/python.exp     |  37 +++----
 9 files changed, 198 insertions(+), 29 deletions(-)
 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 6993d42648..03c440dfd7 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..e0f423404c
--- /dev/null
+++ b/gdb/testsuite/gdb.base/default-args.exp
@@ -0,0 +1,124 @@
+# 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 --" \
+	"show default-args PP = print -pretty --"
+    gdb_test "PP g_s" \
+	[multi_line  \
+	     " = {" \
+	     "  a = 1," \
+	     "  b = 2," \
+	     "  c = 3" \
+	     "}"]
+
+    # 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" ] \
+	"show default-args"
+
+    # Clear the default-args of "PP".
+    gdb_test_no_output "set default-args PP" "clear PP default-args"
+    gdb_test "show default-args PP" "default-args PP = <no default args>"
+    gdb_test "PP g_s" " = {a = 1, b = 2, c = 3}" "simple PP print"
+
+}
+
+# Check errors.
+with_test_prefix "errors" {
+    # Verify we cannot set default args for commands and pre-defined aliases.
+    gdb_test "set default-args backtrace -full" \
+	"Default args can only be specified for user-defined aliases\\."
+
+    
+    # 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"
+
+}
diff --git a/gdb/testsuite/gdb.base/default.exp b/gdb/testsuite/gdb.base/default.exp
index c34bb9a92a..ac1a0f5b6e 100644
--- a/gdb/testsuite/gdb.base/default.exp
+++ b/gdb/testsuite/gdb.base/default.exp
@@ -247,9 +247,9 @@ gdb_test_multiple "generate-core-file" "generate-core-file" {
 }
 
 #test help "h" abbreviation
-gdb_test "h" "List of classes of commands:(\[^\r\n\]*\[\r\n\])+aliases -- Aliases of other commands(\[^\r\n\]*\[\r\n\])+breakpoints -- Making program stop at certain points(\[^\r\n\]*\[\r\n\])+data -- Examining data(\[^\r\n\]*\[\r\n\])+files -- Specifying and examining files(\[^\r\n\]*\[\r\n\])+obscure -- Obscure features(\[^\r\n\]*\[\r\n\])+running -- Running the program(\[^\r\n\]*\[\r\n\])+stack -- Examining the stack(\[^\r\n\]*\[\r\n\])+status -- Status inquiries(\[^\r\n\]*\[\r\n\])+support -- Support facilities(\[^\r\n\]*\[\r\n\])+user-defined -- User-defined commands(\[^\r\n\]*\[\r\n\])+Type \"help\" followed by a class name for a list of commands in that class.(\[^\r\n\]*\[\r\n\])+Type \"help\" followed by command name for full documentation.(\[^\r\n\]*\[\r\n\])+Command name abbreviations are allowed if unambiguous." "help \"h\" abbreviation"
+gdb_test "h" "List of classes of commands:(\[^\r\n\]*\[\r\n\])+aliases -- User-defined aliases of other commands(\[^\r\n\]*\[\r\n\])+breakpoints -- Making program stop at certain points(\[^\r\n\]*\[\r\n\])+data -- Examining data(\[^\r\n\]*\[\r\n\])+files -- Specifying and examining files(\[^\r\n\]*\[\r\n\])+obscure -- Obscure features(\[^\r\n\]*\[\r\n\])+running -- Running the program(\[^\r\n\]*\[\r\n\])+stack -- Examining the stack(\[^\r\n\]*\[\r\n\])+status -- Status inquiries(\[^\r\n\]*\[\r\n\])+support -- Support facilities(\[^\r\n\]*\[\r\n\])+user-defined -- User-defined commands(\[^\r\n\]*\[\r\n\])+Type \"help\" followed by a class name for a list of commands in that class.(\[^\r\n\]*\[\r\n\])+Type \"help\" followed by command name for full documentation.(\[^\r\n\]*\[\r\n\])+Command name abbreviations are allowed if unambiguous." "help \"h\" abbreviation"
 #test help
-gdb_test "help" "List of classes of commands:(\[^\r\n\]*\[\r\n\])+aliases -- Aliases of other commands(\[^\r\n\]*\[\r\n\])+breakpoints -- Making program stop at certain points(\[^\r\n\]*\[\r\n\])+data -- Examining data(\[^\r\n\]*\[\r\n\])+files -- Specifying and examining files(\[^\r\n\]*\[\r\n\])+obscure -- Obscure features(\[^\r\n\]*\[\r\n\])+running -- Running the program(\[^\r\n\]*\[\r\n\])+stack -- Examining the stack(\[^\r\n\]*\[\r\n\])+status -- Status inquiries(\[^\r\n\]*\[\r\n\])+support -- Support facilities(\[^\r\n\]*\[\r\n\])+user-defined -- User-defined commands(\[^\r\n\]*\[\r\n\])+Type \"help\" followed by a class name for a list of commands in that class.(\[^\r\n\]*\[\r\n\])+Type \"help\" followed by command name for full documentation.(\[^\r\n\]*\[\r\n\])+Command name abbreviations are allowed if unambiguous."
+gdb_test "help" "List of classes of commands:(\[^\r\n\]*\[\r\n\])+aliases -- User-defined aliases of other commands(\[^\r\n\]*\[\r\n\])+breakpoints -- Making program stop at certain points(\[^\r\n\]*\[\r\n\])+data -- Examining data(\[^\r\n\]*\[\r\n\])+files -- Specifying and examining files(\[^\r\n\]*\[\r\n\])+obscure -- Obscure features(\[^\r\n\]*\[\r\n\])+running -- Running the program(\[^\r\n\]*\[\r\n\])+stack -- Examining the stack(\[^\r\n\]*\[\r\n\])+status -- Status inquiries(\[^\r\n\]*\[\r\n\])+support -- Support facilities(\[^\r\n\]*\[\r\n\])+user-defined -- User-defined commands(\[^\r\n\]*\[\r\n\])+Type \"help\" followed by a class name for a list of commands in that class.(\[^\r\n\]*\[\r\n\])+Type \"help\" followed by command name for full documentation.(\[^\r\n\]*\[\r\n\])+Command name abbreviations are allowed if unambiguous."
 #test handle
 gdb_test "handle" "Argument required .signal to handle.*"
 #test info "i" abbreviation 
diff --git a/gdb/testsuite/gdb.base/help.exp b/gdb/testsuite/gdb.base/help.exp
index 8ed0be45db..0b6893cf79 100644
--- a/gdb/testsuite/gdb.base/help.exp
+++ b/gdb/testsuite/gdb.base/help.exp
@@ -25,7 +25,7 @@ gdb_start
 gdb_test_no_output "set height 0" "disable pagination"
 
 # Test all the help classes.
-test_class_help "aliases" {"Aliases of other commands\.\[\r\n\]+"}
+test_class_help "aliases" {"User-defined aliases of other commands\.\[\r\n\]+"}
 test_class_help "breakpoints" {
     "Making program stop at certain points\.\[\r\n\]+"
 }
diff --git a/gdb/testsuite/gdb.base/page.exp b/gdb/testsuite/gdb.base/page.exp
index c34c886c64..5936845885 100644
--- a/gdb/testsuite/gdb.base/page.exp
+++ b/gdb/testsuite/gdb.base/page.exp
@@ -23,7 +23,7 @@ gdb_test "show pagination" "State of pagination is off.*" "pagination is off"
 gdb_test_sequence "help" "unpaged help" {
     "List of classes of commands:"
     ""
-    "aliases -- Aliases of other commands"
+    "aliases -- User-defined aliases of other commands"
     "breakpoints -- Making program stop at certain points"
     "data -- Examining data"
     "files -- Specifying and examining files"
@@ -50,7 +50,7 @@ gdb_expect_list "paged help" \
 	".*$pagination_prompt" {
     "List of classes of commands:"
     ""
-    "aliases -- Aliases of other commands"
+    "aliases -- User-defined aliases of other commands"
     "breakpoints -- Making program stop at certain points"
     "data -- Examining data"
     "files -- Specifying and examining files"
diff --git a/gdb/testsuite/gdb.base/style.exp b/gdb/testsuite/gdb.base/style.exp
index 129f1746a3..bfd26144fa 100644
--- a/gdb/testsuite/gdb.base/style.exp
+++ b/gdb/testsuite/gdb.base/style.exp
@@ -120,7 +120,7 @@ save_vars { env(TERM) } {
 	[multi_line \
 	     "List of classes of commands:" \
 	     "" \
-	     "${aliases_expr} -- Aliases of other commands\." \
+	     "${aliases_expr} -- User-defined aliases of other commands\." \
 	     "${breakpoints_expr} -- Making program stop at certain points\." \
 	     ".*" \
 	    ] \
@@ -132,11 +132,13 @@ save_vars { env(TERM) } {
     gdb_test "apropos -v cut for 'thre" \
 	[multi_line \
 	     "" \
-	     "${taas_expr} --.*" \
+	     "${taas_expr}" \
+	     "Apply a command to all .*" \
 	     "Usage:.*" \
 	     "short${cut_for_thre_expr}ad apply.*" \
 	     "" \
-	     "${tfaas_expr} --.*" \
+	     "${tfaas_expr}" \
+	     "Apply a command to all .*" \
 	     "Usage:.*" \
 	     "short${cut_for_thre_expr}ad apply.*" \
 	    ]
diff --git a/gdb/testsuite/gdb.guile/guile.exp b/gdb/testsuite/gdb.guile/guile.exp
index 2b0c0ba1d4..5d7b50fa15 100644
--- a/gdb/testsuite/gdb.guile/guile.exp
+++ b/gdb/testsuite/gdb.guile/guile.exp
@@ -58,11 +58,12 @@ gdb_test_multiline "multi-line guile command" \
   "(print 23)" "" \
   "end" "= 23"
 
+# To avoid duplicate test error, prefix one of the "end" with spaces.
 gdb_test_multiline "show guile command" \
   "define zzq" "Type commands for definition of .* just \"end\"\\.*" \
   "guile" "" \
   "(print 23)" "" \
-  "end" "" \
+  "                     end" "" \
   "end" "" \
   "show user zzq" "User command \"zzq\":.*  guile.*\\(print 23\\).*  end"
 
@@ -80,5 +81,5 @@ gdb_test "guile (print x)" "= 23"
 gdb_test_no_output "guile (define a (execute \"help\" #:to-string #t))" \
     "collect help from uiout"
 
-gdb_test "guile (print a)" "= .*aliases -- Aliases of other commands.*" \
+gdb_test "guile (print a)" "= .*aliases -- User-defined aliases of other commands.*" \
     "verify help to uiout"
diff --git a/gdb/testsuite/gdb.python/python.exp b/gdb/testsuite/gdb.python/python.exp
index a50a7b43e2..8045c666a3 100644
--- a/gdb/testsuite/gdb.python/python.exp
+++ b/gdb/testsuite/gdb.python/python.exp
@@ -77,11 +77,12 @@ with_test_prefix "python interactive help" {
     }
 }
 
+# To avoid duplicate test error, prefix one of the "end" with spaces.
 gdb_py_test_multiple "show python command" \
   "define zzq" "Type commands for definition of .* just \"end\"\\.*" \
   "python" "" \
   "print (23)" "" \
-  "end" "" \
+  "                     end" "" \
   "end" "" \
   "show user zzq" "User command \"zzq\":.*  python.*print \\(23\\).*  end"
 
@@ -187,7 +188,7 @@ gdb_test_no_output "set height 0"
 
 gdb_test_no_output "python a = gdb.execute('help', to_string=True)" "collect help from uiout"
 
-gdb_test "python print (a)" ".*aliases -- Aliases of other commands.*" "verify help to uiout"
+gdb_test "python print (a)" ".*aliases -- User-defined aliases of other commands.*" "verify help to uiout"
 
 # Test PR 12212, using InfThread.selected_thread() when no inferior is
 # loaded.
@@ -229,10 +230,10 @@ runto $lineno
 gdb_test "python gdb.decode_line(\"main.c:43\")" \
     "gdb.error: No source file named main.c.*" "test decode_line no source named main"
 
-gdb_py_test_silent_cmd "python symtab = gdb.decode_line()" "test decode_line current location" 1
-gdb_test "python print (len(symtab))" "2" "test decode_line current location"
-gdb_test "python print (symtab\[0\])" "None" "test decode_line expression parse"
-gdb_test "python print (len(symtab\[1\]))" "1" "test decode_line current location"
+gdb_py_test_silent_cmd "python symtab = gdb.decode_line()" "test decode_line current location =" 1
+gdb_test "python print (len(symtab))" "2" "test decode_line current location len"
+gdb_test "python print (symtab\[0\])" "None" "test decode_line expression parse None"
+gdb_test "python print (len(symtab\[1\]))" "1" "test decode_line current location len 1"
 
 # Test that decode_line with an empty string argument does not crash.
 gdb_py_test_silent_cmd "python symtab2 = gdb.decode_line('')" \
@@ -246,18 +247,18 @@ if { [is_remote host] } {
 gdb_test "python print (symtab\[1\]\[0\].symtab)" ".*${python_c}" "test decode_line current location filename"
 gdb_test "python print (symtab\[1\]\[0\].line)" "$lineno" "test decode_line current location line number"
 
-gdb_py_test_silent_cmd "python symtab = gdb.decode_line(\"python.c:26 if foo\")" "test decode_line python.c:26" 1
-gdb_test "python print (len(symtab))" "2" "test decode_line python.c:26 length"
+gdb_py_test_silent_cmd "python symtab = gdb.decode_line(\"python.c:26 if foo\")" "test decode_line python.c:26 decode" 1
+gdb_test "python print (len(symtab))" "2" "test decode_line python.c:26 length 2"
 gdb_test "python print (symtab\[0\])" "if foo" "test decode_line expression parse"
-gdb_test "python print (len(symtab\[1\]))" "1" "test decode_line python.c:26 length"
+gdb_test "python print (len(symtab\[1\]))" "1" "test decode_line python.c:26 length 1"
 gdb_test "python print (symtab\[1\]\[0\].symtab)" ".*${python_c}" "test decode_line python.c:26 filename"
 gdb_test "python print (symtab\[1\]\[0\].line)" "26" "test decode_line python.c:26 line number"
 
 gdb_test "python gdb.decode_line(\"randomfunc\")" \
     "gdb.error: Function \"randomfunc\" not defined.*" "test decode_line randomfunc"
 gdb_py_test_silent_cmd "python symtab = gdb.decode_line(\"func1\")" "test decode_line func1()" 1
-gdb_test "python print (len(symtab))" "2" "test decode_line func1 length"
-gdb_test "python print (len(symtab\[1\]))" "1" "test decode_line func1 length"
+gdb_test "python print (len(symtab))" "2" "test decode_line func1 length 2"
+gdb_test "python print (len(symtab\[1\]))" "1" "test decode_line func1 length 1"
 
 if { [is_remote host] } {
     set python_1_c [string_to_regexp "python-1.c"]
@@ -336,7 +337,7 @@ set testfake "testfake"
 
 gdb_test_multiple "python gdb.prompt_hook = prompt" "set the hook" {
     -re "\[\r\n\]$newprompt $" {
-	pass "set hook"
+	pass "set hook prompt"
     }
 }
 
@@ -395,7 +396,7 @@ gdb_test_multiple "end" "end programming" {
     }
 }
 
-gdb_py_test_multiple "prompt substitution readline" \
+gdb_py_test_multiple "prompt substitution readline import" \
   "python" "" \
   "import gdb.command.prompt" "" \
   "end" ""
@@ -449,7 +450,7 @@ gdb_test "show python print-stack" \
 gdb_py_test_silent_cmd "set python print-stack message" \
     "Test print-stack set setting to message" 1
 
-gdb_py_test_multiple "prompt substitution readline" \
+gdb_py_test_multiple "prompt substitution readline error_prompt" \
   "python" "" \
   "pCounter = 0" "" \
   "def error_prompt(current):" "" \
@@ -458,24 +459,24 @@ gdb_py_test_multiple "prompt substitution readline" \
 
 gdb_test_multiple "python gdb.prompt_hook = error_prompt" "set the hook" {
     -re "Python Exception (exceptions.RuntimeError|<(type 'exceptions.|class ')RuntimeError'>) Python exception called.*$gdb_prompt $" {
-	pass "set hook"
+	pass "set hook error_prompt"
     }
 }
 
 gdb_py_test_silent_cmd "python gdb.prompt_hook = None" \
-    "set the hook to default" 1
+    "set the hook to default 1" 1
 
 gdb_py_test_silent_cmd "set python print-stack full" \
     "set print-stack full for prompt error test" 1
 
 gdb_test_multiple "python gdb.prompt_hook = error_prompt" "set the hook" {
     -re "Traceback.*File.*line.*RuntimeError.*Python exception called.*$gdb_prompt $" {
-	pass "set hook"
+	pass "set hook error_prompt traceback"
     }
 }
 
 gdb_py_test_silent_cmd "python gdb.prompt_hook = None" \
-    "set the hook to default" 1
+    "set the hook to default 2" 1
 
 # Start with a fresh gdb.
 clean_restart ${testfile}
-- 
2.20.1


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

* [RFAv6 3/3] NEWS and documentation for default-args related concept and commands.
  2020-05-16 17:19 [RFAv6 0/3] Allow the user to define default args for aliases Philippe Waroquiers
  2020-05-16 17:19 ` [RFAv6 1/3] default-args: allow to define default arguments " Philippe Waroquiers
  2020-05-16 17:19 ` [RFAv6 2/3] Add tests for new default-args related commands and arguments Philippe Waroquiers
@ 2020-05-16 17:19 ` Philippe Waroquiers
  2020-05-16 17:49   ` Eli Zaretskii
  2020-05-24 18:53 ` [RFAv6 0/3] Allow the user to define default args for aliases Philippe Waroquiers
  3 siblings, 1 reply; 11+ messages in thread
From: Philippe Waroquiers @ 2020-05-16 17:19 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'.
	(Aliases): Document the new 'DEFAULT-ARGS...' option.
	(Help): Update help aliases text and describe when full alias
	definition is provided.
---
 gdb/NEWS            |  26 ++++++++
 gdb/doc/gdb.texinfo | 146 ++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 166 insertions(+), 6 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index a059fc7aa0..0c4ca5a74c 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -63,10 +63,36 @@ 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 ALIAS [DEFAULT-ARGS...]
+show default-args [ALIAS]
+  GDB can now automatically prepend default arguments to the argument list
+  provided explicitely by the user when using a user-defined alias.
+  This allows to define easily more specialised aliases.
+  For example, 'set default-args myownbt -full -frame-arguments all'
+  ensures that myownbt alias will automatically use the options -full
+  -frame-arguments all, without having to retype them for each myownbt
+  invocation.
+
 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 ALIAS [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 8f3301259a..20fc1ebc00 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 aliases default args::        Automatically prepend default arguments to user-defined aliases
 * Help::                        How to ask @value{GDBN} for help
 @end menu
 
@@ -1997,6 +1998,120 @@ uppercase.
 (For more on using the @code{print} command, see @ref{Data, ,Examining
 Data}.)
 
+@node Command aliases default args
+@section Automatically prepend default arguments to user-defined aliases
+
+You can tell @value{GDBN} to always prepend some default arguments to
+the list of arguments provided explicitely by the user when using a
+user-defined alias.
+
+@cindex command aliases options, automatically prepend
+@cindex command aliases, default arguments
+
+@table @code
+@kindex set default-args
+@item set default-args @var{alias} [@var{default-args@dots{}}]
+
+If you repeatedly use the same arguments or options for a command, you
+can define an alias for this command and tell @value{GDBN} to
+automatically prepend these arguments or options to the list of
+arguments you type explicitely when using the alias@footnote{@value{GDBN}
+could easily accept default arguments for pre-defined commands and aliases,
+but it was deemed this would be confusing, and so is not allowed.}.
+
+For example, if you often use the command @code{thread apply all}
+specifying to work 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}) alias thread apply asc-all = thread apply all
+(@value{GDBP}) set default-args thread apply asc-all -ascending -c
+@end smallexample
+
+Once you have set these default args, any time you type
+the @code{thread apply asc-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{alias}
+and @var{default-args}.
+
+The different aliases of a command do not share their default args.
+For example, you define a new alias @code{bt_ALL} showing all possible
+information and another alias @code{bt_SMALL} showing very limited information
+using:
+@smallexample
+(@value{GDBP}) alias bt_ALL = backtrace
+(@value{GDBP}) set default-args bt_ALL -entry-values both -frame-arg all \
+   -past-main -past-entry -full
+(@value{GDBP}) alias bt_SMALL = backtrace
+(@value{GDBP}) set default-args bt_SMALL -entry-values no -frame-arg none \
+   -past-main off -past-entry off
+@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 lists 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{alias}} (without giving @var{default-args})
+to clear the default args of @var{alias}.
+
+@item show default-args [@var{alias}]
+
+Use @code{show default-args @var{alias}} to show the current values of
+the default args for @var{alias}.  For example:
+@smallexample
+(@value{GDBP}) show default-args bt_ALL
+default-args bt_ALL = -entry-values no -frame-arguments all
+(@value{GDBP}) show default-args mybt
+default-args mybt = <no default args>
+@end smallexample
+
+To show all the aliases that have some default args configured,
+use the command
+@code{show default-args} without giving the @var{alias} argument. 
+
+@end table
+
 @node Help
 @section Getting Help
 @cindex online documentation
@@ -2016,7 +2131,7 @@ display a short list of named classes of commands:
 (@value{GDBP}) help
 List of classes of commands:
 
-aliases -- Aliases of other commands
+aliases -- User-defined aliases of other commands
 breakpoints -- Making program stop at certain points
 data -- Examining data
 files -- Specifying and examining files
@@ -2043,8 +2158,9 @@ Command name abbreviations are allowed if unambiguous.
 Using one of the general help classes as an argument, you can get a
 list of the individual commands in that class.  If a command has
 aliases, the aliases are given after the command name, separated by
-commas.  For example, here is the help display for the class
-@code{status}:
+commas.  If an alias has default arguments, the full definition of
+the alias is given after the first line.
+For example, here is the help display for the class @code{status}:
 
 @smallexample
 (@value{GDBP}) help status
@@ -2056,7 +2172,10 @@ List of commands:
 @c to fit in smallbook page size.
 info, inf, i -- Generic command for showing things
         about the program being debugged
-info address -- Describe where symbol SYM is stored.
+info address, iamain  -- Describe where symbol SYM is stored.
+  alias iamain = info address main
+info all-registers -- List of all registers and their contents,
+        for selected stack frame.
 ...
 show, info set -- Generic command for showing things
         about the debugger
@@ -2072,6 +2191,8 @@ With a command name as @code{help} argument, @value{GDBN} displays a
 short paragraph on how to use that command.  If that command has
 one or more aliases, @value{GDBN} will display a first line with
 the command name and all its aliases separated by commas.
+This first line will be followed by the full definition of all aliases
+having default arguments.
 
 @kindex apropos
 @item apropos [-v] @var{regexp}
@@ -2092,7 +2213,7 @@ results in:
 @smallexample
 @group
 alias -- Define a new command that is an alias of an existing command
-aliases -- Aliases of other commands
+aliases -- User-defined aliases of other commands
 @end group
 @end smallexample
 
@@ -27503,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
 
@@ -27520,6 +27641,19 @@ of the command.  Abbreviations are not used in command completion.
 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 aliases default args,
+,Automatically prepend default arguments to user-defined 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] 11+ messages in thread

* Re: [RFAv6 3/3] NEWS and documentation for default-args related concept and commands.
  2020-05-16 17:19 ` [RFAv6 3/3] NEWS and documentation for default-args related concept and commands Philippe Waroquiers
@ 2020-05-16 17:49   ` Eli Zaretskii
  0 siblings, 0 replies; 11+ messages in thread
From: Eli Zaretskii @ 2020-05-16 17:49 UTC (permalink / raw)
  To: Philippe Waroquiers; +Cc: gdb-patches

> Date: Sat, 16 May 2020 19:19:47 +0200
> From: Philippe Waroquiers via Gdb-patches <gdb-patches@sourceware.org>
> 
> gdb/ChangeLog
> YYYY-MM-DD  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
> 
> 	* NEWS: Mention new default-args commands.  Mention change
> 	to the alias command.

This part is OK.

> +You can tell @value{GDBN} to always prepend some default arguments to
> +the list of arguments provided explicitely by the user when using a
                                  ^^^^^^^^^^^
"explicitly"

OK with these nits fixed.

Thanks.

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

* Re: [RFAv6 0/3] Allow the user to define default args for aliases
  2020-05-16 17:19 [RFAv6 0/3] Allow the user to define default args for aliases Philippe Waroquiers
                   ` (2 preceding siblings ...)
  2020-05-16 17:19 ` [RFAv6 3/3] NEWS and documentation for default-args related concept and commands Philippe Waroquiers
@ 2020-05-24 18:53 ` Philippe Waroquiers
  3 siblings, 0 replies; 11+ messages in thread
From: Philippe Waroquiers @ 2020-05-24 18:53 UTC (permalink / raw)
  To: gdb-patches

Ping ?

Thanks
Philippe

On Sat, 2020-05-16 at 19:19 +0200, Philippe Waroquiers via Gdb-patches wrote:
> Allow the user to define default args for user-defined aliases.
> 
> This is version 6 of the patch series.
> Compared to the previous version:
>   * it handles the comment of Simon that default args should only
>     be available for user-defined aliases and not for GDB commands
>     and GDB pre-defined aliases.
>     As default args are now only for user-defined aliases,
>     the 'show/set enable-default-args [on|off]' commands have been
>     removed.
>   * documentation changed accordingly.
>   * help and apropos now shows the full definition of the aliases having
>     default args.
> 
> Previous versions handled the comments of Christian/Eli/Pedro/Tom/Simon.
> 
> This patch series implements, tests and documents the following commands:
> 
>   set default-args ALIAS [DEFAULT-ARGS...]
>   show default-args [ALIAS]
> 
> 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'.
> 
> 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).
> 
> 


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

* Re: [RFAv6 1/3] default-args: allow to define default arguments for aliases
  2020-05-16 17:19 ` [RFAv6 1/3] default-args: allow to define default arguments " Philippe Waroquiers
@ 2020-06-08 21:28   ` Simon Marchi
  2020-06-09 19:49     ` Philippe Waroquiers
  0 siblings, 1 reply; 11+ messages in thread
From: Simon Marchi @ 2020-06-08 21:28 UTC (permalink / raw)
  To: Philippe Waroquiers, gdb-patches

I don't remember if we talked about this earlier... but is this
the expected behavior when using an alias to define another alias?

(gdb) alias aaa = echo allo\n
(gdb) alias bbb = aaa bonjour\n
(gdb) aaa
allo
(gdb) bbb
bonjour
(gdb)

In other words, it's possible to use an alias in the definition of
another alias, but the default args of the first alias are ignored.
It's understandable when looking at the implementation, but is it
what users will expect?  The equivalent in the shell is different, so
I can imagine some users will be surprised:

$ alias aaa='echo allo'
$ alias bbb='aaa bonjour'
$ aaa
allo
$ bbb
allo bonjour

> @@ -315,6 +317,150 @@ 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."));

This should say ALIAS, since it says ALIAS in "help set default-args".

Simon

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

* Re: [RFAv6 1/3] default-args: allow to define default arguments for aliases
  2020-06-08 21:28   ` Simon Marchi
@ 2020-06-09 19:49     ` Philippe Waroquiers
  2020-06-09 22:59       ` Simon Marchi
  0 siblings, 1 reply; 11+ messages in thread
From: Philippe Waroquiers @ 2020-06-09 19:49 UTC (permalink / raw)
  To: Simon Marchi, gdb-patches

Hello Simon,

On Mon, 2020-06-08 at 17:28 -0400, Simon Marchi wrote:
> I don't remember if we talked about this earlier... but is this
> the expected behavior when using an alias to define another alias?

This point was not discussed but is the consequence of GDB
resolving an alias to point at the (end/final) command it is
aliasing, and e.g. not mplementing an alias as a kind of textual
replacement.
When asking the list of aliases, it similarly shows the 'final'
command it is aliasing, and not the alias that was used 
in the definition.

(gdb) alias aaa = echo bonjour
(gdb) alias bbb = aaa coucou
(gdb) help aliases
User-defined aliases of other commands.

List of commands:

aaa -- Print a constant string.  Give string as argument.
  alias aaa = echo bonjour
bbb -- Print a constant string.  Give string as argument.
  alias bbb = echo coucou

We might explicit this behaviour in the user manual.
(it might be possible to re-implement aliases as textual
replacement but that is a major rework, e.g. the
chain of aliases of a command has to be replaced
by something else, the aliased_command pointer is to point
at another chain of aliases, that must be evaluated "dynamically"
when executing the command, rather than resolved at definition time.


Note that GDB and a shell are already very different beasts
on many aspects e.g. :
  (gdb) set $xxx = "coucou"
  (gdb) echo $xxx
  $xxx(gdb) p $xxx
  $1 = "coucou"
  (gdb) 



> > +  if (*text == nullptr || skip_spaces (*text) == nullptr)
> > +    error (_("COMMAND missing."));
> 
> This should say ALIAS, since it says ALIAS in "help set default-args".
That is a left over of the version that allowed default args for
commands.  I will fix this.

Thanks for the comments

Philippe




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

* Re: [RFAv6 1/3] default-args: allow to define default arguments for aliases
  2020-06-09 19:49     ` Philippe Waroquiers
@ 2020-06-09 22:59       ` Simon Marchi
  2020-06-10 18:56         ` Philippe Waroquiers
  0 siblings, 1 reply; 11+ messages in thread
From: Simon Marchi @ 2020-06-09 22:59 UTC (permalink / raw)
  To: Philippe Waroquiers, gdb-patches

On 2020-06-09 3:49 p.m., Philippe Waroquiers wrote:
> Hello Simon,
> 
> On Mon, 2020-06-08 at 17:28 -0400, Simon Marchi wrote:
>> I don't remember if we talked about this earlier... but is this
>> the expected behavior when using an alias to define another alias?
> 
> This point was not discussed but is the consequence of GDB
> resolving an alias to point at the (end/final) command it is
> aliasing, and e.g. not mplementing an alias as a kind of textual
> replacement.
> When asking the list of aliases, it similarly shows the 'final'
> command it is aliasing, and not the alias that was used 
> in the definition.
> 
> (gdb) alias aaa = echo bonjour
> (gdb) alias bbb = aaa coucou
> (gdb) help aliases
> User-defined aliases of other commands.
> 
> List of commands:
> 
> aaa -- Print a constant string.  Give string as argument.
>   alias aaa = echo bonjour
> bbb -- Print a constant string.  Give string as argument.
>   alias bbb = echo coucou
> 
> We might explicit this behaviour in the user manual.
> (it might be possible to re-implement aliases as textual
> replacement but that is a major rework, e.g. the
> chain of aliases of a command has to be replaced
> by something else, the aliased_command pointer is to point
> at another chain of aliases, that must be evaluated "dynamically"
> when executing the command, rather than resolved at definition time.

I understand that this is because of the current implementation, but I really
think that the behavior is unexpected from the point of view of the user.  If
default arguments don't add up when defining an alias based on another alias,
then I'd suggest preventing the user from creating aliases based on other
aliases.  The rationale being that there is no point in doing:

(gdb) alias aaa = print abc
(gdb) alias bbb = aaa def

over

(gdb) alias aaa = print abc
(gdb) alias bbb = print def

And the former would just cause confusion with the current behavior (even if
documented in the manual).  Plus, if we allow the former, we will be stuck with
this behavior, we won't be able to change it in the future if we want to
implement the behavior where the default arguments accumulate.

I have to admit that I didn't dig much in the implementation, but this is how I
would see it.  Right now, when you define `bbb`, bbb's cmd_list_element->cmd_pointer
points to print's cmd_list_element.  Would it be hard to make it point to aaa's
cmd_list_element instead?  This way, when we look up command `bbb`, we could resolve
the aliases recursively (or iteratively) and just build up the default args string
as each alias level is resolved.  If we take the example from above, when executing
command `bbb`, we would end up with default args "abc def".

I presume it's doable but not a simple change, so that's why I suggest for now to
just prevent defining aliases based on aliases, so we can keep the door open to
implementing it later.

> Note that GDB and a shell are already very different beasts
> on many aspects e.g. :
>   (gdb) set $xxx = "coucou"
>   (gdb) echo $xxx
>   $xxx(gdb) p $xxx
>   $1 = "coucou"
>   (gdb) 

Of course!  But it doesn't prevent us from stealing good ideas from the
shell :).

Simon

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

* Re: [RFAv6 1/3] default-args: allow to define default arguments for aliases
  2020-06-09 22:59       ` Simon Marchi
@ 2020-06-10 18:56         ` Philippe Waroquiers
  2020-06-11  3:07           ` Simon Marchi
  0 siblings, 1 reply; 11+ messages in thread
From: Philippe Waroquiers @ 2020-06-10 18:56 UTC (permalink / raw)
  To: Simon Marchi, gdb-patches

On Tue, 2020-06-09 at 18:59 -0400, Simon Marchi wrote:
> 
> I understand that this is because of the current implementation, but I really
> think that the behavior is unexpected from the point of view of the user.  If
> default arguments don't add up when defining an alias based on another alias,
> then I'd suggest preventing the user from creating aliases based on other
> aliases.  The rationale being that there is no point in doing:
> 
> (gdb) alias aaa = print abc
> (gdb) alias bbb = aaa def
> 
> over
> 
> (gdb) alias aaa = print abc
> (gdb) alias bbb = print def
> 
> And the former would just cause confusion with the current behavior (even if
> documented in the manual).  Plus, if we allow the former, we will be stuck with
> this behavior, we won't be able to change it in the future if we want to
> implement the behavior where the default arguments accumulate.
> 
> I have to admit that I didn't dig much in the implementation, but this is how I
> would see it.  Right now, when you define `bbb`, bbb's cmd_list_element->cmd_pointer
> points to print's cmd_list_element.  Would it be hard to make it point to aaa's
> cmd_list_element instead?  This way, when we look up command `bbb`, we could resolve
> the aliases recursively (or iteratively) and just build up the default args string
> as each alias level is resolved.  If we take the example from above, when executing
> command `bbb`, we would end up with default args "abc def".
Yes, to expand the args, we would have to scan a linked list of aliases.
the linked list should replace the current pointer to the aliased command.
But as far as I can see, there are a bunch of other things to rework
(such as the chain of alias of a command).
So, not a minor change (as you presume below).
> 
> I presume it's doable but not a simple change, so that's why I suggest for now to
> just prevent defining aliases based on aliases, so we can keep the door open to
> implementing it later.
Yes, that is a good idea.

I will implement this protection/prevention this week-end.
Note that to avoid having a backward incompatible change, I suggest to report an
error only when the new or the old alias have default args.
Otherwise, we will break .gdbinit of users that have done:
   alias aaa = backtrace
   alias bbb = aaa

Philippe



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

* Re: [RFAv6 1/3] default-args: allow to define default arguments for aliases
  2020-06-10 18:56         ` Philippe Waroquiers
@ 2020-06-11  3:07           ` Simon Marchi
  0 siblings, 0 replies; 11+ messages in thread
From: Simon Marchi @ 2020-06-11  3:07 UTC (permalink / raw)
  To: Philippe Waroquiers, gdb-patches

On 2020-06-10 2:56 p.m., Philippe Waroquiers wrote:
> On Tue, 2020-06-09 at 18:59 -0400, Simon Marchi wrote:
>>
>> I understand that this is because of the current implementation, but I really
>> think that the behavior is unexpected from the point of view of the user.  If
>> default arguments don't add up when defining an alias based on another alias,
>> then I'd suggest preventing the user from creating aliases based on other
>> aliases.  The rationale being that there is no point in doing:
>>
>> (gdb) alias aaa = print abc
>> (gdb) alias bbb = aaa def
>>
>> over
>>
>> (gdb) alias aaa = print abc
>> (gdb) alias bbb = print def
>>
>> And the former would just cause confusion with the current behavior (even if
>> documented in the manual).  Plus, if we allow the former, we will be stuck with
>> this behavior, we won't be able to change it in the future if we want to
>> implement the behavior where the default arguments accumulate.
>>
>> I have to admit that I didn't dig much in the implementation, but this is how I
>> would see it.  Right now, when you define `bbb`, bbb's cmd_list_element->cmd_pointer
>> points to print's cmd_list_element.  Would it be hard to make it point to aaa's
>> cmd_list_element instead?  This way, when we look up command `bbb`, we could resolve
>> the aliases recursively (or iteratively) and just build up the default args string
>> as each alias level is resolved.  If we take the example from above, when executing
>> command `bbb`, we would end up with default args "abc def".
> Yes, to expand the args, we would have to scan a linked list of aliases.
> the linked list should replace the current pointer to the aliased command.
> But as far as I can see, there are a bunch of other things to rework
> (such as the chain of alias of a command).
> So, not a minor change (as you presume below).
>>
>> I presume it's doable but not a simple change, so that's why I suggest for now to
>> just prevent defining aliases based on aliases, so we can keep the door open to
>> implementing it later.
> Yes, that is a good idea.
> 
> I will implement this protection/prevention this week-end.
> Note that to avoid having a backward incompatible change, I suggest to report an
> error only when the new or the old alias have default args.
> Otherwise, we will break .gdbinit of users that have done:
>    alias aaa = backtrace
>    alias bbb = aaa

Ah right, the alias command already exists so this is an existing use case.  That's
fine with me, since that will continue to work without change in behavior the day
we implement the default arg with aliases thing.

Simon

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

end of thread, other threads:[~2020-06-11  3:07 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-16 17:19 [RFAv6 0/3] Allow the user to define default args for aliases Philippe Waroquiers
2020-05-16 17:19 ` [RFAv6 1/3] default-args: allow to define default arguments " Philippe Waroquiers
2020-06-08 21:28   ` Simon Marchi
2020-06-09 19:49     ` Philippe Waroquiers
2020-06-09 22:59       ` Simon Marchi
2020-06-10 18:56         ` Philippe Waroquiers
2020-06-11  3:07           ` Simon Marchi
2020-05-16 17:19 ` [RFAv6 2/3] Add tests for new default-args related commands and arguments Philippe Waroquiers
2020-05-16 17:19 ` [RFAv6 3/3] NEWS and documentation for default-args related concept and commands Philippe Waroquiers
2020-05-16 17:49   ` Eli Zaretskii
2020-05-24 18:53 ` [RFAv6 0/3] Allow the user to define default args for aliases 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).