From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mailsec117.isp.belgacom.be (mailsec117.isp.belgacom.be [195.238.20.113]) by sourceware.org (Postfix) with ESMTPS id 33A303840C2D for ; Sat, 16 May 2020 17:20:00 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 33A303840C2D IronPort-SDR: /2HbUNjpN2Qr5IyahH1cJBoTFK7YDXPdr86B6JEmfL3G/V3rFiaxC07ocwVULPEkKVz9DXb1aG /a4xZrOBDahkmpkK9cBqvO2EZfp+m4La1I3wQ/Yc0hZBcDjuxXIXFINZJW/9R7B1Y3TeIO8rov /GEarJp+npqKEGp+TSShhLeCA0pLgbMnG2nLIeUjyMt+ZA8nrg2ppp7HwSMU5U5YNW6R8EkWJF 4Wcdc4h4wxQP89UUW2+G8gyBZ20TT8SXGpcCEH84axbR4+DkcZNRigV4UsKTgIF6zJ2dWKufrj 618= IronPort-PHdr: =?us-ascii?q?9a23=3A0yTBuhw7etkJ4arXCy+O+j09IxM/srCxBDY+r6?= =?us-ascii?q?Qd2u4RIJqq85mqBkHD//Il1AaPAdyGrasc06GP6/GocFdDyK7JiGoFfp1IWk?= =?us-ascii?q?1NouQttCtkPvS4D1bmJuXhdS0wEZcKflZk+3amLRodQ56mNBXdrXKo8DEdBA?= =?us-ascii?q?j0OxZrKeTpAI7SiNm82/yv95HJbAhEmTqwbalvIBmqsQndudQajZdmJ60s1h?= =?us-ascii?q?bHv3xEdvhMy2h1P1yThRH85smx/J5n7Stdvu8q+tBDX6vnYak2VKRUAzs6PW?= =?us-ascii?q?874s3rrgTDQhCU5nQASGUWkwFHDBbD4RrnQ5r+qCr6tu562CmHIc37SK0/VD?= =?us-ascii?q?q+46t3ThLjlSEKPCM7/m7KkMx9lKJVrgy8qRJxwIDaZ4OaNPRxca3SZt4WWW?= =?us-ascii?q?lMU9xNWyFbHo+wc40CBPcBM+ZCqIn9okMDowG+BQmtAOPvyydIhmfo0qYn0+?= =?us-ascii?q?suCxvG3As5H9ITsXTbss/1NLwPWu2y1KnIzTTDb/dX2Tfl8IjHbAotoP+WUr?= =?us-ascii?q?JqdsrR0FQvFwLbgVWKsozoJCiV1ucNsmid8eVgSfijhHU5pAxopDWk28gjhJ?= =?us-ascii?q?XTiI0P1lDE6Tt2wJwzJdCgR0B2YcCpHZReui+VOYZ7Xt4uTn1ntis+xLALt5?= =?us-ascii?q?+2cDYExpkp2hLSb/OKfoeG7xzjWuicPSt1iWxkdb+hhxu/9U6twfD/WMmsyF?= =?us-ascii?q?tGsDdJn9vWunwQ2RHe69KLR/hg8ku71zuC2Qbe4fxeL08uj6rUMZshz6Y1lp?= =?us-ascii?q?oUrEvMADf7mF7zjK+KbkUk/fWo6/j/brXmuJCcM4h0hxn7MqszgMC/AeM4Mg?= =?us-ascii?q?0QUGSD+OS80qPs/VHhTblUk/E7kLPVvI3UKMkavKK0ABJZ3pwt5huxFzum1c?= =?us-ascii?q?4XnXgDLFJLYhKHiI3pNknWIPD4DPe/h1WskC9zx//YJLHgDI/CLmLEkLf4YL?= =?us-ascii?q?Z96lBTyBAozd1E/JJUCbEAIPTtVU/trtDXFQE2PxSuw+n7ENV9yp8eWWWXD6?= =?us-ascii?q?+WLazdqkaE5vo1LOmQeIAVuCjyK+M+6v71in85hEUdcrW30poZcn+4BOppL1?= =?us-ascii?q?+eYXr2jdcLCX0KsRYmTOz2lF2CViZeZ26yX6I94jE7CZqmDZ/dSYy3jr2Oxj?= =?us-ascii?q?27HppPZmBbC1CDD23od56fVvcXayKTIslhnSIYVbS7UIAuy0LmiAivxLZta/?= =?us-ascii?q?Ld5iYYuInLz99o/ebeihgo+HpzFcvO/XuKSjRMnmIMRicu0ehAqFZ600qC3L?= =?us-ascii?q?Jjy6hAFd1X5utRX0ElPITb1vF7BsrpchnCb9GEVBCsT4P1UnkKUtstzopWMA?= =?us-ascii?q?5GENK4g0Wb0g=3D=3D?= X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: =?us-ascii?q?A2B/IwDYH8Be/yFRiNlmglKBdjQqRVQ?= =?us-ascii?q?hEiyNJYV6gxGaYwsBAQEBAQEBAQEIHw0BAgQBAYREAoIVJzgTAgMBAQEDAgU?= =?us-ascii?q?BAQYBAQEBAQEEBAFsBAEBBwoCAYROIQEDAQEFCgFDQgEMAQgBAYFhIoMVBho?= =?us-ascii?q?BDAsBIyMQPxJXGYMmAYMAsCwzhVGDb4FAgTgBh1qEdoFMP4EQAYISSXOKQgS?= =?us-ascii?q?OLIl2mXF9B4JTgQEEhyGQFQwdgl2NcogOhHmOK4N0nB+BaSKBVm0yBB2CaQl?= =?us-ascii?q?HGA2QTBeOJ0IwNwIGCAEBAwlXASIBiGaBG0eBVi2CFgEB?= X-IPAS-Result: =?us-ascii?q?A2B/IwDYH8Be/yFRiNlmglKBdjQqRVQhEiyNJYV6gxGaY?= =?us-ascii?q?wsBAQEBAQEBAQEIHw0BAgQBAYREAoIVJzgTAgMBAQEDAgUBAQYBAQEBAQEEB?= =?us-ascii?q?AFsBAEBBwoCAYROIQEDAQEFCgFDQgEMAQgBAYFhIoMVBhoBDAsBIyMQPxJXG?= =?us-ascii?q?YMmAYMAsCwzhVGDb4FAgTgBh1qEdoFMP4EQAYISSXOKQgSOLIl2mXF9B4JTg?= =?us-ascii?q?QEEhyGQFQwdgl2NcogOhHmOK4N0nB+BaSKBVm0yBB2CaQlHGA2QTBeOJ0IwN?= =?us-ascii?q?wIGCAEBAwlXASIBiGaBG0eBVi2CFgEB?= Received: from 33.81-136-217.adsl-dyn.isp.belgacom.be (HELO md.home) ([217.136.81.33]) by relay.skynet.be with ESMTP/TLS/ECDHE-RSA-AES128-GCM-SHA256; 16 May 2020 19:19:53 +0200 From: Philippe Waroquiers To: gdb-patches@sourceware.org Subject: [RFAv6 1/3] default-args: allow to define default arguments for aliases Date: Sat, 16 May 2020 19:19:45 +0200 Message-Id: <20200516171947.10507-2-philippe.waroquiers@skynet.be> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200516171947.10507-1-philippe.waroquiers@skynet.be> References: <20200516171947.10507-1-philippe.waroquiers@skynet.be> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-13.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 16 May 2020 17:20:04 -0000 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 * 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 + 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 () + ? "" : 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, ""); +} + /* 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 { + "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; } } @@ -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