/* Handle lists of commands, their decoding and documentation, for GDB.
- Copyright (C) 1986-2021 Free Software Foundation, Inc.
+ Copyright (C) 1986-2022 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
#include "defs.h"
#include "symtab.h"
#include <ctype.h>
-#include "gdb_regex.h"
+#include "gdbsupport/gdb_regex.h"
#include "completer.h"
#include "ui-out.h"
#include "cli/cli-cmds.h"
static void undef_cmd_error (const char *, const char *);
-static struct cmd_list_element *delete_cmd (const char *name,
- struct cmd_list_element **list,
- struct cmd_list_element **prehook,
- struct cmd_list_element **prehookee,
- struct cmd_list_element **posthook,
- struct cmd_list_element **posthookee);
+static cmd_list_element::aliases_list_type delete_cmd
+ (const char *name, cmd_list_element **list, cmd_list_element **prehook,
+ cmd_list_element **prehookee, cmd_list_element **posthook,
+ cmd_list_element **posthookee);
static struct cmd_list_element *find_cmd (const char *command,
int len,
}
static void
-print_help_for_command (struct cmd_list_element *c,
+print_help_for_command (const cmd_list_element &c,
bool recurse, struct ui_file *stream);
static void
return prefixname;
}
+/* See cli/cli-decode.h. */
+
+std::vector<std::string>
+cmd_list_element::command_components () const
+{
+ std::vector<std::string> result;
+
+ if (this->prefix != nullptr)
+ result = this->prefix->command_components ();
+
+ result.emplace_back (std::string (this->name));
+ return result;
+}
+
/* Add element named NAME.
Space for NAME and DOC must be allocated by the caller.
CLASS is the top level category into which commands are broken down
{
struct cmd_list_element *c = new struct cmd_list_element (name, theclass,
doc);
- struct cmd_list_element *p, *iter;
/* Turn each alias of the old command into an alias of the new
command. */
c->aliases = delete_cmd (name, list, &c->hook_pre, &c->hookee_pre,
&c->hook_post, &c->hookee_post);
- for (iter = c->aliases; iter; iter = iter->alias_chain)
- iter->alias_target = c;
+
+ for (cmd_list_element &alias : c->aliases)
+ alias.alias_target = c;
+
if (c->hook_pre)
c->hook_pre->hookee_pre = c;
+
if (c->hookee_pre)
c->hookee_pre->hook_pre = c;
+
if (c->hook_post)
c->hook_post->hookee_post = c;
+
if (c->hookee_post)
c->hookee_post->hook_post = c;
}
else
{
- p = *list;
+ cmd_list_element *p = *list;
while (p->next && strcmp (p->next->name, name) <= 0)
{
p = p->next;
add_cmd_suppress_notification (const char *name, enum command_class theclass,
cmd_simple_func_ftype *fun, const char *doc,
struct cmd_list_element **list,
- int *suppress_notification)
+ bool *suppress_notification)
{
struct cmd_list_element *element;
c->allow_unknown = target->allow_unknown;
c->abbrev_flag = abbrev_flag;
c->alias_target = target;
- c->alias_chain = target->aliases;
- target->aliases = c;
+ target->aliases.push_front (*c);
return c;
}
return cmd;
}
+/* See command.h. */
+
+set_show_commands
+add_setshow_prefix_cmd (const char *name, command_class theclass,
+ const char *set_doc, const char *show_doc,
+ cmd_list_element **set_subcommands_list,
+ cmd_list_element **show_subcommands_list,
+ cmd_list_element **set_list,
+ cmd_list_element **show_list)
+{
+ set_show_commands cmds;
+
+ cmds.set = add_basic_prefix_cmd (name, theclass, set_doc,
+ set_subcommands_list, 0,
+ set_list);
+ cmds.show = add_show_prefix_cmd (name, theclass, show_doc,
+ show_subcommands_list, 0,
+ show_list);
+
+ return cmds;
+}
+
/* Like ADD_PREFIX_CMD but sets the suppress_notification pointer on the
new command list element. */
cmd_simple_func_ftype *fun,
const char *doc, struct cmd_list_element **subcommands,
int allow_unknown, struct cmd_list_element **list,
- int *suppress_notification)
+ bool *suppress_notification)
{
struct cmd_list_element *element
= add_prefix_cmd (name, theclass, fun, doc, subcommands,
CLASS is as in add_cmd.
VAR_TYPE is the kind of thing we are setting.
VAR is address of the variable being controlled by this command.
+ SET_SETTING_FUNC is a pointer to an optional function callback used to set
+ the setting value.
+ GET_SETTING_FUNC is a pointer to an optional function callback used to get
+ the setting value.
DOC is the documentation string. */
static struct cmd_list_element *
/* Add element named NAME to both the command SET_LIST and SHOW_LIST.
CLASS is as in add_cmd. VAR_TYPE is the kind of thing we are
setting. VAR is address of the variable being controlled by this
- command. SET_FUNC and SHOW_FUNC are the callback functions (if
- non-NULL). SET_DOC, SHOW_DOC and HELP_DOC are the documentation
- strings.
+ command. If nullptr is given as VAR, then both SET_SETTING_FUNC and
+ GET_SETTING_FUNC must be provided. SET_SETTING_FUNC and GET_SETTING_FUNC are
+ callbacks used to access and modify the underlying property, whatever its
+ storage is. SET_FUNC and SHOW_FUNC are the callback functions (if non-NULL).
+ SET_DOC, SHOW_DOC and HELP_DOC are the documentation strings.
Return the newly created set and show commands. */
{
struct cmd_list_element *set;
struct cmd_list_element *show;
- char *full_set_doc;
- char *full_show_doc;
+ gdb::unique_xmalloc_ptr<char> full_set_doc;
+ gdb::unique_xmalloc_ptr<char> full_show_doc;
if (help_doc != NULL)
{
}
else
{
- full_set_doc = xstrdup (set_doc);
- full_show_doc = xstrdup (show_doc);
+ full_set_doc = make_unique_xstrdup (set_doc);
+ full_show_doc = make_unique_xstrdup (show_doc);
}
set = add_set_or_show_cmd (name, set_cmd, theclass, var_type, args,
- full_set_doc, set_list);
+ full_set_doc.release (), set_list);
set->doc_allocated = 1;
if (set_func != NULL)
set->func = set_func;
show = add_set_or_show_cmd (name, show_cmd, theclass, var_type, args,
- full_show_doc, show_list);
+ full_show_doc.release (), show_list);
show->doc_allocated = 1;
show->show_value_func = show_func;
/* Disable the default symbol completer. Doesn't make much sense
var_types var_type, T *var,
const char *set_doc, const char *show_doc,
const char *help_doc,
+ typename setting_func_types<T>::set set_setting_func,
+ typename setting_func_types<T>::get get_setting_func,
cmd_func_ftype *set_func,
show_value_ftype *show_func,
struct cmd_list_element **set_list,
struct cmd_list_element **show_list)
{
auto erased_args
- = setting::erase_args (var_type, var);
+ = setting::erase_args (var_type, var,
+ set_setting_func, get_setting_func);
return add_setshow_cmd_full_erased (name,
theclass,
struct cmd_list_element **set_list,
struct cmd_list_element **show_list)
{
+ /* We require *VAR to be initialized before this call, and
+ furthermore it must be == to one of the values in ENUMLIST. */
+ gdb_assert (var != nullptr && *var != nullptr);
+ for (int i = 0; ; ++i)
+ {
+ gdb_assert (enumlist[i] != nullptr);
+ if (*var == enumlist[i])
+ break;
+ }
+
set_show_commands commands
= add_setshow_cmd_full<const char *> (name, theclass, var_enum, var,
set_doc, show_doc, help_doc,
- set_func, show_func,
- set_list, show_list);
+ nullptr, nullptr, set_func,
+ show_func, set_list, show_list);
commands.set->enums = enumlist;
return commands;
}
+/* Same as above but using a getter and a setter function instead of a pointer
+ to a global storage buffer. */
+
+set_show_commands
+add_setshow_enum_cmd (const char *name, command_class theclass,
+ const char *const *enumlist, const char *set_doc,
+ const char *show_doc, const char *help_doc,
+ setting_func_types<const char *>::set set_func,
+ setting_func_types<const char *>::get get_func,
+ show_value_ftype *show_func,
+ cmd_list_element **set_list,
+ cmd_list_element **show_list)
+{
+ auto cmds = add_setshow_cmd_full<const char *> (name, theclass, var_enum,
+ nullptr, set_doc, show_doc,
+ help_doc, set_func, get_func,
+ nullptr, show_func, set_list,
+ show_list);
+
+ cmds.set->enums = enumlist;
+
+ return cmds;
+}
+
/* See cli-decode.h. */
const char * const auto_boolean_enums[] = { "on", "off", "auto", NULL };
struct cmd_list_element **show_list)
{
set_show_commands commands
- = add_setshow_cmd_full<enum auto_boolean> (name, theclass,
- var_auto_boolean,var,
- set_doc, show_doc, help_doc,
- set_func, show_func,
- set_list, show_list);
+ = add_setshow_cmd_full<enum auto_boolean> (name, theclass, var_auto_boolean,
+ var, set_doc, show_doc, help_doc,
+ nullptr, nullptr, set_func,
+ show_func, set_list, show_list);
commands.set->enums = auto_boolean_enums;
return commands;
}
+/* Same as above but using a getter and a setter function instead of a pointer
+ to a global storage buffer. */
+
+set_show_commands
+add_setshow_auto_boolean_cmd (const char *name, command_class theclass,
+ const char *set_doc, const char *show_doc,
+ const char *help_doc,
+ setting_func_types<enum auto_boolean>::set set_func,
+ setting_func_types<enum auto_boolean>::get get_func,
+ show_value_ftype *show_func,
+ cmd_list_element **set_list,
+ cmd_list_element **show_list)
+{
+ auto cmds = add_setshow_cmd_full<enum auto_boolean> (name, theclass,
+ var_auto_boolean,
+ nullptr, set_doc,
+ show_doc, help_doc,
+ set_func, get_func,
+ nullptr, show_func,
+ set_list, show_list);
+
+ cmds.set->enums = auto_boolean_enums;
+
+ return cmds;
+}
+
/* See cli-decode.h. */
const char * const boolean_enums[] = { "on", "off", NULL };
set_show_commands commands
= add_setshow_cmd_full<bool> (name, theclass, var_boolean, var,
set_doc, show_doc, help_doc,
- set_func, show_func,
+ nullptr, nullptr, set_func, show_func,
set_list, show_list);
commands.set->enums = boolean_enums;
return commands;
}
+/* Same as above but using a getter and a setter function instead of a pointer
+ to a global storage buffer. */
+
+set_show_commands
+add_setshow_boolean_cmd (const char *name, command_class theclass,
+ const char *set_doc, const char *show_doc,
+ const char *help_doc,
+ setting_func_types<bool>::set set_func,
+ setting_func_types<bool>::get get_func,
+ show_value_ftype *show_func,
+ cmd_list_element **set_list,
+ cmd_list_element **show_list)
+{
+ auto cmds = add_setshow_cmd_full<bool> (name, theclass, var_boolean, nullptr,
+ set_doc, show_doc, help_doc,
+ set_func, get_func, nullptr,
+ show_func, set_list, show_list);
+
+ cmds.set->enums = boolean_enums;
+
+ return cmds;
+}
+
/* Add element named NAME to both the set and show command LISTs (the
list for set/show or some sublist thereof). */
set_show_commands
add_setshow_filename_cmd (const char *name, enum command_class theclass,
- char **var,
+ std::string *var,
const char *set_doc, const char *show_doc,
const char *help_doc,
cmd_func_ftype *set_func,
struct cmd_list_element **show_list)
{
set_show_commands commands
- = add_setshow_cmd_full<char *> (name, theclass, var_filename, var,
- set_doc, show_doc, help_doc,
- set_func, show_func,
- set_list, show_list);
+ = add_setshow_cmd_full<std::string> (name, theclass, var_filename, var,
+ set_doc, show_doc, help_doc,
+ nullptr, nullptr, set_func,
+ show_func, set_list, show_list);
set_cmd_completer (commands.set, filename_completer);
return commands;
}
+/* Same as above but using a getter and a setter function instead of a pointer
+ to a global storage buffer. */
+
+set_show_commands
+add_setshow_filename_cmd (const char *name, command_class theclass,
+ const char *set_doc, const char *show_doc,
+ const char *help_doc,
+ setting_func_types<std::string>::set set_func,
+ setting_func_types<std::string>::get get_func,
+ show_value_ftype *show_func,
+ cmd_list_element **set_list,
+ cmd_list_element **show_list)
+{
+ auto cmds = add_setshow_cmd_full<std::string> (name, theclass, var_filename,
+ nullptr, set_doc, show_doc,
+ help_doc, set_func, get_func,
+ nullptr, show_func, set_list,
+ show_list);
+
+ set_cmd_completer (cmds.set, filename_completer);
+
+ return cmds;
+}
+
/* Add element named NAME to both the set and show command LISTs (the
list for set/show or some sublist thereof). */
set_show_commands
add_setshow_string_cmd (const char *name, enum command_class theclass,
- char **var,
+ std::string *var,
const char *set_doc, const char *show_doc,
const char *help_doc,
cmd_func_ftype *set_func,
struct cmd_list_element **show_list)
{
set_show_commands commands
- = add_setshow_cmd_full<char *> (name, theclass, var_string, var,
- set_doc, show_doc, help_doc,
- set_func, show_func,
- set_list, show_list);
+ = add_setshow_cmd_full<std::string> (name, theclass, var_string, var,
+ set_doc, show_doc, help_doc,
+ nullptr, nullptr, set_func,
+ show_func, set_list, show_list);
/* Disable the default symbol completer. */
set_cmd_completer (commands.set, nullptr);
return commands;
}
+/* Same as above but using a getter and a setter function instead of a pointer
+ to a global storage buffer. */
+
+set_show_commands
+add_setshow_string_cmd (const char *name, command_class theclass,
+ const char *set_doc, const char *show_doc,
+ const char *help_doc,
+ setting_func_types<std::string>::set set_func,
+ setting_func_types<std::string>::get get_func,
+ show_value_ftype *show_func,
+ cmd_list_element **set_list,
+ cmd_list_element **show_list)
+{
+ auto cmds = add_setshow_cmd_full<std::string> (name, theclass, var_string,
+ nullptr, set_doc, show_doc,
+ help_doc, set_func, get_func,
+ nullptr, show_func, set_list,
+ show_list);
+
+ /* Disable the default symbol completer. */
+ set_cmd_completer (cmds.set, nullptr);
+
+ return cmds;
+}
+
/* Add element named NAME to both the set and show command LISTs (the
list for set/show or some sublist thereof). */
set_show_commands
add_setshow_string_noescape_cmd (const char *name, enum command_class theclass,
- char **var,
+ std::string *var,
const char *set_doc, const char *show_doc,
const char *help_doc,
cmd_func_ftype *set_func,
struct cmd_list_element **show_list)
{
set_show_commands commands
- = add_setshow_cmd_full<char *> (name, theclass, var_string_noescape, var,
- set_doc, show_doc, help_doc, set_func,
- show_func, set_list, show_list);
+ = add_setshow_cmd_full<std::string> (name, theclass, var_string_noescape,
+ var, set_doc, show_doc, help_doc,
+ nullptr, nullptr, set_func, show_func,
+ set_list, show_list);
/* Disable the default symbol completer. */
set_cmd_completer (commands.set, nullptr);
return commands;
}
+/* Same as above but using a getter and a setter function instead of a pointer
+ to a global storage buffer. */
+
+set_show_commands
+add_setshow_string_noescape_cmd (const char *name, command_class theclass,
+ const char *set_doc, const char *show_doc,
+ const char *help_doc,
+ setting_func_types<std::string>::set set_func,
+ setting_func_types<std::string>::get get_func,
+ show_value_ftype *show_func,
+ cmd_list_element **set_list,
+ cmd_list_element **show_list)
+{
+ auto cmds = add_setshow_cmd_full<std::string> (name, theclass,
+ var_string_noescape, nullptr,
+ set_doc, show_doc, help_doc,
+ set_func, get_func,
+ nullptr, show_func, set_list,
+ show_list);
+
+ /* Disable the default symbol completer. */
+ set_cmd_completer (cmds.set, nullptr);
+
+ return cmds;
+}
+
/* Add element named NAME to both the set and show command LISTs (the
list for set/show or some sublist thereof). */
set_show_commands
add_setshow_optional_filename_cmd (const char *name, enum command_class theclass,
- char **var,
+ std::string *var,
const char *set_doc, const char *show_doc,
const char *help_doc,
cmd_func_ftype *set_func,
struct cmd_list_element **show_list)
{
set_show_commands commands
- = add_setshow_cmd_full<char *> (name, theclass, var_optional_filename,
- var, set_doc, show_doc, help_doc,
- set_func, show_func, set_list, show_list);
+ = add_setshow_cmd_full<std::string> (name, theclass, var_optional_filename,
+ var, set_doc, show_doc, help_doc,
+ nullptr, nullptr, set_func, show_func,
+ set_list, show_list);
set_cmd_completer (commands.set, filename_completer);
return commands;
}
+/* Same as above but using a getter and a setter function instead of a pointer
+ to a global storage buffer. */
+
+set_show_commands
+add_setshow_optional_filename_cmd (const char *name, command_class theclass,
+ const char *set_doc, const char *show_doc,
+ const char *help_doc,
+ setting_func_types<std::string>::set set_func,
+ setting_func_types<std::string>::get get_func,
+ show_value_ftype *show_func,
+ cmd_list_element **set_list,
+ cmd_list_element **show_list)
+{
+ auto cmds =
+ add_setshow_cmd_full<std::string> (name, theclass, var_optional_filename,
+ nullptr, set_doc, show_doc, help_doc,
+ set_func, get_func, nullptr, show_func,
+ set_list,show_list);
+
+ set_cmd_completer (cmds.set, filename_completer);
+
+ return cmds;
+}
+
/* Completes on literal "unlimited". Used by integer commands that
support a special "unlimited" value. */
NULL,
};
+ if (*text == '\0')
+ tracker.add_completion (make_unique_xstrdup ("NUMBER"));
complete_on_enum (tracker, keywords, text, word);
}
struct cmd_list_element **show_list)
{
set_show_commands commands
- = add_setshow_cmd_full<int> (name, theclass, var_integer, var, set_doc,
- show_doc, help_doc, set_func, show_func,
- set_list, show_list);
+ = add_setshow_cmd_full<int> (name, theclass, var_integer, var,
+ set_doc, show_doc, help_doc,
+ nullptr, nullptr, set_func,
+ show_func, set_list, show_list);
set_cmd_completer (commands.set, integer_unlimited_completer);
return commands;
}
+/* Same as above but using a getter and a setter function instead of a pointer
+ to a global storage buffer. */
+
+set_show_commands
+add_setshow_integer_cmd (const char *name, command_class theclass,
+ const char *set_doc, const char *show_doc,
+ const char *help_doc,
+ setting_func_types<int>::set set_func,
+ setting_func_types<int>::get get_func,
+ show_value_ftype *show_func,
+ cmd_list_element **set_list,
+ cmd_list_element **show_list)
+{
+ auto cmds = add_setshow_cmd_full<int> (name, theclass, var_integer, nullptr,
+ set_doc, show_doc, help_doc, set_func,
+ get_func, nullptr, show_func, set_list,
+ show_list);
+
+ set_cmd_completer (cmds.set, integer_unlimited_completer);
+
+ return cmds;
+}
+
/* Add element named NAME to both the set and show command LISTs (the
list for set/show or some sublist thereof). CLASS is as in
add_cmd. VAR is address of the variable which will contain the
set_show_commands commands
= add_setshow_cmd_full<unsigned int> (name, theclass, var_uinteger, var,
set_doc, show_doc, help_doc,
- set_func, show_func,
- set_list, show_list);
+ nullptr, nullptr, set_func,
+ show_func, set_list, show_list);
set_cmd_completer (commands.set, integer_unlimited_completer);
return commands;
}
+/* Same as above but using a getter and a setter function instead of a pointer
+ to a global storage buffer. */
+
+set_show_commands
+add_setshow_uinteger_cmd (const char *name, command_class theclass,
+ const char *set_doc, const char *show_doc,
+ const char *help_doc,
+ setting_func_types<unsigned int>::set set_func,
+ setting_func_types<unsigned int>::get get_func,
+ show_value_ftype *show_func,
+ cmd_list_element **set_list,
+ cmd_list_element **show_list)
+{
+ auto cmds = add_setshow_cmd_full<unsigned int> (name, theclass, var_uinteger,
+ nullptr, set_doc, show_doc,
+ help_doc, set_func, get_func,
+ nullptr, show_func, set_list,
+ show_list);
+
+ set_cmd_completer (cmds.set, integer_unlimited_completer);
+
+ return cmds;
+}
+
/* Add element named NAME to both the set and show command LISTs (the
list for set/show or some sublist thereof). CLASS is as in
add_cmd. VAR is address of the variable which will contain the
{
return add_setshow_cmd_full<int> (name, theclass, var_zinteger, var,
set_doc, show_doc, help_doc,
- set_func, show_func,
- set_list, show_list);
+ nullptr, nullptr, set_func,
+ show_func, set_list, show_list);
+}
+
+/* Same as above but using a getter and a setter function instead of a pointer
+ to a global storage buffer. */
+
+set_show_commands
+add_setshow_zinteger_cmd (const char *name, command_class theclass,
+ const char *set_doc, const char *show_doc,
+ const char *help_doc,
+ setting_func_types<int>::set set_func,
+ setting_func_types<int>::get get_func,
+ show_value_ftype *show_func,
+ cmd_list_element **set_list,
+ cmd_list_element **show_list)
+{
+ return add_setshow_cmd_full<int> (name, theclass, var_zinteger, nullptr,
+ set_doc, show_doc, help_doc, set_func,
+ get_func, nullptr, show_func, set_list,
+ show_list);
}
set_show_commands
{
set_show_commands commands
= add_setshow_cmd_full<int> (name, theclass, var_zuinteger_unlimited, var,
- set_doc, show_doc, help_doc, set_func,
- show_func, set_list, show_list);
+ set_doc, show_doc, help_doc, nullptr,
+ nullptr, set_func, show_func, set_list,
+ show_list);
set_cmd_completer (commands.set, integer_unlimited_completer);
return commands;
}
+/* Same as above but using a getter and a setter function instead of a pointer
+ to a global storage buffer. */
+
+set_show_commands
+add_setshow_zuinteger_unlimited_cmd (const char *name, command_class theclass,
+ const char *set_doc, const char *show_doc,
+ const char *help_doc,
+ setting_func_types<int>::set set_func,
+ setting_func_types<int>::get get_func,
+ show_value_ftype *show_func,
+ cmd_list_element **set_list,
+ cmd_list_element **show_list)
+{
+ auto cmds
+ = add_setshow_cmd_full<int> (name, theclass, var_zuinteger_unlimited,
+ nullptr, set_doc, show_doc, help_doc, set_func,
+ get_func, nullptr, show_func, set_list,
+ show_list);
+
+ set_cmd_completer (cmds.set, integer_unlimited_completer);
+
+ return cmds;
+}
+
/* Add element named NAME to both the set and show command LISTs (the
list for set/show or some sublist thereof). CLASS is as in
add_cmd. VAR is address of the variable which will contain the
{
return add_setshow_cmd_full<unsigned int> (name, theclass, var_zuinteger,
var, set_doc, show_doc, help_doc,
- set_func, show_func, set_list,
+ nullptr, nullptr, set_func,
+ show_func, set_list, show_list);
+}
+
+/* Same as above but using a getter and a setter function instead of a pointer
+ to a global storage buffer. */
+
+set_show_commands
+add_setshow_zuinteger_cmd (const char *name, command_class theclass,
+ const char *set_doc, const char *show_doc,
+ const char *help_doc,
+ setting_func_types<unsigned int>::set set_func,
+ setting_func_types<unsigned int>::get get_func,
+ show_value_ftype *show_func,
+ cmd_list_element **set_list,
+ cmd_list_element **show_list)
+{
+ return add_setshow_cmd_full<unsigned int> (name, theclass, var_zuinteger,
+ nullptr, set_doc, show_doc,
+ help_doc, set_func, get_func,
+ nullptr, show_func, set_list,
show_list);
}
-/* Remove the command named NAME from the command list. Return the
- list commands which were aliased to the deleted command. If the
- command had no aliases, return NULL. The various *HOOKs are set to
- the pre- and post-hook commands for the deleted command. If the
- command does not have a hook, the corresponding out parameter is
- set to NULL. */
+/* Remove the command named NAME from the command list. Return the list
+ commands which were aliased to the deleted command. The various *HOOKs are
+ set to the pre- and post-hook commands for the deleted command. If the
+ command does not have a hook, the corresponding out parameter is set to
+ NULL. */
-static struct cmd_list_element *
+static cmd_list_element::aliases_list_type
delete_cmd (const char *name, struct cmd_list_element **list,
struct cmd_list_element **prehook,
struct cmd_list_element **prehookee,
{
struct cmd_list_element *iter;
struct cmd_list_element **previous_chain_ptr;
- struct cmd_list_element *aliases = NULL;
+ cmd_list_element::aliases_list_type aliases;
*prehook = NULL;
*prehookee = NULL;
/* Update the link. */
*previous_chain_ptr = iter->next;
- aliases = iter->aliases;
+ aliases = std::move (iter->aliases);
/* If this command was an alias, remove it from the list of
aliases. */
if (iter->is_alias ())
{
- struct cmd_list_element **prevp = &iter->alias_target->aliases;
- struct cmd_list_element *a = *prevp;
-
- while (a != iter)
- {
- prevp = &a->alias_chain;
- a = *prevp;
- }
- *prevp = iter->alias_chain;
+ auto it = iter->alias_target->aliases.iterator_to (*iter);
+ iter->alias_target->aliases.erase (it);
}
delete iter;
struct cmd_list_element *
add_com_suppress_notification (const char *name, enum command_class theclass,
cmd_simple_func_ftype *fun, const char *doc,
- int *suppress_notification)
+ bool *suppress_notification)
{
return add_cmd_suppress_notification (name, theclass, fun, doc,
&cmdlist, suppress_notification);
/* Print the prefix of C followed by name of C in title style. */
static void
-fput_command_name_styled (struct cmd_list_element *c, struct ui_file *stream)
+fput_command_name_styled (const cmd_list_element &c, struct ui_file *stream)
{
std::string prefixname
- = c->prefix == nullptr ? "" : c->prefix->prefixname ();
+ = c.prefix == nullptr ? "" : c.prefix->prefixname ();
fprintf_styled (stream, title_style.style (), "%s%s",
- prefixname.c_str (), c->name);
+ prefixname.c_str (), c.name);
+}
+
+/* True if ALIAS has a user-defined documentation. */
+
+static bool
+user_documented_alias (const cmd_list_element &alias)
+{
+ gdb_assert (alias.is_alias ());
+ /* Alias is user documented if it has an allocated documentation
+ that differs from the aliased command. */
+ return (alias.doc_allocated
+ && strcmp (alias.doc, alias.alias_target->doc) != 0);
}
/* 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,
+fput_alias_definition_styled (const cmd_list_element &c,
struct ui_file *stream)
{
- gdb_assert (c->is_alias ());
- fputs_filtered (" alias ", stream);
+ gdb_assert (c.is_alias ());
+ gdb_puts (" alias ", stream);
fput_command_name_styled (c, stream);
- fprintf_filtered (stream, " = ");
- fput_command_name_styled (c->alias_target, stream);
- fprintf_filtered (stream, " %s\n", c->default_args.c_str ());
+ gdb_printf (stream, " = ");
+ fput_command_name_styled (*c.alias_target, stream);
+ gdb_printf (stream, " %s\n", c.default_args.c_str ());
}
-/* Print the definition of the aliases of CMD that have default args. */
+/* Print the definition of CMD aliases not deprecated and having default args
+ and not specifically documented by the user. */
static void
-fput_aliases_definition_styled (struct cmd_list_element *cmd,
+fput_aliases_definition_styled (const 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);
- }
- }
+ for (const cmd_list_element &alias : cmd.aliases)
+ if (!alias.cmd_deprecated
+ && !user_documented_alias (alias)
+ && !alias.default_args.empty ())
+ fput_alias_definition_styled (alias, stream);
}
-
-/* If C has one or more aliases, style print the name of C and
- the name of its aliases, separated by commas.
+/* If C has one or more aliases, style print the name of C and the name of its
+ aliases not documented specifically by the user, separated by commas.
If ALWAYS_FPUT_C_NAME, print the name of C even if it has no aliases.
If one or more names are printed, POSTFIX is printed after the last name.
*/
static void
-fput_command_names_styled (struct cmd_list_element *c,
+fput_command_names_styled (const cmd_list_element &c,
bool always_fput_c_name, const char *postfix,
struct ui_file *stream)
{
- if (always_fput_c_name || c->aliases != nullptr)
+ /* First, check if we are going to print something. That is, either if
+ ALWAYS_FPUT_C_NAME is true or if there exists at least one non-deprecated
+ alias not documented specifically by the user. */
+
+ auto print_alias = [] (const cmd_list_element &alias)
+ {
+ return !alias.cmd_deprecated && !user_documented_alias (alias);
+ };
+
+ bool print_something = always_fput_c_name;
+ if (!print_something)
+ for (const cmd_list_element &alias : c.aliases)
+ {
+ if (!print_alias (alias))
+ continue;
+
+ print_something = true;
+ break;
+ }
+
+ if (print_something)
fput_command_name_styled (c, stream);
- if (c->aliases != nullptr)
+
+ for (const cmd_list_element &alias : c.aliases)
{
- for (cmd_list_element *iter = c->aliases; iter; iter = iter->alias_chain)
- {
- fputs_filtered (", ", stream);
- wrap_here (" ");
- fput_command_name_styled (iter, stream);
- }
+ if (!print_alias (alias))
+ continue;
+
+ gdb_puts (", ", stream);
+ stream->wrap_here (3);
+ fput_command_name_styled (alias, stream);
}
- if (always_fput_c_name || c->aliases != nullptr)
- fputs_filtered (postfix, stream);
+
+ if (print_something)
+ gdb_puts (postfix, stream);
}
/* If VERBOSE, print the full help for command C and highlight the
otherwise print only one-line help for command C. */
static void
-print_doc_of_command (struct cmd_list_element *c, const char *prefix,
+print_doc_of_command (const cmd_list_element &c, const char *prefix,
bool verbose, compiled_regex &highlight,
struct ui_file *stream)
{
this documentation from the previous command help, in the likely
case that apropos finds several commands. */
if (verbose)
- fputs_filtered ("\n", stream);
+ gdb_puts ("\n", stream);
fput_command_names_styled (c, true,
verbose ? "" : " -- ", stream);
if (verbose)
{
- fputs_filtered ("\n", stream);
+ gdb_puts ("\n", stream);
fput_aliases_definition_styled (c, stream);
- fputs_highlighted (c->doc, highlight, stream);
- fputs_filtered ("\n", stream);
+ fputs_highlighted (c.doc, highlight, stream);
+ gdb_puts ("\n", stream);
}
else
{
- print_doc_line (stream, c->doc, false);
- fputs_filtered ("\n", stream);
+ print_doc_line (stream, c.doc, false);
+ gdb_puts ("\n", stream);
fput_aliases_definition_styled (c, stream);
}
}
/* Walk through the commands. */
for (c=commandlist;c;c=c->next)
{
- if (c->is_alias ())
+ if (c->is_alias () && !user_documented_alias (*c))
{
- /* Command aliases/abbreviations are skipped to ensure we print the
- doc of a command only once, when encountering the aliased
- command. */
+ /* Command aliases/abbreviations not specifically documented by the
+ user are skipped to ensure we print the doc of a command only once,
+ when encountering the aliased command. */
continue;
}
/* Try to match against the name. */
returnvalue = regex.search (c->name, name_len, 0, name_len, NULL);
if (returnvalue >= 0)
- print_doc_of_command (c, prefix, verbose, regex, stream);
+ print_doc_of_command (*c, prefix, verbose, regex, stream);
/* Try to match against the name of the aliases. */
- for (cmd_list_element *iter = c->aliases;
- returnvalue < 0 && iter;
- iter = iter->alias_chain)
+ for (const cmd_list_element &alias : c->aliases)
{
- name_len = strlen (iter->name);
- returnvalue = regex.search (iter->name, name_len, 0, name_len, NULL);
+ name_len = strlen (alias.name);
+ returnvalue = regex.search (alias.name, name_len, 0, name_len, NULL);
if (returnvalue >= 0)
- print_doc_of_command (c, prefix, verbose, regex, stream);
+ {
+ print_doc_of_command (*c, prefix, verbose, regex, stream);
+ break;
+ }
}
}
if (c->doc != NULL && returnvalue < 0)
/* Try to match against documentation. */
if (regex.search (c->doc, doc_len, 0, doc_len, NULL) >= 0)
- print_doc_of_command (c, prefix, verbose, regex, stream);
+ print_doc_of_command (*c, prefix, verbose, regex, stream);
}
/* Check if this command has subcommands. */
if (c->is_prefix ())
number of this class so that the commands in the class will be
listed. */
- /* 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 (alias == nullptr || !user_documented_alias (*alias))
+ {
+ /* Case of a normal command, or an alias not explictly
+ documented by the user. */
+ /* 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);
+ gdb_puts (c->doc, stream);
+ }
+ else
+ {
+ /* Case of an alias explictly documented by the user.
+ Only output the alias definition and its explicit documentation. */
+ fput_alias_definition_styled (*alias, stream);
+ fput_command_names_styled (*alias, false, "\n", stream);
+ gdb_puts (alias->doc, stream);
+ }
+ gdb_puts ("\n", stream);
if (!c->is_prefix () && !c->is_command_class_help ())
return;
- fprintf_filtered (stream, "\n");
+ gdb_printf (stream, "\n");
/* If this is a prefix command, print it's subcommands. */
if (c->is_prefix ())
help_list (cmdlist, "", c->theclass, stream);
if (c->hook_pre || c->hook_post)
- fprintf_filtered (stream,
- "\nThis command has a hook (or hooks) defined:\n");
+ gdb_printf (stream,
+ "\nThis command has a hook (or hooks) defined:\n");
if (c->hook_pre)
- fprintf_filtered (stream,
- "\tThis command is run after : %s (pre hook)\n",
- c->hook_pre->name);
+ gdb_printf (stream,
+ "\tThis command is run after : %s (pre hook)\n",
+ c->hook_pre->name);
if (c->hook_post)
- fprintf_filtered (stream,
- "\tThis command is run before : %s (post hook)\n",
- c->hook_post->name);
+ gdb_printf (stream,
+ "\tThis command is run before : %s (post hook)\n",
+ c->hook_post->name);
}
/*
}
if (theclass == all_classes)
- fprintf_filtered (stream, "List of classes of %scommands:\n\n", cmdtype2);
+ gdb_printf (stream, "List of classes of %scommands:\n\n", cmdtype2);
else
- fprintf_filtered (stream, "List of %scommands:\n\n", cmdtype2);
+ gdb_printf (stream, "List of %scommands:\n\n", cmdtype2);
help_cmd_list (list, theclass, theclass >= 0, stream);
if (theclass == all_classes)
{
- fprintf_filtered (stream, "\n\
+ gdb_printf (stream, "\n\
Type \"help%s\" followed by a class name for a list of commands in ",
- cmdtype1);
- wrap_here ("");
- fprintf_filtered (stream, "that class.");
+ cmdtype1);
+ stream->wrap_here (0);
+ gdb_printf (stream, "that class.");
- fprintf_filtered (stream, "\n\
+ gdb_printf (stream, "\n\
Type \"help all\" for the list of all commands.");
}
- fprintf_filtered (stream, "\nType \"help%s\" followed by %scommand name ",
- cmdtype1, cmdtype2);
- wrap_here ("");
- fputs_filtered ("for ", stream);
- wrap_here ("");
- fputs_filtered ("full ", stream);
- wrap_here ("");
- fputs_filtered ("documentation.\n", stream);
- fputs_filtered ("Type \"apropos word\" to search "
- "for commands related to \"word\".\n", stream);
- fputs_filtered ("Type \"apropos -v word\" for full documentation", stream);
- wrap_here ("");
- fputs_filtered (" of commands related to \"word\".\n", stream);
- fputs_filtered ("Command name abbreviations are allowed if unambiguous.\n",
- stream);
+ gdb_printf (stream, "\nType \"help%s\" followed by %scommand name ",
+ cmdtype1, cmdtype2);
+ stream->wrap_here (0);
+ gdb_puts ("for ", stream);
+ stream->wrap_here (0);
+ gdb_puts ("full ", stream);
+ stream->wrap_here (0);
+ gdb_puts ("documentation.\n", stream);
+ gdb_puts ("Type \"apropos word\" to search "
+ "for commands related to \"word\".\n", stream);
+ gdb_puts ("Type \"apropos -v word\" for full documentation", stream);
+ stream->wrap_here (0);
+ gdb_puts (" of commands related to \"word\".\n", stream);
+ gdb_puts ("Command name abbreviations are allowed if unambiguous.\n",
+ stream);
}
static void
if (c->is_command_class_help ())
{
- fprintf_filtered (stream, "\nCommand class: %s\n\n", c->name);
+ gdb_printf (stream, "\nCommand class: %s\n\n", c->name);
help_cmd_list (cmdlist, c->theclass, true, stream);
}
}
{
if (!seen_unclassified)
{
- fprintf_filtered (stream, "\nUnclassified commands\n\n");
+ gdb_printf (stream, "\nUnclassified commands\n\n");
seen_unclassified = 1;
}
- print_help_for_command (c, true, stream);
+ print_help_for_command (*c, true, stream);
}
}
}
else
line_buffer[p - str] = '\0';
- fputs_filtered (line_buffer, stream);
+ gdb_puts (line_buffer, stream);
}
/* Print one-line help for command C.
If RECURSE is non-zero, also print one-line descriptions
of all prefixed subcommands. */
static void
-print_help_for_command (struct cmd_list_element *c,
+print_help_for_command (const cmd_list_element &c,
bool recurse, struct ui_file *stream)
{
fput_command_names_styled (c, true, " -- ", stream);
- print_doc_line (stream, c->doc, false);
- fputs_filtered ("\n", stream);
- if (!c->default_args.empty ())
+ print_doc_line (stream, c.doc, false);
+ gdb_puts ("\n", stream);
+ if (!c.default_args.empty ())
fput_alias_definition_styled (c, stream);
fput_aliases_definition_styled (c, stream);
if (recurse
- && c->is_prefix ()
- && c->abbrev_flag == 0)
+ && c.is_prefix ()
+ && c.abbrev_flag == 0)
/* Subcommands of a prefix command typically have 'all_commands'
as class. If we pass CLASS to recursive invocation,
most often we won't see anything. */
- help_cmd_list (*c->subcommands, all_commands, true, stream);
+ help_cmd_list (*c.subcommands, all_commands, true, stream);
}
/*
as this would show the (possibly very long) not very useful
list of sub-commands of the aliased command. */
print_help_for_command
- (c,
+ (*c,
recurse && (theclass != class_alias || !c->is_alias ()),
stream);
continue;
tmp_alias_str += std::string (alias->name);
if (cmd->cmd_deprecated)
- printf_filtered (_("Warning: command '%ps' (%ps) is deprecated.\n"),
- styled_string (title_style.style (),
- tmp_cmd_str.c_str ()),
- styled_string (title_style.style (),
- tmp_alias_str.c_str ()));
+ gdb_printf (_("Warning: command '%ps' (%ps) is deprecated.\n"),
+ styled_string (title_style.style (),
+ tmp_cmd_str.c_str ()),
+ styled_string (title_style.style (),
+ tmp_alias_str.c_str ()));
else
- printf_filtered (_("Warning: '%ps', an alias for the command '%ps', "
- "is deprecated.\n"),
- styled_string (title_style.style (),
- tmp_alias_str.c_str ()),
- styled_string (title_style.style (),
- tmp_cmd_str.c_str ()));
+ gdb_printf (_("Warning: '%ps', an alias for the command '%ps', "
+ "is deprecated.\n"),
+ styled_string (title_style.style (),
+ tmp_alias_str.c_str ()),
+ styled_string (title_style.style (),
+ tmp_cmd_str.c_str ()));
}
else
- printf_filtered (_("Warning: command '%ps' is deprecated.\n"),
- styled_string (title_style.style (),
- tmp_cmd_str.c_str ()));
+ gdb_printf (_("Warning: command '%ps' is deprecated.\n"),
+ styled_string (title_style.style (),
+ tmp_cmd_str.c_str ()));
/* Now display a second line indicating what the user should use instead.
If it is only the alias that is deprecated, we want to indicate the
else
replacement = cmd->replacement;
if (replacement != nullptr)
- printf_filtered (_("Use '%ps'.\n\n"),
- styled_string (title_style.style (),
- replacement));
+ gdb_printf (_("Use '%ps'.\n\n"),
+ styled_string (title_style.style (),
+ replacement));
else
- printf_filtered (_("No alternative known.\n\n"));
+ gdb_printf (_("No alternative known.\n\n"));
/* We've warned you, now we'll keep quiet. */
if (alias != nullptr)
{
if (!cmd->is_command_class_help ())
{
- gdb::optional<scoped_restore_tmpl<int>> restore_suppress;
+ gdb::optional<scoped_restore_tmpl<bool>> restore_suppress;
if (cmd->suppress_notification != NULL)
- restore_suppress.emplace (cmd->suppress_notification, 1);
+ restore_suppress.emplace (cmd->suppress_notification, true);
cmd->func (args, from_tty, cmd);
}