This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
small enhancements to gdb here..
- To: gdb-patches at sourceware dot cygnus dot com
- Subject: small enhancements to gdb here..
- From: "Don Beusee" <Don dot Beusee at oracle dot com>
- Date: Mon, 20 Nov 2000 23:57:19 -0800 (PST)
Hi,
I originally sent this email to gnu-gdb@gnu.org before I saw the CONTRIBUTE file. I reformatted the diff output to your specifications. The diff's are based on 5.0 distribution at GNU's ftp site.
I have patches for 3 small enhancements to improve convenience:
- allow O/S commands directly from gdb when no match for internal command.
- additional arg syntax in user-defined commands:
$# number of args
$* all args
$N specific arg (where N is a number from 1 to 9). $1 is the first
arg (same as $arg0).
${NN} NN can be any number between 1 and MAXUSERARGS (10 currently).
${ENV} environment variable
- a user command referencing an argument not provided on the command returns
an empty string, not an error.
Example .gdbinit:
define sh
shell $*
end
define host
shell $*
end
define pa
echo args = $*, count = $#\n
echo arg1 = $1\n
echo arg2 = $2\n
echo arg10 = ${10}\n
echo arg0=$arg0\n
echo arg1=$arg1\n
end
define c
if strcmp("$1", "at") == 0
printf "continuing at %d\n", $2
jump $2
else
continue $*
end
end
ChangeLog entry:
2000-11-20 Don Beusee <Don.Beusee@oracle.com>
* gdb/command.c, gdb/top.c: If a command entered in gdb is not
internal, execute as a shell command.
* gdb/top.c: Enhance user-defined command argument parsing to accept
$# (number of args), $* (all args), $N (where N is a number from 1 to
9), ${NN} where NN is any number from 1 to MAXUSERARGS (10 currently),
and ${ENV} where ENV is an environment variable.
* gdb/doc/gdb.info-9: document above arg parsing in user-defined
commands.
Here are the patches in rcsdiff -up format:
$ rcsdiff -up gdb/command.c
--- 1.1 2000/11/20 11:49:09
+++ gdb/command.c 2000/11/20 11:53:35
@@ -43,7 +43,7 @@ static void show_user_1 (struct cmd_list
static void make_command PARAMS ((char *, int));
-static void shell_escape PARAMS ((char *, int));
+void shell_escape PARAMS ((char *, int));
static int parse_binary_operation PARAMS ((char *));
@@ -512,7 +512,7 @@ help_cmd (command, stream)
c = lookup_cmd (&command, cmdlist, "", 0, 0);
- if (c == 0)
+ if (c == 0 || c == -1 || c == -2)
return;
/* There are three cases here.
@@ -901,8 +901,8 @@ undef_cmd_error (cmdtype, q)
LIST is a chain of struct cmd_list_element's.
If it is found, return the struct cmd_list_element for that command
and update *LINE to point after the command name, at the first argument.
- If not found, call error if ALLOW_UNKNOWN is zero
- otherwise (or if error returns) return zero.
+ If not found, return -2 to signal caller to run shell if ALLOW_UNKNOWN is
+ zero otherwise (or if error returns) return zero.
Call error if specified command is ambiguous,
unless ALLOW_UNKNOWN is negative.
CMDTYPE precedes the word "command" in the error message.
@@ -948,7 +948,10 @@ lookup_cmd (line, list, cmdtype, allow_u
q = (char *) alloca (p - *line + 1);
strncpy (q, *line, p - *line);
q[p - *line] = '\0';
- undef_cmd_error (cmdtype, q);
+ if (!*cmdtype)
+ return (struct cmd_list_element *) -2; /* invoke shell */
+ else
+ undef_cmd_error (cmdtype, q);
}
}
else
@@ -1861,7 +1864,7 @@ cmd_show_list (list, from_tty, prefix)
}
/* ARGSUSED */
-static void
+void
shell_escape (arg, from_tty)
char *arg;
int from_tty;
$ rcsdiff -up gdb/top.c
--- 1.1 2000/11/20 11:49:13
+++ gdb/top.c 2000/11/20 12:02:39
@@ -97,7 +97,9 @@ recurse_read_control_structure PARAMS ((
static struct cleanup *setup_user_args PARAMS ((char *));
-static char *locate_arg PARAMS ((char *));
+static char *locate_arg PARAMS ((char *, int *, char **, char **, char *));
+
+static char *itoa PARAMS ((int));
static char *insert_args PARAMS ((char *));
@@ -144,6 +146,8 @@ static void complete_command PARAMS ((ch
static void do_nothing PARAMS ((int));
+extern void shell_escape PARAMS ((char *, int));
+
static void show_debug PARAMS ((char *, int));
static void set_debug PARAMS ((char *, int));
@@ -360,6 +364,7 @@ struct user_args
int len;
}
a[MAXUSERARGS];
+ char args[256];
int count;
}
*user_args;
@@ -1296,6 +1301,8 @@ setup_user_args (p)
if (p == NULL)
return old_chain;
+ strcpy(args->args, p);
+
while (*p)
{
char *start_arg;
@@ -1357,20 +1364,87 @@ setup_user_args (p)
return old_chain;
}
-/* Given character string P, return a point to the first argument ($arg),
- or NULL if P contains no arguments. */
+/*
+ * Given character string P, return a point to the substitution argument
+ * or variable; or NULL if P contains no arguments or variable tokens.
+ * num will contain one of the following values:
+ * -1 (all arguments should replace this token)
+ * -2 (argument count should replace this token)
+ * -3 (string stored in newstr should replace this token)
+ * the argument number,
+ */
static char *
-locate_arg (p)
- char *p;
+locate_arg (p, num, start, after, newstr)
+ char *p, **start, **after, *newstr;
+ int *num;
{
+ *start = NULL;
+ *newstr = '\0';
while ((p = strchr (p, '$')))
{
if (strncmp (p, "$arg", 4) == 0 && isdigit (p[4]))
- return p;
+ {
+ *num = p[4]-'0';
+ *start = p;
+ *after = p+5;
+ return *start;
+ }
+ if (p[0] == '$' && isdigit (p[1]))
+ {
+ *num = p[1] - '0' - 1;
+ *start = p;
+ *after = p+2;
+ return *start;
+ }
+ if (p[0] == '$' && p[1] == '#')
+ {
+ *num = -2; /* indicates to replace with count */
+ *start = p;
+ *after = p+2;
+ return *start;
+ }
+ if (p[0] == '$' && p[1] == '*')
+ {
+ *num = -1; /* indicates to use all args */
+ *start = p;
+ *after = p+2;
+ return *start;
+ }
+ if (p[0] == '$' && p[1] == '{' && isdigit(p[2]))
+ {
+ *num = atoi(p+2) - 1;
+ *start = p;
+ *after = strchr(p, '}')+1;
+ return *start;
+ }
+ if (p[0] == '$' && p[1] == '{')
+ {
+ char env[256], *e;
+ memset(env, '\0', sizeof(env));
+ *num = -3; /* environment variable */
+ *start = p;
+ *after = strchr(p, '}')+1;
+ memcpy(env, p+2, (*after) - p - 3);
+ if (e = getenv(env))
+ {
+ strcpy(newstr, e);
+ }
+ return *start;
+ }
p++;
}
- return NULL;
+ return *start;
+}
+
+static char *
+itoa(i)
+ int i;
+{
+ static char a[12];
+ *a = '\0';
+ sprintf(a, "%0d", i);
+ return(a);
}
/* Insert the user defined arguments stored in user_arg into the $arg
@@ -1380,24 +1454,33 @@ static char *
insert_args (line)
char *line;
{
- char *p, *save_line, *new_line;
- unsigned len, i;
+ char *p, *save_line, *new_line, *afterarg;
+ char envstr[256];
+ unsigned len;
+ int i;
/* First we need to know how much memory to allocate for the new line. */
save_line = line;
len = 0;
- while ((p = locate_arg (line)))
+ while (locate_arg (line, &i/*argnum*/, &p/*startarg*/, &afterarg, envstr))
{
- len += p - line;
- i = p[4] - '0';
-
- if (i >= user_args->count)
- {
- error ("Missing argument %d in user function.\n", i);
- return NULL;
+ len += p - line; /* add portion before arg token */
+ if (i == -1 && user_args)
+ len += strlen(user_args->args);
+ else if (i == -2 && user_args)
+ len += strlen(itoa(user_args->count));
+ else if (i == -3)
+ len += strlen(envstr);
+ else if (user_args && i < user_args->count)
+ len += user_args->a[i].len;
+/*
+ else
+ {
+ error ("Missing argument %d in user function.\n", i);
+ return NULL;
}
- len += user_args->a[i].len;
- line = p + 5;
+*/
+ line = afterarg;
}
/* Don't forget the tail. */
@@ -1406,7 +1489,10 @@ insert_args (line)
/* Allocate space for the new line and fill it in. */
new_line = (char *) xmalloc (len + 1);
if (new_line == NULL)
- return NULL;
+ {
+ error ("could not allocate memory for argument substitution.\n");
+ return NULL;
+ }
/* Restore pointer to beginning of old line. */
line = save_line;
@@ -1414,21 +1500,36 @@ insert_args (line)
/* Save pointer to beginning of new line. */
save_line = new_line;
- while ((p = locate_arg (line)))
+ while (locate_arg (line, &i/*argnum*/, &p/*startarg*/, &afterarg, envstr))
{
- int i, len;
-
- memcpy (new_line, line, p - line);
- new_line += p - line;
- i = p[4] - '0';
-
- len = user_args->a[i].len;
- if (len)
- {
+ memcpy (new_line, line, p - line); /* copy line before arg token */
+ new_line += p - line; /* point new_line at end */
+ if (i == -1 && user_args)
+ {
+ len = strlen(user_args->args);
+ memcpy (new_line, user_args->args, len);
+ }
+ else if (i == -2 && user_args)
+ {
+ len = strlen(itoa(user_args->count));
+ memcpy (new_line, itoa(user_args->count), len);
+ }
+ else if (i == -3)
+ {
+ len = strlen(envstr);
+ memcpy (new_line, envstr, len);
+ }
+ else if (user_args && i < user_args->count)
+ {
+ len = user_args->a[i].len;
memcpy (new_line, user_args->a[i].arg, len);
- new_line += len;
- }
- line = p + 5;
+ }
+ else
+ {
+ len = 0; /* arg not present - add nothing */
+ }
+ new_line += len;
+ line = afterarg;
}
/* Don't forget the tail. */
strcpy (new_line, line);
@@ -1505,6 +1606,14 @@ execute_command (p, from_tty)
line = p;
c = lookup_cmd (&p, cmdlist, "", 0, 1);
+ if (c == (struct cmd_list_element *)-2) /* invoke shell? */
+ {
+ char *shellcmd;
+ shellcmd = malloc(strlen(p)+7);
+ sprintf(shellcmd, "shell %s", p);
+ execute_command(shellcmd, from_tty);
+ return;
+ }
/* If the target is running, we allow only a limited set of
commands. */
@@ -1517,6 +1626,10 @@ execute_command (p, from_tty)
/* Pass null arg rather than an empty one. */
arg = *p ? p : 0;
+ if (arg && c->function.cfunc != define_command
+ && c->function.cfunc != shell_escape )
+ arg=insert_args(arg); /* replace environment variables in command with
+ their values */
/* Clear off trailing whitespace, except for set and complete command. */
if (arg && c->type != set_cmd && c->function.cfunc != complete_command)
$ rcsdiff -up gdb/doc/gdb.info-9
--- 1.1 2000/11/21 07:35:46
+++ gdb/doc/gdb.info-9 2000/11/21 07:41:39
@@ -250,12 +250,22 @@ User-defined commands
A "user-defined command" is a sequence of GDB commands to which you
assign a new name as a command. This is done with the `define'
-command. User commands may accept up to 10 arguments separated by
+command.
+
+User commands may accept up to 10 arguments separated by
whitespace. Arguments are accessed within the user command via
-$ARG0...$ARG9. A trivial example:
+$ARG0...$ARG9 or $1...$9 and the 10th as ${10} or (${1}..${10}).
+$# is the number of arguments given to the user-defined command.
+A reference to an argument that is not given will be returned as an
+empty string.
+
+You may also reference environment variables with ${ENV}, where ENV
+is the name of the environment variable.
+
+A trivial example:
define adder
- print $arg0 + $arg1 + $arg2
+ print $1 + $2 + $3
To execute the command use:
-Don