/* Handle lists of commands, their decoding and documentation, for GDB.
- Copyright 1986, 1989, 1990, 1991, 1998, 2000, 2001
- Free Software Foundation, Inc.
+
+ Copyright 1986, 1989, 1990, 1991, 1998, 2000, 2001, 2002 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 "symtab.h"
#include <ctype.h>
#include "gdb_regex.h"
+#include "gdb_string.h"
-#ifdef UI_OUT
#include "ui-out.h"
-#endif
#include "cli/cli-cmds.h"
#include "cli/cli-decode.h"
+#include "gdb_assert.h"
+
/* Prototypes for local functions */
static void undef_cmd_error (char *, char *);
static void help_all (struct ui_file *stream);
\f
+/* Set the callback function for the specified command. For each both
+ the commands callback and func() are set. The latter set to a
+ bounce function (unless cfunc / sfunc is NULL that is). */
+
+static void
+do_cfunc (struct cmd_list_element *c, char *args, int from_tty)
+{
+ c->function.cfunc (args, from_tty); /* Ok. */
+}
+
+void
+set_cmd_cfunc (struct cmd_list_element *cmd, cmd_cfunc_ftype *cfunc)
+{
+ if (cfunc == NULL)
+ cmd->func = NULL;
+ else
+ cmd->func = do_cfunc;
+ cmd->function.cfunc = cfunc; /* Ok. */
+}
+
+static void
+do_sfunc (struct cmd_list_element *c, char *args, int from_tty)
+{
+ c->function.sfunc (args, from_tty, c); /* Ok. */
+}
+
+void
+set_cmd_sfunc (struct cmd_list_element *cmd, cmd_sfunc_ftype *sfunc)
+{
+ if (sfunc == NULL)
+ cmd->func = NULL;
+ else
+ cmd->func = do_sfunc;
+ cmd->function.sfunc = sfunc; /* Ok. */
+}
+
+int
+cmd_cfunc_eq (struct cmd_list_element *cmd,
+ void (*cfunc) (char *args, int from_tty))
+{
+ return cmd->func == do_cfunc && cmd->function.cfunc == cfunc;
+}
+
+void
+set_cmd_context (struct cmd_list_element *cmd, void *context)
+{
+ cmd->context = context;
+}
+
+void *
+get_cmd_context (struct cmd_list_element *cmd)
+{
+ return cmd->context;
+}
+
+enum cmd_types
+cmd_type (struct cmd_list_element *cmd)
+{
+ return cmd->type;
+}
+
+void
+set_cmd_completer (struct cmd_list_element *cmd,
+ char **(*completer) (char *text, char *word))
+{
+ cmd->completer = completer; /* Ok. */
+}
+
+
/* Add element named NAME.
CLASS is the top level category into which commands are broken down
for "help" purposes.
c->name = name;
c->class = class;
- c->function.cfunc = fun;
+ set_cmd_cfunc (c, fun);
+ set_cmd_context (c, NULL);
c->doc = doc;
c->flags = 0;
c->replacement = NULL;
c->prefixname = NULL;
c->allow_unknown = 0;
c->abbrev_flag = 0;
- c->completer = make_symbol_completion_list;
+ set_cmd_completer (c, make_symbol_completion_list);
c->type = not_set_cmd;
c->var = NULL;
c->var_type = var_boolean;
return c;
}
-/* Same as above, except that the abbrev_flag is set. */
-/* Note: Doesn't seem to be used anywhere currently. */
-
-struct cmd_list_element *
-add_abbrev_cmd (char *name, enum command_class class, void (*fun) (char *, int),
- char *doc, struct cmd_list_element **list)
-{
- register struct cmd_list_element *c
- = add_cmd (name, class, fun, doc, list);
-
- c->abbrev_flag = 1;
- return c;
-}
-
/* Deprecates a command CMD.
REPLACEMENT is the name of the command which should be used in place
of this command, or NULL if no such command exists.
return 0;
}
- c = add_cmd (name, class, old->function.cfunc, old->doc, list);
+ c = add_cmd (name, class, NULL, old->doc, list);
+ /* NOTE: Both FUNC and all the FUNCTIONs need to be copied. */
+ c->func = old->func;
+ c->function = old->function;
c->prefixlist = old->prefixlist;
c->prefixname = old->prefixname;
c->allow_unknown = old->allow_unknown;
{
}
-/* Add element named NAME to command list LIST (the list for set
+/* Add element named NAME to command list LIST (the list for set/show
or some sublist thereof).
+ TYPE is set_cmd or show_cmd.
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.
DOC is the documentation string. */
+static struct cmd_list_element *
+add_set_or_show_cmd (char *name,
+ enum cmd_types type,
+ enum command_class class,
+ var_types var_type,
+ void *var,
+ char *doc,
+ struct cmd_list_element **list)
+{
+ struct cmd_list_element *c = add_cmd (name, class, NULL, doc, list);
+ gdb_assert (type == set_cmd || type == show_cmd);
+ c->type = type;
+ c->var_type = var_type;
+ c->var = var;
+ /* This needs to be something besides NULL so that this isn't
+ treated as a help class. */
+ set_cmd_sfunc (c, empty_sfunc);
+ return c;
+}
+
+/* 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 and SHOW_DOC are the documentation strings.
+ SET_RESULT and SHOW_RESULT, if not NULL, are set to the resulting
+ command structures. */
+
+void
+add_setshow_cmd_full (char *name,
+ enum command_class class,
+ var_types var_type, void *var,
+ char *set_doc, char *show_doc,
+ cmd_sfunc_ftype *set_func, cmd_sfunc_ftype *show_func,
+ struct cmd_list_element **set_list,
+ struct cmd_list_element **show_list,
+ struct cmd_list_element **set_result,
+ struct cmd_list_element **show_result)
+{
+ struct cmd_list_element *set;
+ struct cmd_list_element *show;
+ set = add_set_or_show_cmd (name, set_cmd, class, var_type, var,
+ set_doc, set_list);
+ if (set_func != NULL)
+ set_cmd_sfunc (set, set_func);
+ show = add_set_or_show_cmd (name, show_cmd, class, var_type, var,
+ show_doc, show_list);
+ if (show_func != NULL)
+ set_cmd_sfunc (show, show_func);
+
+ if (set_result != NULL)
+ *set_result = set;
+ if (show_result != NULL)
+ *show_result = show;
+}
+
+/* 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 and SHOW_DOC are the documentation strings. */
+
+void
+add_setshow_cmd (char *name,
+ enum command_class class,
+ var_types var_type, void *var,
+ char *set_doc, char *show_doc,
+ cmd_sfunc_ftype *set_func, cmd_sfunc_ftype *show_func,
+ struct cmd_list_element **set_list,
+ struct cmd_list_element **show_list)
+{
+ add_setshow_cmd_full (name, class, var_type, var, set_doc, show_doc,
+ set_func, show_func, set_list, show_list,
+ NULL, NULL);
+}
+
struct cmd_list_element *
add_set_cmd (char *name,
enum command_class class,
char *doc,
struct cmd_list_element **list)
{
- struct cmd_list_element *c
- = add_cmd (name, class, NO_FUNCTION, doc, list);
-
- c->type = set_cmd;
- c->var_type = var_type;
- c->var = var;
- /* This needs to be something besides NO_FUNCTION so that this isn't
- treated as a help class. */
- c->function.sfunc = empty_sfunc;
- return c;
+ return add_set_or_show_cmd (name, set_cmd, class, var_type, var, doc, list);
}
/* Add element named NAME to command list LIST (the list for set
return c;
}
-/* Add element named NAME to command list LIST (the list for set
- or some sublist thereof).
- CLASS is as in add_cmd.
- VAR is address of the variable which will contain the value.
- DOC is the documentation string. */
-struct cmd_list_element *
-add_set_auto_boolean_cmd (char *name,
- enum command_class class,
- enum cmd_auto_boolean *var,
- char *doc,
- struct cmd_list_element **list)
+/* Add an auto-boolean command named NAME to both the set and show
+ command list lists. CLASS is as in add_cmd. VAR is address of the
+ variable which will contain the value. DOC is the documentation
+ string. FUNC is the corresponding callback. */
+void
+add_setshow_auto_boolean_cmd (char *name,
+ enum command_class class,
+ enum auto_boolean *var,
+ char *set_doc, char *show_doc,
+ cmd_sfunc_ftype *set_func,
+ cmd_sfunc_ftype *show_func,
+ struct cmd_list_element **set_list,
+ struct cmd_list_element **show_list)
{
static const char *auto_boolean_enums[] = { "on", "off", "auto", NULL };
struct cmd_list_element *c;
- c = add_set_cmd (name, class, var_auto_boolean, var, doc, list);
+ add_setshow_cmd_full (name, class, var_auto_boolean, var,
+ set_doc, show_doc, set_func, show_func,
+ set_list, show_list,
+ &c, NULL);
c->enums = auto_boolean_enums;
- return c;
}
-/* Add element named NAME to command list LIST (the list for set
- or some sublist thereof).
- CLASS is as in add_cmd.
- VAR is address of the variable which will contain the value.
- DOC is the documentation string. */
-struct cmd_list_element *
-add_set_boolean_cmd (char *name,
- enum command_class class,
- int *var,
- char *doc,
- struct cmd_list_element **list)
+/* 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
+ value. SET_DOC and SHOW_DOR are the documentation strings. */
+void
+add_setshow_boolean_cmd (char *name,
+ enum command_class class,
+ int *var, char *set_doc, char *show_doc,
+ cmd_sfunc_ftype *set_func,
+ cmd_sfunc_ftype *show_func,
+ struct cmd_list_element **set_list,
+ struct cmd_list_element **show_list)
{
static const char *boolean_enums[] = { "on", "off", NULL };
struct cmd_list_element *c;
- c = add_set_cmd (name, class, var_boolean, var, doc, list);
+ add_setshow_cmd_full (name, class, var_boolean, var,
+ set_doc, show_doc,
+ set_func, show_func,
+ set_list, show_list,
+ &c, NULL);
c->enums = boolean_enums;
- return c;
}
/* Where SETCMD has already been added, add the corresponding show
- command to LIST and return a pointer to the added command (not
+ command to LIST and return a pointer to the added command (not
necessarily the head of LIST). */
+/* NOTE: cagney/2002-03-17: The original version of add_show_from_set
+ used memcpy() to clone `set' into `show'. This meant that in
+ addition to all the needed fields (var, name, et.al.) some
+ unnecessary fields were copied (namely the callback function). The
+ function explictly copies relevant fields. For a `set' and `show'
+ command to share the same callback, the caller must set both
+ explicitly. */
struct cmd_list_element *
add_show_from_set (struct cmd_list_element *setcmd,
struct cmd_list_element **list)
{
- struct cmd_list_element *showcmd =
- (struct cmd_list_element *) xmalloc (sizeof (struct cmd_list_element));
- struct cmd_list_element *p;
-
- memcpy (showcmd, setcmd, sizeof (struct cmd_list_element));
- delete_cmd (showcmd->name, list);
- showcmd->type = show_cmd;
-
- /* Replace "set " at start of docstring with "show ". */
- if (setcmd->doc[0] == 'S' && setcmd->doc[1] == 'e'
- && setcmd->doc[2] == 't' && setcmd->doc[3] == ' ')
- showcmd->doc = concat ("Show ", setcmd->doc + 4, NULL);
- else
- fprintf_unfiltered (gdb_stderr, "GDB internal error: Bad docstring for set command\n");
+ char *doc;
+ const static char setstring[] = "Set ";
- if (*list == NULL || strcmp ((*list)->name, showcmd->name) >= 0)
- {
- showcmd->next = *list;
- *list = showcmd;
- }
- else
- {
- p = *list;
- while (p->next && strcmp (p->next->name, showcmd->name) <= 0)
- {
- p = p->next;
- }
- showcmd->next = p->next;
- p->next = showcmd;
- }
+ /* Create a doc string by replacing "Set " at the start of the
+ `set'' command's doco with "Show ". */
+ gdb_assert (strncmp (setcmd->doc, setstring, sizeof (setstring) - 1) == 0);
+ doc = concat ("Show ", setcmd->doc + sizeof (setstring) - 1, NULL);
- return showcmd;
+ /* Insert the basic command. */
+ return add_set_or_show_cmd (setcmd->name, show_cmd, setcmd->class,
+ setcmd->var_type, setcmd->var, doc, list);
}
/* Remove the command named NAME from the command list. */
If c->prefixlist is nonzero, we have a prefix command.
Print its documentation, then list its subcommands.
- If c->function is nonzero, we really have a command.
- Print its documentation and return.
+ If c->func is non NULL, we really have a command. Print its
+ documentation and return.
- If c->function is zero, we have a class name.
- Print its documentation (as if it were a command)
- and then set class to the number of this class
- so that the commands in the class will be listed. */
+ If c->func is NULL, we have a class name. Print its
+ documentation (as if it were a command) and then set class to the
+ number of this class so that the commands in the class will be
+ listed. */
fputs_filtered (c->doc, stream);
fputs_filtered ("\n", stream);
- if (c->prefixlist == 0 && c->function.cfunc != NULL)
+ if (c->prefixlist == 0 && c->func != NULL)
return;
fprintf_filtered (stream, "\n");
help_list (*c->prefixlist, c->prefixname, all_commands, stream);
/* If this is a class name, print all of the commands in the class */
- if (c->function.cfunc == NULL)
+ if (c->func == NULL)
help_list (cmdlist, "", c->class, stream);
if (c->hook_pre || c->hook_post)
help_cmd_list (list, class, cmdtype, (int) class >= 0, stream);
if (class == all_classes)
- fprintf_filtered (stream, "\n\
-Type \"help%s\" followed by a class name for a list of commands in that class.",
- cmdtype1);
+ {
+ fprintf_filtered (stream, "\n\
+Type \"help%s\" followed by a class name for a list of commands in ",
+ cmdtype1);
+ wrap_here ("");
+ fprintf_filtered (stream, "that class.");
+ }
- fprintf_filtered (stream, "\n\
-Type \"help%s\" followed by %scommand name for full documentation.\n\
-Command name abbreviations are allowed if unambiguous.\n",
+ 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 ("Command name abbreviations are allowed if unambiguous.\n",
+ stream);
}
static void
help_cmd_list (*c->prefixlist, all_commands, c->prefixname, 0, stream);
/* If this is a class name, print all of the commands in the class */
- else if (c->function.cfunc == NULL)
+ else if (c->func == NULL)
help_cmd_list (cmdlist, c->class, "", 0, stream);
}
}
line_buffer[p - str] = '\0';
if (islower (line_buffer[0]))
line_buffer[0] = toupper (line_buffer[0]);
-#ifdef UI_OUT
ui_out_text (uiout, line_buffer);
-#else
- fputs_filtered (line_buffer, stream);
-#endif
}
/*
{
if (c->abbrev_flag == 0 &&
(class == all_commands
- || (class == all_classes && c->function.cfunc == NULL)
- || (class == c->class && c->function.cfunc != NULL)))
+ || (class == all_classes && c->func == NULL)
+ || (class == c->class && c->func != NULL)))
{
fprintf_filtered (stream, "%s%s -- ", prefix, c->name);
print_doc_line (stream, c->doc);
*nfound = 0;
for (c = clist; c; c = c->next)
if (!strncmp (command, c->name, len)
- && (!ignore_help_classes || c->function.cfunc))
+ && (!ignore_help_classes || c->func))
{
found = c;
(*nfound)++;
/* Treating underscores as part of command words is important
so that "set args_foo()" doesn't get interpreted as
"set args _foo()". */
+ /* NOTE: cagney/2003-02-13 The `tui_active' was previously
+ `tui_version'. */
for (p = *text;
*p && (isalnum (*p) || *p == '-' || *p == '_' ||
- (tui_version &&
+#if defined(TUI)
+ (tui_active &&
(*p == '+' || *p == '<' || *p == '>' || *p == '$')) ||
+#endif
(xdb_commands && (*p == '!' || *p == '/' || *p == '?')));
p++)
;
cmdtype,
q,
*cmdtype ? " " : "",
- strlen (cmdtype) - 1,
+ (int) strlen (cmdtype) - 1,
cmdtype);
}
/* Treating underscores as part of command words is important
so that "set args_foo()" doesn't get interpreted as
"set args _foo()". */
+ /* NOTE: cagney/2003-02-13 The `tui_active' was previously
+ `tui_version'. */
for (p = text;
*p && (isalnum (*p) || *p == '-' || *p == '_' ||
- (tui_version &&
+#if defined(TUI)
+ (tui_active &&
(*p == '+' || *p == '<' || *p == '>' || *p == '$')) ||
+#endif
(xdb_commands && (*p == '!' || *p == '/' || *p == '?')));
p++)
;
for (ptr = list; ptr; ptr = ptr->next)
if (!strncmp (ptr->name, text, textlen)
&& !ptr->abbrev_flag
- && (ptr->function.cfunc
+ && (ptr->func
|| ptr->prefixlist))
{
if (matches == sizeof_matchlist)
return matchlist;
}
+
+/* check function pointer */
+int
+cmd_func_p (struct cmd_list_element *cmd)
+{
+ return (cmd->func != NULL);
+}
+
+
+/* call the command function */
+void
+cmd_func (struct cmd_list_element *cmd, char *args, int from_tty)
+{
+ if (cmd_func_p (cmd))
+ (*cmd->func) (cmd, args, from_tty);
+ else
+ error ("Invalid command");
+}
+
+