aboutsummaryrefslogtreecommitdiff
path: root/gdb/command.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/command.c')
-rw-r--r--gdb/command.c352
1 files changed, 255 insertions, 97 deletions
diff --git a/gdb/command.c b/gdb/command.c
index acde0e3..000b273 100644
--- a/gdb/command.c
+++ b/gdb/command.c
@@ -104,6 +104,7 @@ what you give them. Help stamp out software-hoarding! */
#include "command.h"
+#include "defs.h"
#include <stdio.h>
#ifdef sparc
@@ -112,8 +113,6 @@ what you give them. Help stamp out software-hoarding! */
extern char *xmalloc ();
-static char *savestring ();
-
/* Add element named NAME to command list *LIST.
FUN should be the function to execute the command;
it will get a character string as argument, with leading
@@ -149,6 +148,33 @@ add_cmd (name, class, fun, doc, list)
return c;
}
+/* Same as above, except that the abbrev_flag is set. */
+
+struct cmd_list_element *
+add_abbrev_cmd (name, class, fun, doc, list)
+ char *name;
+ int class;
+ void (*fun) ();
+ char *doc;
+ struct cmd_list_element **list;
+{
+ register struct cmd_list_element *c
+ = (struct cmd_list_element *) xmalloc (sizeof (struct cmd_list_element));
+
+ delete_cmd (name, list);
+ c->next = *list;
+ c->name = savestring (name, strlen (name));
+ c->class = class;
+ c->function = fun;
+ c->doc = doc;
+ c->prefixlist = 0;
+ c->allow_unknown = 0;
+ c->abbrev_flag = 1;
+ c->aux = 0;
+ *list = c;
+ return c;
+}
+
struct cmd_list_element *
add_alias_cmd (name, oldname, class, abbrev_flag, list)
char *name;
@@ -180,7 +206,7 @@ add_alias_cmd (name, oldname, class, abbrev_flag, list)
return c;
}
-/* Like add_prefix_cmd but adds an element for a command prefix:
+/* Like add_cmd but adds an element for a command prefix:
a name that should be followed by a subcommand to be looked up
in another command list. PREFIXLIST should be the address
of the variable containing that list. */
@@ -204,6 +230,28 @@ add_prefix_cmd (name, class, fun, doc, prefixlist, prefixname,
return c;
}
+/* Like add_prefix_cmd butsets 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;
+ int class;
+ void (*fun) ();
+ 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;
+ c->prefixname = prefixname;
+ c->allow_unknown = allow_unknown;
+ c->abbrev_flag = 1;
+ return c;
+}
+
/* Remove the command named NAME from the command list. */
void
@@ -228,65 +276,86 @@ delete_cmd (name, list)
}
}
-/* Implement a help command on command list LIST.
- COMMAND is the argument given (a command from the list to document)
- or zero for no arg (describe briefly all the commands in the list).
- CMDTYPE is a string to use in the error message if command COMMAND
- is not found in the list. */
+void help_cmd (), help_list (), help_cmd_list ();
-/* CLASS should be -1 to list all commands in LIST,
- or a nonnegative class number value to list just commands in that class,
- or -2 to list the classes themselves. */
+/* This command really has to deal with two things:
+ * 1) I want documentation on *this string* (usually called by
+ * "help commandname").
+ * 2) I want documentation on *this list* (usually called by
+ * giving a command that requires subcommands. Also called by saying
+ * just "help".)
+ *
+ * I am going to split this into two seperate comamnds, help_cmd and
+ * help_list.
+ */
void
-help_cmd (command, list, cmdtype, class, stream)
+help_cmd (command, stream)
char *command;
- struct cmd_list_element *list;
- char *cmdtype;
- int class;
FILE *stream;
{
- register struct cmd_list_element *c;
- register char *p;
- register int ncmds;
- struct cmdvec { struct cmd_list_element *cmd; int class; };
- register struct cmdvec *cmdvec;
- char *cmdtype1, *cmdtype2;
- int len;
+ struct cmd_list_element *c;
+ extern struct cmd_list_element *cmdlist;
- if (command)
+ if (!command)
{
- c = lookup_cmd (&command, list, cmdtype, 0);
- if (c == 0)
- return;
-
- /* There are three cases here.
- If c->prefixlist is nonzer, 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->function is zero, we have a class name.
- Print its documentation (as if it were a command)
- and then set class to he number of this class
- so that the commands in the class will be listed. */
-
- p = c->doc;
- fprintf (stream, "%s\n", p);
- if (c->function != 0 && c->prefixlist == 0)
- return;
- fputc ('\n', stream);
- if (c->prefixlist)
- {
- list = *c->prefixlist;
- class = 0;
- cmdtype = c->prefixname;
- }
- else
- class = c->class;
+ help_list (cmdlist, "", -2, stream);
+ return;
}
+ c = lookup_cmd (&command, cmdlist, "", 0);
+
+ if (c == 0)
+ return;
+
+ /* There are three cases here.
+ If c->prefixlist is nonzer, 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->function is zero, we have a class name.
+ Print its documentation (as if it were a command)
+ and then set class to he number of this class
+ so that the commands in the class will be listed. */
+
+ fprintf (stream, "%s\n", c->doc);
+ if (c->prefixlist == 0 && c->function != 0)
+ return;
+ fputc ('\n', stream);
+
+ /* If this is a prefix command, print it's subcommands */
+ if (c->prefixlist)
+ help_list (*c->prefixlist, c->prefixname, -1, stream);
+
+ /* If this is a class name, print all of the commands in the class */
+ if (c->function == 0)
+ help_list (cmdlist, "", c->class, stream);
+}
+
+/*
+ * Get a specific kind of help on a command list.
+ *
+ * LIST is the list.
+ * CMDTYPE is the prefix to use in the title string.
+ * CLASS is the class with which to list the nodes of this list (see
+ * documentation for help_cmd_list below), As usual, -1 for
+ * everything, -2 for just classes, and non-negative for only things
+ * in a specific class.
+ * and STREAM is the output stream on which to print things.
+ * 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;
+ int class;
+ FILE *stream;
+{
+ int len;
+ char *cmdtype1, *cmdtype2;
+
/* If CMDTYPE is "foo ", CMDTYPE1 gets " foo" and CMDTYPE2 gets "foo sub" */
len = strlen (cmdtype);
cmdtype1 = (char *) alloca (len + 1);
@@ -307,21 +376,7 @@ help_cmd (command, list, cmdtype, class, stream)
else
fprintf (stream, "List of %scommands:\n\n", cmdtype2);
- for (c = list; c; c = c->next)
- {
- if (c->abbrev_flag == 0
- && (class == -1 /* Listing all */
- || (c->class == class && c->function != 0) /* Listing one class */
- || (class == -2 && c->function == 0))) /* Listing the classes */
- {
- fprintf (stream, "%s -- ", c->name);
- /* Print just first line of documentation. */
- p = c->doc;
- while (*p && *p != '\n') p++;
- fwrite (c->doc, 1, p - c->doc, stream);
- fputc ('\n', stream);
- }
- }
+ help_cmd_list (list, class, cmdtype, (class >= 0), stream);
if (class == -2)
fprintf (stream, "\n\
@@ -333,6 +388,55 @@ Type \"help%s\" followed by %scommand name for full documentation.\n\
Command name abbreviations are allowed if unambiguous.\n",
cmdtype1, cmdtype2);
}
+
+
+/*
+ * Implement a help command on command list LIST.
+ * RECURSE should be non-zero if this should be done recursively on
+ * all sublists of LIST.
+ * PREFIX is the prefix to print before each command name.
+ * STREAM is the stream upon which the output should be written.
+ * CLASS should be:
+ * A non-negative class number to list only commands in that
+ * class.
+ * -1 to list all commands in list.
+ * -2 to list all classes in list.
+ *
+ * Note that RECURSE will be active on *all* sublists, not just the
+ * ones seclected by the criteria above (ie. the selection mechanism
+ * is at the low level, not the high-level).
+ */
+void
+help_cmd_list (list, class, prefix, recurse, stream)
+ struct cmd_list_element *list;
+ int class;
+ char *prefix;
+ int recurse;
+ FILE *stream;
+{
+ register struct cmd_list_element *c;
+ register char *p;
+
+ for (c = list; c; c = c->next)
+ {
+ if (c->abbrev_flag == 0 &&
+ (class == -1
+ || (class == -2 && c->function == 0)
+ || (class == c->class && c->function != 0)))
+ {
+ fprintf (stream, "%s%s -- ", prefix, c->name);
+ /* Print just the first line */
+ p = c->doc;
+ while (*p && *p != '\n') p++;
+ fwrite (c->doc, 1, p - c->doc, stream);
+ fputc('\n', stream);
+ }
+ if (recurse
+ && c->prefixlist != 0
+ && c->abbrev_flag == 0)
+ help_cmd_list (*c->prefixlist, class, c->prefixname, 1, stream);
+ }
+}
/* Look up the contents of *LINE as a command in the command list LIST.
LIST is a chain of struct cmd_list_element's.
@@ -355,6 +459,8 @@ lookup_cmd (line, list, cmdtype, allow_unknown)
register struct cmd_list_element *c, *found;
int nfound;
char ambbuf[100];
+ char *processed_cmd;
+ int i, cmd_len;
/* Skip leading whitespace. */
@@ -371,29 +477,53 @@ lookup_cmd (line, list, cmdtype, allow_unknown)
/* Find end of command name. */
p = *line;
- while (*p == '-'
- || (*p >= 'a' && *p <= 'z')
- || (*p >= 'A' && *p <= 'Z')
- || (*p >= '0' && *p <= '9'))
- {
- if (*p >= 'A' && *p <= 'Z')
- *p += 'a' - 'A';
- p++;
- }
+ if (*p == '!')
+ p++;
+ else while (*p == '-'
+ || (*p >= 'a' && *p <= 'z')
+ || (*p >= 'A' && *p <= 'Z')
+ || (*p >= '0' && *p <= '9'))
+ p++;
/* Look up the command name.
If exact match, keep that.
- Otherwise, take command abbreviated, if unique. */
+ Otherwise, take command abbreviated, if unique. Note that (in my
+ opinion) a null string does *not* indicate ambiguity; simply the
+ end of the argument. */
+
+ if (p == *line)
+ {
+ if (!allow_unknown)
+ error ("Lack of needed %scommand", cmdtype);
+ return 0;
+ }
+
+ /* Copy over to a local buffer, converting to lowercase on the way.
+ This is in case the command being parsed is a subcommand which
+ doesn't match anything, and that's ok. We want the original
+ untouched for the routine of the original command. */
+
+ processed_cmd = (char *) alloca (p - *line + 1);
+ for (cmd_len = 0; cmd_len < p - *line; cmd_len++)
+ {
+ char x = (*line)[cmd_len];
+ if (x >= 'A' && x <= 'Z')
+ processed_cmd[cmd_len] = x - 'A' + 'a';
+ else
+ processed_cmd[cmd_len] = x;
+ }
+ processed_cmd[cmd_len] = '\0';
+ /* Check all possibilities in the current command list. */
found = 0;
nfound = 0;
for (c = list; c; c = c->next)
{
- if (!strncmp (*line, c->name, p - *line))
+ if (!strncmp (processed_cmd, c->name, cmd_len))
{
found = c;
nfound++;
- if (c->name[p - *line] == 0)
+ if (c->name[cmd_len] == 0)
{
nfound = 1;
break;
@@ -407,10 +537,9 @@ lookup_cmd (line, list, cmdtype, allow_unknown)
{
if (nfound > 1 && allow_unknown >= 0)
{
- *p = 0;
ambbuf[0] = 0;
for (c = list; c; c = c->next)
- if (!strncmp (*line, c->name, p - *line))
+ if (!strncmp (processed_cmd, c->name, cmd_len))
{
if (strlen (ambbuf) + strlen (c->name) + 6 < sizeof ambbuf)
{
@@ -424,13 +553,11 @@ lookup_cmd (line, list, cmdtype, allow_unknown)
break;
}
}
- error ("Ambiguous %scommand \"%s\": %s.", cmdtype, *line, ambbuf);
+ error ("Ambiguous %scommand \"%s\": %s.", cmdtype,
+ processed_cmd, ambbuf);
}
else if (!allow_unknown)
- {
- *p = 0;
- error ("Undefined %scommand: \"%s\".", cmdtype, *line);
- }
+ error ("Undefined %scommand: \"%s\".", cmdtype, processed_cmd);
return 0;
}
@@ -450,17 +577,48 @@ lookup_cmd (line, list, cmdtype, allow_unknown)
return found;
}
-/* Make a copy of the string at PTR with SIZE characters
- (and add a null character at the end in the copy).
- Uses malloc to get the space. Returns the address of the copy. */
+static void
+shell_escape (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ int rc, status, pid;
+ char *p, *user_shell;
+ extern char *rindex ();
+
+ if ((user_shell = (char *) getenv ("SHELL")) == NULL)
+ user_shell = "/bin/sh";
+
+ /* Get the name of the shell for arg0 */
+ if ((p = rindex (user_shell, '/')) == NULL)
+ p = user_shell;
+ else
+ p++; /* Get past '/' */
+
+ if ((pid = fork()) == 0)
+ {
+ if (!arg)
+ execl (user_shell, p, 0);
+ else
+ execl (user_shell, p, "-c", arg, 0);
-static char *
-savestring (ptr, size)
- char *ptr;
- int size;
+ fprintf (stderr, "Exec of shell failed\n");
+ exit (0);
+ }
+
+ if (pid != -1)
+ while ((rc = wait (&status)) != pid && rc != -1)
+ ;
+ else
+ error ("Fork failed");
+}
+
+void
+_initialize_command ()
{
- register char *p = (char *) xmalloc (size + 1);
- bcopy (ptr, p, size);
- p[size] = 0;
- return p;
+ 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.");
+
+ add_com_alias ("!", "shell", class_support, 1);
}