Add add_cmd function overloads

This adds two add_cmd overloads: one whose callback takes a const char *,
and one that doesn't accept a function at all.  The no-function overload
was introduced to avoid ambiguity when NULL was passed as the function.

Long term the goal is for all commands to take const arguments, and
for the non-const variants to be removed entirely.

gdb/ChangeLog
2017-09-27  Tom Tromey  <tom@tromey.com>

	* cli/cli-decode.c (add_cmd, set_cmd_cfunc): New function
	overloads.
	(do_add_cmd): Rename from add_cmd.  Don't call set_cmd_cfunc.
	(do_const_cfunc): New function.
	(cmd_cfunc_eq): New overload.
	(cli_user_command_p): Check do_const_cfunc.
	* cli/cli-decode.h (struct cmd_list_element) <function>: New field
	const_cfunc.
	* command.h (add_cmd): Add const overload and no-function
	overload.
	(set_cmd_cfunc): Add const overload.
	(cmd_const_cfunc_ftype): Declare.
	(cmd_cfunc_eq): Add const overload.
	* breakpoint.c, cli-cmds.c, cli-dump.c, guile/scm-cmd.c,
	python/py-cmd.c, target.c, tracepoint.c: Use no-function add_cmd
	overload.
This commit is contained in:
Tom Tromey 2017-09-09 20:51:33 -06:00
parent a9bbfbd85f
commit 0450cc4ce8
11 changed files with 124 additions and 31 deletions

View file

@ -1,3 +1,22 @@
2017-09-27 Tom Tromey <tom@tromey.com>
* cli/cli-decode.c (add_cmd, set_cmd_cfunc): New function
overloads.
(do_add_cmd): Rename from add_cmd. Don't call set_cmd_cfunc.
(do_const_cfunc): New function.
(cmd_cfunc_eq): New overload.
(cli_user_command_p): Check do_const_cfunc.
* cli/cli-decode.h (struct cmd_list_element) <function>: New field
const_cfunc.
* command.h (add_cmd): Add const overload and no-function
overload.
(set_cmd_cfunc): Add const overload.
(cmd_const_cfunc_ftype): Declare.
(cmd_cfunc_eq): Add const overload.
* breakpoint.c, cli-cmds.c, cli-dump.c, guile/scm-cmd.c,
python/py-cmd.c, target.c, tracepoint.c: Use no-function add_cmd
overload.
2017-09-27 Tom Tromey <tom@tromey.com> 2017-09-27 Tom Tromey <tom@tromey.com>
* macroexp.c (get_next_token_for_substitution): New function. * macroexp.c (get_next_token_for_substitution): New function.

View file

@ -15414,13 +15414,13 @@ add_catch_command (const char *name, const char *docstring,
{ {
struct cmd_list_element *command; struct cmd_list_element *command;
command = add_cmd (name, class_breakpoint, NULL, docstring, command = add_cmd (name, class_breakpoint, docstring,
&catch_cmdlist); &catch_cmdlist);
set_cmd_sfunc (command, sfunc); set_cmd_sfunc (command, sfunc);
set_cmd_context (command, user_data_catch); set_cmd_context (command, user_data_catch);
set_cmd_completer (command, completer); set_cmd_completer (command, completer);
command = add_cmd (name, class_breakpoint, NULL, docstring, command = add_cmd (name, class_breakpoint, docstring,
&tcatch_cmdlist); &tcatch_cmdlist);
set_cmd_sfunc (command, sfunc); set_cmd_sfunc (command, sfunc);
set_cmd_context (command, user_data_tcatch); set_cmd_context (command, user_data_tcatch);

View file

@ -1693,28 +1693,28 @@ _initialize_cli_cmds (void)
/* Define the classes of commands. /* Define the classes of commands.
They will appear in the help list in alphabetical order. */ They will appear in the help list in alphabetical order. */
add_cmd ("internals", class_maintenance, NULL, _("\ add_cmd ("internals", class_maintenance, _("\
Maintenance commands.\n\ Maintenance commands.\n\
Some gdb commands are provided just for use by gdb maintainers.\n\ Some gdb commands are provided just for use by gdb maintainers.\n\
These commands are subject to frequent change, and may not be as\n\ These commands are subject to frequent change, and may not be as\n\
well documented as user commands."), well documented as user commands."),
&cmdlist); &cmdlist);
add_cmd ("obscure", class_obscure, NULL, _("Obscure features."), &cmdlist); add_cmd ("obscure", class_obscure, _("Obscure features."), &cmdlist);
add_cmd ("aliases", class_alias, NULL, add_cmd ("aliases", class_alias,
_("Aliases of other commands."), &cmdlist); _("Aliases of other commands."), &cmdlist);
add_cmd ("user-defined", class_user, NULL, _("\ add_cmd ("user-defined", class_user, _("\
User-defined commands.\n\ User-defined commands.\n\
The commands in this class are those defined by the user.\n\ The commands in this class are those defined by the user.\n\
Use the \"define\" command to define a command."), &cmdlist); Use the \"define\" command to define a command."), &cmdlist);
add_cmd ("support", class_support, NULL, _("Support facilities."), &cmdlist); add_cmd ("support", class_support, _("Support facilities."), &cmdlist);
if (!dbx_commands) if (!dbx_commands)
add_cmd ("status", class_info, NULL, _("Status inquiries."), &cmdlist); add_cmd ("status", class_info, _("Status inquiries."), &cmdlist);
add_cmd ("files", class_files, NULL, _("Specifying and examining files."), add_cmd ("files", class_files, _("Specifying and examining files."),
&cmdlist); &cmdlist);
add_cmd ("breakpoints", class_breakpoint, NULL, add_cmd ("breakpoints", class_breakpoint,
_("Making program stop at certain points."), &cmdlist); _("Making program stop at certain points."), &cmdlist);
add_cmd ("data", class_vars, NULL, _("Examining data."), &cmdlist); add_cmd ("data", class_vars, _("Examining data."), &cmdlist);
add_cmd ("stack", class_stack, NULL, _("\ add_cmd ("stack", class_stack, _("\
Examining the stack.\n\ Examining the stack.\n\
The stack is made up of stack frames. Gdb assigns numbers to stack frames\n\ The stack is made up of stack frames. Gdb assigns numbers to stack frames\n\
counting from zero for the innermost (currently executing) frame.\n\n\ counting from zero for the innermost (currently executing) frame.\n\n\
@ -1723,7 +1723,7 @@ Variable lookups are done with respect to the selected frame.\n\
When the program being debugged stops, gdb selects the innermost frame.\n\ When the program being debugged stops, gdb selects the innermost frame.\n\
The commands below can be used to select other frames by number or address."), The commands below can be used to select other frames by number or address."),
&cmdlist); &cmdlist);
add_cmd ("running", class_run, NULL, _("Running the program."), &cmdlist); add_cmd ("running", class_run, _("Running the program."), &cmdlist);
/* Define general commands. */ /* Define general commands. */

View file

@ -103,7 +103,7 @@ print_help_for_command (struct cmd_list_element *c, const char *prefix,
static void static void
do_cfunc (struct cmd_list_element *c, char *args, int from_tty) do_cfunc (struct cmd_list_element *c, char *args, int from_tty)
{ {
c->function.cfunc (args, from_tty); /* Ok. */ c->function.cfunc (args, from_tty);
} }
void void
@ -113,13 +113,29 @@ set_cmd_cfunc (struct cmd_list_element *cmd, cmd_cfunc_ftype *cfunc)
cmd->func = NULL; cmd->func = NULL;
else else
cmd->func = do_cfunc; cmd->func = do_cfunc;
cmd->function.cfunc = cfunc; /* Ok. */ cmd->function.cfunc = cfunc;
}
static void
do_const_cfunc (struct cmd_list_element *c, char *args, int from_tty)
{
c->function.const_cfunc (args, from_tty);
}
void
set_cmd_cfunc (struct cmd_list_element *cmd, cmd_const_cfunc_ftype *cfunc)
{
if (cfunc == NULL)
cmd->func = NULL;
else
cmd->func = do_const_cfunc;
cmd->function.const_cfunc = cfunc;
} }
static void static void
do_sfunc (struct cmd_list_element *c, char *args, int from_tty) do_sfunc (struct cmd_list_element *c, char *args, int from_tty)
{ {
c->function.sfunc (args, from_tty, c); /* Ok. */ c->function.sfunc (args, from_tty, c);
} }
void void
@ -129,7 +145,7 @@ set_cmd_sfunc (struct cmd_list_element *cmd, cmd_sfunc_ftype *sfunc)
cmd->func = NULL; cmd->func = NULL;
else else
cmd->func = do_sfunc; cmd->func = do_sfunc;
cmd->function.sfunc = sfunc; /* Ok. */ cmd->function.sfunc = sfunc;
} }
int int
@ -138,6 +154,12 @@ cmd_cfunc_eq (struct cmd_list_element *cmd, cmd_cfunc_ftype *cfunc)
return cmd->func == do_cfunc && cmd->function.cfunc == cfunc; return cmd->func == do_cfunc && cmd->function.cfunc == cfunc;
} }
int
cmd_cfunc_eq (struct cmd_list_element *cmd, cmd_const_cfunc_ftype *cfunc)
{
return cmd->func == do_const_cfunc && cmd->function.const_cfunc == cfunc;
}
void void
set_cmd_context (struct cmd_list_element *cmd, void *context) set_cmd_context (struct cmd_list_element *cmd, void *context)
{ {
@ -189,8 +211,8 @@ set_cmd_completer_handle_brkchars (struct cmd_list_element *cmd,
Returns a pointer to the added command (not necessarily the head Returns a pointer to the added command (not necessarily the head
of *LIST). */ of *LIST). */
struct cmd_list_element * static struct cmd_list_element *
add_cmd (const char *name, enum command_class theclass, cmd_cfunc_ftype *fun, do_add_cmd (const char *name, enum command_class theclass,
const char *doc, struct cmd_list_element **list) const char *doc, struct cmd_list_element **list)
{ {
struct cmd_list_element *c = XNEW (struct cmd_list_element); struct cmd_list_element *c = XNEW (struct cmd_list_element);
@ -229,7 +251,6 @@ add_cmd (const char *name, enum command_class theclass, cmd_cfunc_ftype *fun,
c->name = name; c->name = name;
c->theclass = theclass; c->theclass = theclass;
set_cmd_cfunc (c, fun);
set_cmd_context (c, NULL); set_cmd_context (c, NULL);
c->doc = doc; c->doc = doc;
c->cmd_deprecated = 0; c->cmd_deprecated = 0;
@ -259,6 +280,35 @@ add_cmd (const char *name, enum command_class theclass, cmd_cfunc_ftype *fun,
return c; return c;
} }
struct cmd_list_element *
add_cmd (const char *name, enum command_class theclass, cmd_cfunc_ftype *fun,
const char *doc, struct cmd_list_element **list)
{
cmd_list_element *result = do_add_cmd (name, theclass, doc, list);
set_cmd_cfunc (result, fun);
return result;
}
struct cmd_list_element *
add_cmd (const char *name, enum command_class theclass,
const char *doc, struct cmd_list_element **list)
{
cmd_list_element *result = do_add_cmd (name, theclass, doc, list);
result->func = NULL;
result->function.cfunc = NULL; /* Ok. */
return result;
}
struct cmd_list_element *
add_cmd (const char *name, enum command_class theclass,
cmd_const_cfunc_ftype *fun,
const char *doc, struct cmd_list_element **list)
{
cmd_list_element *result = do_add_cmd (name, theclass, doc, list);
set_cmd_cfunc (result, fun);
return result;
}
/* Deprecates a command CMD. /* Deprecates a command CMD.
REPLACEMENT is the name of the command which should be used in REPLACEMENT is the name of the command which should be used in
place of this command, or NULL if no such command exists. place of this command, or NULL if no such command exists.
@ -301,7 +351,7 @@ add_alias_cmd (const char *name, cmd_list_element *old,
return 0; return 0;
} }
struct cmd_list_element *c = add_cmd (name, theclass, NULL, old->doc, list); struct cmd_list_element *c = add_cmd (name, theclass, old->doc, list);
/* If OLD->DOC can be freed, we should make another copy. */ /* If OLD->DOC can be freed, we should make another copy. */
if (old->doc_allocated) if (old->doc_allocated)
@ -419,7 +469,7 @@ add_set_or_show_cmd (const char *name,
const char *doc, const char *doc,
struct cmd_list_element **list) struct cmd_list_element **list)
{ {
struct cmd_list_element *c = add_cmd (name, theclass, NULL, doc, list); struct cmd_list_element *c = add_cmd (name, theclass, doc, list);
gdb_assert (type == set_cmd || type == show_cmd); gdb_assert (type == set_cmd || type == show_cmd);
c->type = type; c->type = type;
@ -1909,5 +1959,6 @@ int
cli_user_command_p (struct cmd_list_element *cmd) cli_user_command_p (struct cmd_list_element *cmd)
{ {
return (cmd->theclass == class_user return (cmd->theclass == class_user
&& (cmd->func == do_cfunc || cmd->func == do_sfunc)); && (cmd->func == do_cfunc || cmd->func == do_sfunc
|| cmd->func == do_const_cfunc));
} }

View file

@ -114,6 +114,8 @@ struct cmd_list_element
{ {
/* If type is not_set_cmd, call it like this: */ /* If type is not_set_cmd, call it like this: */
cmd_cfunc_ftype *cfunc; cmd_cfunc_ftype *cfunc;
/* ... or like this. */
cmd_const_cfunc_ftype *const_cfunc;
/* If type is set_cmd or show_cmd, first set the variables, /* If type is set_cmd or show_cmd, first set the variables,
and then call this: */ and then call this: */
cmd_sfunc_ftype *sfunc; cmd_sfunc_ftype *sfunc;

View file

@ -360,7 +360,7 @@ add_dump_command (const char *name,
struct cmd_list_element *c; struct cmd_list_element *c;
struct dump_context *d; struct dump_context *d;
c = add_cmd (name, all_commands, NULL, descr, &dump_cmdlist); c = add_cmd (name, all_commands, descr, &dump_cmdlist);
c->completer = filename_completer; c->completer = filename_completer;
d = XNEW (struct dump_context); d = XNEW (struct dump_context);
d->func = func; d->func = func;
@ -368,7 +368,7 @@ add_dump_command (const char *name,
set_cmd_context (c, d); set_cmd_context (c, d);
c->func = call_dump_func; c->func = call_dump_func;
c = add_cmd (name, all_commands, NULL, descr, &append_cmdlist); c = add_cmd (name, all_commands, descr, &append_cmdlist);
c->completer = filename_completer; c->completer = filename_completer;
d = XNEW (struct dump_context); d = XNEW (struct dump_context);
d->func = func; d->func = func;

View file

@ -117,6 +117,7 @@ var_types;
struct cmd_list_element; struct cmd_list_element;
typedef void cmd_cfunc_ftype (char *args, int from_tty); typedef void cmd_cfunc_ftype (char *args, int from_tty);
typedef void cmd_const_cfunc_ftype (const char *args, int from_tty);
/* This structure specifies notifications to be suppressed by a cli /* This structure specifies notifications to be suppressed by a cli
command interpreter. */ command interpreter. */
@ -140,6 +141,19 @@ extern struct cmd_list_element *add_cmd (const char *, enum command_class,
const char *, const char *,
struct cmd_list_element **); struct cmd_list_element **);
/* Const-correct variant of the above. */
extern struct cmd_list_element *add_cmd (const char *, enum command_class,
cmd_const_cfunc_ftype *fun,
const char *,
struct cmd_list_element **);
/* Like add_cmd, but no command function is specified. */
extern struct cmd_list_element *add_cmd (const char *, enum command_class,
const char *,
struct cmd_list_element **);
extern struct cmd_list_element *add_alias_cmd (const char *, const char *, extern struct cmd_list_element *add_alias_cmd (const char *, const char *,
enum command_class, int, enum command_class, int,
struct cmd_list_element **); struct cmd_list_element **);
@ -171,6 +185,11 @@ extern struct cmd_list_element *add_abbrev_prefix_cmd (const char *,
extern void set_cmd_cfunc (struct cmd_list_element *cmd, extern void set_cmd_cfunc (struct cmd_list_element *cmd,
cmd_cfunc_ftype *cfunc); cmd_cfunc_ftype *cfunc);
/* Const-correct variant of the above. */
extern void set_cmd_cfunc (struct cmd_list_element *cmd,
cmd_const_cfunc_ftype *cfunc);
typedef void cmd_sfunc_ftype (char *args, int from_tty, typedef void cmd_sfunc_ftype (char *args, int from_tty,
struct cmd_list_element *c); struct cmd_list_element *c);
extern void set_cmd_sfunc (struct cmd_list_element *cmd, extern void set_cmd_sfunc (struct cmd_list_element *cmd,
@ -205,6 +224,8 @@ extern void set_cmd_completer_handle_brkchars (struct cmd_list_element *,
around in cmd objects to test the value of the commands sfunc(). */ around in cmd objects to test the value of the commands sfunc(). */
extern int cmd_cfunc_eq (struct cmd_list_element *cmd, extern int cmd_cfunc_eq (struct cmd_list_element *cmd,
cmd_cfunc_ftype *cfun); cmd_cfunc_ftype *cfun);
extern int cmd_cfunc_eq (struct cmd_list_element *cmd,
cmd_const_cfunc_ftype *cfun);
/* Each command object has a local context attached to it. */ /* Each command object has a local context attached to it. */
extern void set_cmd_context (struct cmd_list_element *cmd, extern void set_cmd_context (struct cmd_list_element *cmd,

View file

@ -774,7 +774,7 @@ gdbscm_register_command_x (SCM self)
else else
{ {
cmd = add_cmd (c_smob->cmd_name, c_smob->cmd_class, cmd = add_cmd (c_smob->cmd_name, c_smob->cmd_class,
NULL, c_smob->doc, cmd_list); c_smob->doc, cmd_list);
} }
} }
CATCH (except, RETURN_MASK_ALL) CATCH (except, RETURN_MASK_ALL)

View file

@ -612,7 +612,7 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw)
pfx_name, allow_unknown, cmd_list); pfx_name, allow_unknown, cmd_list);
} }
else else
cmd = add_cmd (cmd_name, (enum command_class) cmdtype, NULL, cmd = add_cmd (cmd_name, (enum command_class) cmdtype,
docstring, cmd_list); docstring, cmd_list);
/* There appears to be no API to set this. */ /* There appears to be no API to set this. */

View file

@ -386,7 +386,7 @@ Remaining arguments are interpreted by the target protocol. For more\n\
information on the arguments for a particular protocol, type\n\ information on the arguments for a particular protocol, type\n\
`help target ' followed by the protocol name."), `help target ' followed by the protocol name."),
&targetlist, "target ", 0, &cmdlist); &targetlist, "target ", 0, &cmdlist);
c = add_cmd (t->to_shortname, no_class, NULL, t->to_doc, &targetlist); c = add_cmd (t->to_shortname, no_class, t->to_doc, &targetlist);
set_cmd_sfunc (c, open_target); set_cmd_sfunc (c, open_target);
set_cmd_context (c, t); set_cmd_context (c, t);
if (completer != NULL) if (completer != NULL)
@ -411,7 +411,7 @@ add_deprecated_target_alias (struct target_ops *t, const char *alias)
/* If we use add_alias_cmd, here, we do not get the deprecated warning, /* If we use add_alias_cmd, here, we do not get the deprecated warning,
see PR cli/15104. */ see PR cli/15104. */
c = add_cmd (alias, no_class, NULL, t->to_doc, &targetlist); c = add_cmd (alias, no_class, t->to_doc, &targetlist);
set_cmd_sfunc (c, open_target); set_cmd_sfunc (c, open_target);
set_cmd_context (c, t); set_cmd_context (c, t);
alt = xstrprintf ("target %s", t->to_shortname); alt = xstrprintf ("target %s", t->to_shortname);

View file

@ -4203,7 +4203,7 @@ _initialize_tracepoint (void)
add_info ("scope", info_scope_command, add_info ("scope", info_scope_command,
_("List the variables local to a scope")); _("List the variables local to a scope"));
add_cmd ("tracepoints", class_trace, NULL, add_cmd ("tracepoints", class_trace,
_("Tracing of program execution without stopping the program."), _("Tracing of program execution without stopping the program."),
&cmdlist); &cmdlist);