/* Handle lists of commands, their decoding and documentation, for GDB.
- Copyright 1986, 1989, 1990, 1991, 1998 Free Software Foundation, Inc.
+ Copyright 1986, 1989, 1990, 1991, 1998, 2000 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 "value.h"
#include <ctype.h>
#include "gdb_string.h"
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
+#ifdef UI_OUT
+#include "ui-out.h"
#endif
-#ifdef HAVE_WAIT_H
-#include <wait.h>
-#else
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
+#include "gdb_wait.h"
+#include "gnu-regex.h"
+/* FIXME: this should be auto-configured! */
+#ifdef __MSDOS__
+# define CANT_FORK
#endif
-#include "wait.h"
-
/* Prototypes for local functions */
-static void undef_cmd_error PARAMS ((char *, char *));
+static void undef_cmd_error (char *, char *);
+
+static void show_user (char *, int);
-static void show_user PARAMS ((char *, int));
+static void show_user_1 (struct cmd_list_element *, struct ui_file *);
-static void show_user_1 PARAMS ((struct cmd_list_element *, GDB_FILE *));
+static void make_command (char *, int);
-static void make_command PARAMS ((char *, int));
+static void shell_escape (char *, int);
-static void shell_escape PARAMS ((char *, int));
+static int parse_binary_operation (char *);
-static int parse_binary_operation PARAMS ((char *));
+static void print_doc_line (struct ui_file *, char *);
-static void print_doc_line PARAMS ((GDB_FILE *, char *));
+static struct cmd_list_element *find_cmd (char *command,
+ int len,
+ struct cmd_list_element *clist,
+ int ignore_help_classes,
+ int *nfound);
+static void apropos_cmd_helper (struct ui_file *, struct cmd_list_element *,
+ struct re_pattern_buffer *, char *);
-static struct cmd_list_element *find_cmd PARAMS ((char *command,
- int len,
- struct cmd_list_element * clist,
- int ignore_help_classes,
- int *nfound));
+static void help_all (struct ui_file *stream);
-void _initialize_command PARAMS ((void));
+void apropos_command (char *, int);
+
+void _initialize_command (void);
/* Add element named NAME.
CLASS is the top level category into which commands are broken down
of *LIST). */
struct cmd_list_element *
-add_cmd (name, class, fun, doc, list)
- char *name;
- enum command_class class;
- void (*fun) PARAMS ((char *, int));
- char *doc;
- struct cmd_list_element **list;
+add_cmd (char *name, enum command_class class, void (*fun) (char *, int),
+ char *doc, struct cmd_list_element **list)
{
register struct cmd_list_element *c
= (struct cmd_list_element *) xmalloc (sizeof (struct cmd_list_element));
c->class = class;
c->function.cfunc = fun;
c->doc = doc;
+ c->flags = 0;
+ c->replacement = NULL;
c->hook = NULL;
c->prefixlist = NULL;
c->prefixname = NULL;
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.
+
+ This function does not check to see if command REPLACEMENT exists
+ since gdb may not have gotten around to adding REPLACEMENT when this
+ function is called.
+
+ Returns a pointer to the deprecated command. */
+
+struct cmd_list_element *
+deprecate_cmd (struct cmd_list_element *cmd, char *replacement)
+{
+ cmd->flags |= (CMD_DEPRECATED | DEPRECATED_WARN_USER);
+
+ if (replacement != NULL)
+ cmd->replacement = replacement;
+ else
+ cmd->replacement = NULL;
+
+ return cmd;
+}
+
+
/* Same as above, except that the abbrev_flag is set. */
#if 0 /* Currently unused */
struct cmd_list_element *
-add_abbrev_cmd (name, class, fun, doc, list)
- char *name;
- enum command_class class;
- void (*fun) PARAMS ((char *, int));
- char *doc;
- struct cmd_list_element **list;
+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);
#endif
struct cmd_list_element *
-add_alias_cmd (name, oldname, class, abbrev_flag, list)
- char *name;
- char *oldname;
- enum command_class class;
- int abbrev_flag;
- struct cmd_list_element **list;
+add_alias_cmd (char *name, char *oldname, enum command_class class,
+ int abbrev_flag, struct cmd_list_element **list)
{
/* Must do this since lookup_cmd tries to side-effect its first arg */
char *copied_name;
of the variable containing that list. */
struct cmd_list_element *
-add_prefix_cmd (name, class, fun, doc, prefixlist, prefixname,
- allow_unknown, list)
- char *name;
- enum command_class class;
- void (*fun) PARAMS ((char *, int));
- char *doc;
- struct cmd_list_element **prefixlist;
- char *prefixname;
- int allow_unknown;
- struct cmd_list_element **list;
+add_prefix_cmd (char *name, enum command_class class, void (*fun) (char *, int),
+ char *doc, struct cmd_list_element **prefixlist,
+ char *prefixname, int allow_unknown,
+ struct cmd_list_element **list)
{
register struct cmd_list_element *c = add_cmd (name, class, fun, doc, list);
c->prefixlist = prefixlist;
/* Like add_prefix_cmd but sets the abbrev_flag on the new command. */
struct cmd_list_element *
-add_abbrev_prefix_cmd (name, class, fun, doc, prefixlist, prefixname,
- allow_unknown, list)
- char *name;
- enum command_class class;
- void (*fun) PARAMS ((char *, int));
- char *doc;
- struct cmd_list_element **prefixlist;
- char *prefixname;
- int allow_unknown;
- struct cmd_list_element **list;
+add_abbrev_prefix_cmd (char *name, enum command_class class,
+ void (*fun) (char *, int), char *doc,
+ struct cmd_list_element **prefixlist, char *prefixname,
+ int allow_unknown, struct cmd_list_element **list)
{
register struct cmd_list_element *c = add_cmd (name, class, fun, doc, list);
c->prefixlist = prefixlist;
/* This is an empty "cfunc". */
void
-not_just_help_class_command (args, from_tty)
- char *args;
- int from_tty;
+not_just_help_class_command (char *args, int from_tty)
{
}
/* This is an empty "sfunc". */
-static void empty_sfunc PARAMS ((char *, int, struct cmd_list_element *));
+static void empty_sfunc (char *, int, struct cmd_list_element *);
static void
-empty_sfunc (args, from_tty, c)
- char *args;
- int from_tty;
- struct cmd_list_element *c;
+empty_sfunc (char *args, int from_tty, struct cmd_list_element *c)
{
}
DOC is the documentation string. */
struct cmd_list_element *
-add_set_cmd (name, class, var_type, var, doc, list)
- char *name;
- enum command_class class;
- var_types var_type;
- char *var;
- char *doc;
- struct cmd_list_element **list;
+add_set_cmd (char *name,
+ 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, NO_FUNCTION, doc, list);
DOC is the documentation string. */
struct cmd_list_element *
-add_set_enum_cmd (name, class, enumlist, var, doc, list)
- char *name;
- enum command_class class;
- char *enumlist[];
- char *var;
- char *doc;
- struct cmd_list_element **list;
+add_set_enum_cmd (char *name,
+ enum command_class class,
+ const char *enumlist[],
+ const char **var,
+ char *doc,
+ struct cmd_list_element **list)
{
struct cmd_list_element *c
= add_set_cmd (name, class, var_enum, var, doc, list);
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)
+{
+ 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);
+ c->enums = auto_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
necessarily the head of LIST). */
struct cmd_list_element *
-add_show_from_set (setcmd, list)
- struct cmd_list_element *setcmd;
- struct cmd_list_element **list;
+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));
/* Remove the command named NAME from the command list. */
void
-delete_cmd (name, list)
- char *name;
- struct cmd_list_element **list;
+delete_cmd (char *name, struct cmd_list_element **list)
{
register struct cmd_list_element *c;
struct cmd_list_element *p;
c = c->next;
}
}
+/* Recursively walk the commandlist structures, and print out the
+ documentation of commands that match our regex in either their
+ name, or their documentation.
+*/
+static void
+apropos_cmd_helper (struct ui_file *stream, struct cmd_list_element *commandlist,
+ struct re_pattern_buffer *regex, char *prefix)
+{
+ register struct cmd_list_element *c;
+ int returnvalue=1; /*Needed to avoid double printing*/
+ /* Walk through the commands */
+ for (c=commandlist;c;c=c->next)
+ {
+ if (c->name != NULL)
+ {
+ /* Try to match against the name*/
+ returnvalue=re_search(regex,c->name,strlen(c->name),0,strlen(c->name),NULL);
+ if (returnvalue >= 0)
+ {
+ /* Stolen from help_cmd_list. We don't directly use
+ * help_cmd_list because it doesn't let us print out
+ * single commands
+ */
+ fprintf_filtered (stream, "%s%s -- ", prefix, c->name);
+ print_doc_line (stream, c->doc);
+ fputs_filtered ("\n", stream);
+ returnvalue=0; /*Set this so we don't print it again.*/
+ }
+ }
+ if (c->doc != NULL && returnvalue != 0)
+ {
+ /* Try to match against documentation */
+ if (re_search(regex,c->doc,strlen(c->doc),0,strlen(c->doc),NULL) >=0)
+ {
+ /* Stolen from help_cmd_list. We don't directly use
+ * help_cmd_list because it doesn't let us print out
+ * single commands
+ */
+ fprintf_filtered (stream, "%s%s -- ", prefix, c->name);
+ print_doc_line (stream, c->doc);
+ fputs_filtered ("\n", stream);
+ }
+ }
+ /* Check if this command has subcommands */
+ if (c->prefixlist != NULL)
+ {
+ /* Recursively call ourselves on the subcommand list,
+ passing the right prefix in.
+ */
+ apropos_cmd_helper(stream,*c->prefixlist,regex,c->prefixname);
+ }
+ }
+}
+/* Search through names of commands and documentations for a certain
+ regular expression.
+*/
+void
+apropos_command (char *searchstr, int from_tty)
+{
+ extern struct cmd_list_element *cmdlist; /*This is the main command list*/
+ regex_t pattern;
+ char *pattern_fastmap;
+ char errorbuffer[512];
+ pattern_fastmap=calloc(256,sizeof(char));
+ if (searchstr == NULL)
+ error("REGEXP string is empty");
+
+ if (regcomp(&pattern,searchstr,REG_ICASE) == 0)
+ {
+ pattern.fastmap=pattern_fastmap;
+ re_compile_fastmap(&pattern);
+ apropos_cmd_helper(gdb_stdout,cmdlist,&pattern,"");
+ }
+ else
+ {
+ regerror(regcomp(&pattern,searchstr,REG_ICASE),NULL,errorbuffer,512);
+ error("Error in regular expression:%s",errorbuffer);
+ }
+ free(pattern_fastmap);
+}
+
/* This command really has to deal with two things:
* 1) I want documentation on *this string* (usually called by
*/
void
-help_cmd (command, stream)
- char *command;
- GDB_FILE *stream;
+help_cmd (char *command, struct ui_file *stream)
{
struct cmd_list_element *c;
extern struct cmd_list_element *cmdlist;
return;
}
+ if (strcmp (command, "all") == 0)
+ {
+ help_all (stream);
+ return;
+ }
+
c = lookup_cmd (&command, cmdlist, "", 0, 0);
if (c == 0)
* If you call this routine with a class >= 0, it recurses.
*/
void
-help_list (list, cmdtype, class, stream)
- struct cmd_list_element *list;
- char *cmdtype;
- enum command_class class;
- GDB_FILE *stream;
+help_list (struct cmd_list_element *list, char *cmdtype,
+ enum command_class class, struct ui_file *stream)
{
int len;
char *cmdtype1, *cmdtype2;
cmdtype1, cmdtype2);
}
+static void
+help_all (struct ui_file *stream)
+{
+ struct cmd_list_element *c;
+ extern struct cmd_list_element *cmdlist;
+
+ for (c = cmdlist; c; c = c->next)
+ {
+ if (c->abbrev_flag)
+ continue;
+ /* If this is a prefix command, print it's subcommands */
+ if (c->prefixlist)
+ 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)
+ help_cmd_list (cmdlist, c->class, "", 0, stream);
+ }
+}
+
/* Print only the first line of STR on STREAM. */
static void
-print_doc_line (stream, str)
- GDB_FILE *stream;
- char *str;
+print_doc_line (struct ui_file *stream, char *str)
{
static char *line_buffer = 0;
static int line_size;
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
}
/*
* is at the low level, not the high-level).
*/
void
-help_cmd_list (list, class, prefix, recurse, stream)
- struct cmd_list_element *list;
- enum command_class class;
- char *prefix;
- int recurse;
- GDB_FILE *stream;
+help_cmd_list (struct cmd_list_element *list, enum command_class class,
+ char *prefix, int recurse, struct ui_file *stream)
{
register struct cmd_list_element *c;
found in nfound */
static struct cmd_list_element *
-find_cmd (command, len, clist, ignore_help_classes, nfound)
- char *command;
- int len;
- struct cmd_list_element *clist;
- int ignore_help_classes;
- int *nfound;
+find_cmd (char *command, int len, struct cmd_list_element *clist,
+ int ignore_help_classes, int *nfound)
{
struct cmd_list_element *found, *c;
the struct cmd_list_element is NULL). */
struct cmd_list_element *
-lookup_cmd_1 (text, clist, result_list, ignore_help_classes)
- char **text;
- struct cmd_list_element *clist, **result_list;
- int ignore_help_classes;
+lookup_cmd_1 (char **text, struct cmd_list_element *clist,
+ struct cmd_list_element **result_list, int ignore_help_classes)
{
char *p, *command;
int len, tmp, nfound;
struct cmd_list_element *found, *c;
+ char *line = *text;
while (**text == ' ' || **text == '\t')
(*text)++;
*text = p;
- /* If this was an abbreviation, use the base command instead. */
-
if (found->cmd_pointer)
- found = found->cmd_pointer;
-
+ {
+ /* We drop the alias (abbreviation) in favor of the command it is
+ pointing to. If the alias is deprecated, though, we need to
+ warn the user about it before we drop it. Note that while we
+ 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->flags & DEPRECATED_WARN_USER)
+ deprecated_cmd_warning (&line);
+ found = found->cmd_pointer;
+ }
/* If we found a prefix command, keep looking. */
if (found->prefixlist)
/* All this hair to move the space to the front of cmdtype */
static void
-undef_cmd_error (cmdtype, q)
- char *cmdtype, *q;
+undef_cmd_error (char *cmdtype, char *q)
{
error ("Undefined %scommand: \"%s\". Try \"help%s%.*s\".",
cmdtype,
the function field of the struct cmd_list_element is 0). */
struct cmd_list_element *
-lookup_cmd (line, list, cmdtype, allow_unknown, ignore_help_classes)
- char **line;
- struct cmd_list_element *list;
- char *cmdtype;
- int allow_unknown;
- int ignore_help_classes;
+lookup_cmd (char **line, struct cmd_list_element *list, char *cmdtype,
+ int allow_unknown, int ignore_help_classes)
{
struct cmd_list_element *last_list = 0;
struct cmd_list_element *c =
return 0;
}
+/* We are here presumably because an alias or command in *TEXT is
+ deprecated and a warning message should be generated. This function
+ decodes *TEXT and potentially generates a warning message as outlined
+ below.
+
+ Example for 'set endian big' which has a fictitious alias 'seb'.
+
+ If alias wasn't used in *TEXT, and the command is deprecated:
+ "warning: 'set endian big' is deprecated."
+
+ If alias was used, and only the alias is deprecated:
+ "warning: 'seb' an alias for the command 'set endian big' is deprecated."
+
+ If alias was used and command is deprecated (regardless of whether the
+ alias itself is deprecated:
+
+ "warning: 'set endian big' (seb) is deprecated."
+
+ After the message has been sent, clear the appropriate flags in the
+ command and/or the alias so the user is no longer bothered.
+
+*/
+void
+deprecated_cmd_warning (char **text)
+{
+ struct cmd_list_element *alias = NULL;
+ struct cmd_list_element *prefix_cmd = NULL;
+ struct cmd_list_element *cmd = NULL;
+ struct cmd_list_element *c;
+ char *type;
+
+ if (!lookup_cmd_composition (*text, &alias, &prefix_cmd, &cmd))
+ /* return if text doesn't evaluate to a command */
+ return;
+
+ if (!((alias ? (alias->flags & DEPRECATED_WARN_USER) : 0)
+ || (cmd->flags & DEPRECATED_WARN_USER) ) )
+ /* return if nothing is deprecated */
+ return;
+
+ printf_filtered ("Warning:");
+
+ if (alias && !(cmd->flags & CMD_DEPRECATED))
+ printf_filtered (" '%s', an alias for the", alias->name);
+
+ printf_filtered (" command '");
+
+ if (prefix_cmd)
+ printf_filtered ("%s", prefix_cmd->prefixname);
+
+ printf_filtered ("%s", cmd->name);
+
+ if (alias && (cmd->flags & CMD_DEPRECATED))
+ printf_filtered ("' (%s) is deprecated.\n", alias->name);
+ else
+ printf_filtered ("' is deprecated.\n");
+
+
+ /* if it is only the alias that is deprecated, we want to indicate the
+ new alias, otherwise we'll indicate the new command */
+
+ if (alias && !(cmd->flags & CMD_DEPRECATED))
+ {
+ if (alias->replacement)
+ printf_filtered ("Use '%s'.\n\n", alias->replacement);
+ else
+ printf_filtered ("No alternative known.\n\n");
+ }
+ else
+ {
+ if (cmd->replacement)
+ printf_filtered ("Use '%s'.\n\n", cmd->replacement);
+ else
+ printf_filtered ("No alternative known.\n\n");
+ }
+
+ /* We've warned you, now we'll keep quiet */
+ if (alias)
+ alias->flags &= ~DEPRECATED_WARN_USER;
+
+ cmd->flags &= ~DEPRECATED_WARN_USER;
+}
+
+
+
+/* Look up the contents of LINE as a command in the command list 'cmdlist'.
+ Return 1 on success, 0 on failure.
+
+ If LINE refers to an alias, *alias will point to that alias.
+
+ If LINE is a postfix command (i.e. one that is preceeded by a prefix
+ command) set *prefix_cmd.
+
+ Set *cmd to point to the command LINE indicates.
+
+ If any of *alias, *prefix_cmd, or *cmd cannot be determined or do not
+ exist, they are NULL when we return.
+
+*/
+int
+lookup_cmd_composition (char *text,
+ struct cmd_list_element **alias,
+ struct cmd_list_element **prefix_cmd,
+ struct cmd_list_element **cmd)
+{
+ char *p, *command;
+ int len, tmp, nfound;
+ struct cmd_list_element *cur_list;
+ struct cmd_list_element *prev_cmd;
+ *alias = NULL;
+ *prefix_cmd = NULL;
+ *cmd = NULL;
+
+ cur_list = cmdlist;
+
+ while (1)
+ {
+ /* Go through as many command lists as we need to
+ to find the command TEXT refers to. */
+
+ prev_cmd = *cmd;
+
+ while (*text == ' ' || *text == '\t')
+ (text)++;
+
+ /* Treating underscores as part of command words is important
+ so that "set args_foo()" doesn't get interpreted as
+ "set args _foo()". */
+ for (p = text;
+ *p && (isalnum (*p) || *p == '-' || *p == '_' ||
+ (tui_version &&
+ (*p == '+' || *p == '<' || *p == '>' || *p == '$')) ||
+ (xdb_commands && (*p == '!' || *p == '/' || *p == '?')));
+ p++)
+ ;
+
+ /* If nothing but whitespace, return. */
+ if (p == text)
+ return 0;
+
+ len = p - text;
+
+ /* text and p now bracket the first command word to lookup (and
+ it's length is len). We copy this into a local temporary */
+
+ command = (char *) alloca (len + 1);
+ for (tmp = 0; tmp < len; tmp++)
+ {
+ char x = text[tmp];
+ command[tmp] = x;
+ }
+ command[len] = '\0';
+
+ /* Look it up. */
+ *cmd = 0;
+ nfound = 0;
+ *cmd = find_cmd (command, len, cur_list, 1, &nfound);
+
+ /* We didn't find the command in the entered case, so lower case it
+ and search again.
+ */
+ if (!*cmd || nfound == 0)
+ {
+ for (tmp = 0; tmp < len; tmp++)
+ {
+ char x = command[tmp];
+ command[tmp] = isupper (x) ? tolower (x) : x;
+ }
+ *cmd = find_cmd (command, len, cur_list, 1, &nfound);
+ }
+
+ if (*cmd == (struct cmd_list_element *) -1)
+ {
+ return 0; /* ambiguous */
+ }
+
+ if (*cmd == NULL)
+ return 0; /* nothing found */
+ else
+ {
+ if ((*cmd)->cmd_pointer)
+ {
+ /* cmd was actually an alias, we note that an alias was used
+ (by assigning *alais) and we set *cmd.
+ */
+ *alias = *cmd;
+ *cmd = (*cmd)->cmd_pointer;
+ }
+ *prefix_cmd = prev_cmd;
+ }
+ if ((*cmd)->prefixlist)
+ cur_list = *(*cmd)->prefixlist;
+ else
+ return 1;
+
+ text = p;
+ }
+}
+
+
+
+
#if 0
/* Look up the contents of *LINE as a command in the command list LIST.
LIST is a chain of struct cmd_list_element's.
CMDTYPE precedes the word "command" in the error message. */
struct cmd_list_element *
-lookup_cmd (line, list, cmdtype, allow_unknown)
- char **line;
- struct cmd_list_element *list;
- char *cmdtype;
- int allow_unknown;
+lookup_cmd (char **line, struct cmd_list_element *list, char *cmdtype,
+ int allow_unknown)
{
register char *p;
register struct cmd_list_element *c, *found;
"oobar"; if WORD is "baz/foo", return "baz/foobar". */
char **
-complete_on_cmdlist (list, text, word)
- struct cmd_list_element *list;
- char *text;
- char *word;
+complete_on_cmdlist (struct cmd_list_element *list, char *text, char *word)
{
struct cmd_list_element *ptr;
char **matchlist;
"oobar"; if WORD is "baz/foo", return "baz/foobar". */
char **
-complete_on_enum (enumlist, text, word)
- char **enumlist;
- char *text;
- char *word;
+complete_on_enum (const char *enumlist[],
+ char *text,
+ char *word)
{
char **matchlist;
int sizeof_matchlist;
int matches;
int textlen = strlen (text);
int i;
- char *name;
+ const char *name;
sizeof_matchlist = 10;
matchlist = (char **) xmalloc (sizeof_matchlist * sizeof (char *));
return matchlist;
}
+static enum cmd_auto_boolean
+parse_auto_binary_operation (const char *arg)
+{
+ if (arg != NULL && *arg != '\0')
+ {
+ int length = strlen (arg);
+ while (isspace (arg[length - 1]) && length > 0)
+ length--;
+ if (strncmp (arg, "on", length) == 0
+ || strncmp (arg, "1", length) == 0
+ || strncmp (arg, "yes", length) == 0
+ || strncmp (arg, "enable", length) == 0)
+ return CMD_AUTO_BOOLEAN_TRUE;
+ else if (strncmp (arg, "off", length) == 0
+ || strncmp (arg, "0", length) == 0
+ || strncmp (arg, "no", length) == 0
+ || strncmp (arg, "disable", length) == 0)
+ return CMD_AUTO_BOOLEAN_FALSE;
+ else if (strncmp (arg, "auto", length) == 0
+ || (strncmp (arg, "-1", length) == 0 && length > 1))
+ return CMD_AUTO_BOOLEAN_AUTO;
+ }
+ error ("\"on\", \"off\" or \"auto\" expected.");
+ return CMD_AUTO_BOOLEAN_AUTO; /* pacify GCC */
+}
+
static int
-parse_binary_operation (arg)
- char *arg;
+parse_binary_operation (char *arg)
{
int length;
while (arg[length - 1] == ' ' || arg[length - 1] == '\t')
length--;
- if (!strncmp (arg, "on", length)
- || !strncmp (arg, "1", length)
- || !strncmp (arg, "yes", length))
+ if (strncmp (arg, "on", length) == 0
+ || strncmp (arg, "1", length) == 0
+ || strncmp (arg, "yes", length) == 0
+ || strncmp (arg, "enable", length) == 0)
return 1;
- else if (!strncmp (arg, "off", length)
- || !strncmp (arg, "0", length)
- || !strncmp (arg, "no", length))
+ else if (strncmp (arg, "off", length) == 0
+ || strncmp (arg, "0", length) == 0
+ || strncmp (arg, "no", length) == 0
+ || strncmp (arg, "disable", length) == 0)
return 0;
else
{
directly by the user (i.e. these are just like any other
command). C is the command list element for the command. */
void
-do_setshow_command (arg, from_tty, c)
- char *arg;
- int from_tty;
- struct cmd_list_element *c;
+do_setshow_command (char *arg, int from_tty, struct cmd_list_element *c)
{
if (c->type == set_cmd)
{
case var_boolean:
*(int *) c->var = parse_binary_operation (arg);
break;
+ case var_auto_boolean:
+ *(enum cmd_auto_boolean *) c->var = parse_auto_binary_operation (arg);
+ break;
case var_uinteger:
if (arg == NULL)
error_no_arg ("integer to set it to.");
int i;
int len;
int nmatches;
- char *match = NULL;
+ const char *match = NULL;
char *p;
/* if no argument was supplied, print an informative error message */
for (i = 0; c->enums[i]; i++)
if (strncmp (arg, c->enums[i], len) == 0)
{
- match = c->enums[i];
- nmatches++;
+ if (c->enums[i][len] == '\0')
+ {
+ match = c->enums[i];
+ nmatches = 1;
+ break; /* exact match. */
+ }
+ else
+ {
+ match = c->enums[i];
+ nmatches++;
+ }
}
if (nmatches <= 0)
if (nmatches > 1)
error ("Ambiguous item \"%s\".", arg);
- *(char **) c->var = match;
+ *(const char **) c->var = match;
}
break;
default:
}
else if (c->type == show_cmd)
{
+#ifdef UI_OUT
+ struct cleanup *old_chain;
+ struct ui_stream *stb;
+ int quote;
+
+ stb = ui_out_stream_new (uiout);
+ old_chain = make_cleanup_ui_out_stream_delete (stb);
+#endif /* UI_OUT */
+
/* Print doc minus "show" at start. */
print_doc_line (gdb_stdout, c->doc + 5);
- fputs_filtered (" is ", gdb_stdout);
- wrap_here (" ");
+#ifdef UI_OUT
+ ui_out_text (uiout, " is ");
+ ui_out_wrap_hint (uiout, " ");
+ quote = 0;
switch (c->var_type)
{
case var_string:
{
unsigned char *p;
+ if (*(unsigned char **) c->var)
+ fputstr_filtered (*(unsigned char **) c->var, '"', stb->stream);
+ quote = 1;
+ }
+ break;
+ case var_string_noescape:
+ case var_filename:
+ case var_enum:
+ if (*(char **) c->var)
+ fputs_filtered (*(char **) c->var, stb->stream);
+ quote = 1;
+ break;
+ case var_boolean:
+ fputs_filtered (*(int *) c->var ? "on" : "off", stb->stream);
+ break;
+ case var_auto_boolean:
+ switch (*(enum cmd_auto_boolean*) c->var)
+ {
+ case CMD_AUTO_BOOLEAN_TRUE:
+ fputs_filtered ("on", stb->stream);
+ break;
+ case CMD_AUTO_BOOLEAN_FALSE:
+ fputs_filtered ("off", stb->stream);
+ break;
+ case CMD_AUTO_BOOLEAN_AUTO:
+ fputs_filtered ("auto", stb->stream);
+ break;
+ default:
+ internal_error ("do_setshow_command: invalid var_auto_boolean");
+ break;
+ }
+ break;
+ case var_uinteger:
+ if (*(unsigned int *) c->var == UINT_MAX)
+ {
+ fputs_filtered ("unlimited", stb->stream);
+ break;
+ }
+ /* else fall through */
+ case var_zinteger:
+ fprintf_filtered (stb->stream, "%u", *(unsigned int *) c->var);
+ break;
+ case var_integer:
+ if (*(int *) c->var == INT_MAX)
+ {
+ fputs_filtered ("unlimited", stb->stream);
+ }
+ else
+ fprintf_filtered (stb->stream, "%d", *(int *) c->var);
+ break;
+
+ default:
+ error ("gdb internal error: bad var_type in do_setshow_command");
+ }
+ if (quote)
+ ui_out_text (uiout, "\"");
+ ui_out_field_stream (uiout, "value", stb);
+ if (quote)
+ ui_out_text (uiout, "\"");
+ ui_out_text (uiout, ".\n");
+ do_cleanups (old_chain);
+#else
+ fputs_filtered (" is ", gdb_stdout);
+ wrap_here (" ");
+ switch (c->var_type)
+ {
+ case var_string:
+ {
fputs_filtered ("\"", gdb_stdout);
if (*(unsigned char **) c->var)
fputstr_filtered (*(unsigned char **) c->var, '"', gdb_stdout);
case var_boolean:
fputs_filtered (*(int *) c->var ? "on" : "off", gdb_stdout);
break;
+ case var_auto_boolean:
+ switch (*(enum cmd_auto_boolean*) c->var)
+ {
+ case CMD_AUTO_BOOLEAN_TRUE:
+ fputs_filtered ("on", gdb_stdout);
+ break;
+ case CMD_AUTO_BOOLEAN_FALSE:
+ fputs_filtered ("off", gdb_stdout);
+ break;
+ case CMD_AUTO_BOOLEAN_AUTO:
+ fputs_filtered ("auto", gdb_stdout);
+ break;
+ default:
+ internal_error ("do_setshow_command: invalid var_auto_boolean");
+ break;
+ }
+ break;
case var_uinteger:
if (*(unsigned int *) c->var == UINT_MAX)
{
error ("gdb internal error: bad var_type in do_setshow_command");
}
fputs_filtered (".\n", gdb_stdout);
+#endif
}
else
error ("gdb internal error: bad cmd_type in do_setshow_command");
(*c->function.sfunc) (NULL, from_tty, c);
+ if (c->type == set_cmd && set_hook)
+ set_hook (c);
}
/* Show all the settings in a list of show commands. */
void
-cmd_show_list (list, from_tty, prefix)
- struct cmd_list_element *list;
- int from_tty;
- char *prefix;
+cmd_show_list (struct cmd_list_element *list, int from_tty, char *prefix)
{
+#ifdef UI_OUT
+ ui_out_list_begin (uiout, "showlist");
+#endif
for (; list != NULL; list = list->next)
{
/* If we find a prefix, run its list, prefixing our output by its
prefix (with "show " skipped). */
+#ifdef UI_OUT
+ if (list->prefixlist && !list->abbrev_flag)
+ {
+ ui_out_list_begin (uiout, "optionlist");
+ ui_out_field_string (uiout, "prefix", list->prefixname + 5);
+ cmd_show_list (*list->prefixlist, from_tty, list->prefixname + 5);
+ ui_out_list_end (uiout);
+ }
+ if (list->type == show_cmd)
+ {
+ ui_out_list_begin (uiout, "option");
+ ui_out_text (uiout, prefix);
+ ui_out_field_string (uiout, "name", list->name);
+ ui_out_text (uiout, ": ");
+ do_setshow_command ((char *) NULL, from_tty, list);
+ ui_out_list_end (uiout);
+ }
+#else
if (list->prefixlist && !list->abbrev_flag)
cmd_show_list (*list->prefixlist, from_tty, list->prefixname + 5);
if (list->type == show_cmd)
fputs_filtered (": ", gdb_stdout);
do_setshow_command ((char *) NULL, from_tty, list);
}
+#endif
}
+#ifdef UI_OUT
+ ui_out_list_end (uiout);
+#endif
}
/* ARGSUSED */
static void
-shell_escape (arg, from_tty)
- char *arg;
- int from_tty;
+shell_escape (char *arg, int from_tty)
{
#ifdef CANT_FORK
- /* FIXME: what about errors (I don't know how GO32 system() handles
- them)? */
- system (arg);
+ /* If ARG is NULL, they want an inferior shell, but `system' just
+ reports if the shell is available when passed a NULL arg. */
+ int rc = system (arg ? arg : "");
+
+ if (!arg)
+ arg = "inferior shell";
+
+ if (rc == -1)
+ {
+ fprintf_unfiltered (gdb_stderr, "Cannot execute %s: %s\n", arg,
+ safe_strerror (errno));
+ gdb_flush (gdb_stderr);
+ }
+ else if (rc)
+ {
+ fprintf_unfiltered (gdb_stderr, "%s exited with status %d\n", arg, rc);
+ gdb_flush (gdb_stderr);
+ }
+#ifdef __DJGPP__
+ /* Make sure to return to the directory GDB thinks it is, in case the
+ shell command we just ran changed it. */
+ chdir (current_directory);
+#endif
#else /* Can fork. */
int rc, status, pid;
char *p, *user_shell;
}
static void
-make_command (arg, from_tty)
- char *arg;
- int from_tty;
+make_command (char *arg, int from_tty)
{
char *p;
}
static void
-show_user_1 (c, stream)
- struct cmd_list_element *c;
- GDB_FILE *stream;
+show_user_1 (struct cmd_list_element *c, struct ui_file *stream)
{
register struct command_line *cmdlines;
fputs_filtered (c->name, stream);
fputs_filtered (":\n", stream);
+#ifdef UI_OUT
+ print_command_lines (uiout, cmdlines, 1);
+ fputs_filtered ("\n", stream);
+#else
while (cmdlines)
{
print_command_line (cmdlines, 4, stream);
cmdlines = cmdlines->next;
}
fputs_filtered ("\n", stream);
+#endif
}
/* ARGSUSED */
static void
-show_user (args, from_tty)
- char *args;
- int from_tty;
+show_user (char *args, int from_tty)
{
struct cmd_list_element *c;
extern struct cmd_list_element *cmdlist;
}
void
-_initialize_command ()
+_initialize_command (void)
{
add_com ("shell", class_support, shell_escape,
"Execute the rest of the line as a shell command. \n\
With no arguments, run an inferior shell.");
+ /* NOTE: cagney/2000-03-20: Being able to enter ``(gdb) !ls'' would
+ be a really useful feature. Unfortunatly, the below wont do
+ this. Instead it adds support for the form ``(gdb) ! ls''
+ (i.e. the space is required). If the ``!'' command below is
+ added the complains about no ``!'' command would be replaced by
+ complains about how the ``!'' command is broken :-) */
if (xdb_commands)
add_com_alias ("!", "shell", class_support, 0);
"Show definitions of user defined commands.\n\
Argument is the name of the user defined command.\n\
With no argument, show definitions of all user defined commands.", &showlist);
+ add_com ("apropos", class_support, apropos_command, "Search for commands matching a REGEXP");
}