This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
Patch to command hook (3rd time lucky) [Now under 79 wide].
- To: gdb-patches at sourceware dot cygnus dot com
- Subject: Patch to command hook (3rd time lucky) [Now under 79 wide].
- From: Steven Johnson <sbjohnson at ozemail dot com dot au>
- Date: Thu, 17 Aug 2000 12:04:27 +1000
Attached is a patch that achieves the following (now in under 79 columns):
1. Removes a potential problem with hooks where a hook calling
it's hooked command will end up in recursion until GDB Segfaults.
2. Adds the "hookpost-" hook. This is similar to "hook-" except
the hook is run after the command and not before. "hookpost-"
and "hook-" are not mutually exclusive, they can both exist
simultaneously on the same command.
3. Adds a "hookpre-" this is the same as "hook-" but I added it
for clarity when using the post hook. There is code present,
such that if you use "hook-" on a command then "hookpre-" no
longer is valid and vice versa.
4. Updated gdb.texinfo section on hooks to document "hookpost-"
and "hookpre-".
By way of example, the following is now possible:
define hook-echo
echo We are in hook-echo\n
end
define hookpost-echo
echo We are in hookpost-echo\n
end
then when:
gdb> echo hello\n
is executed, the output is:
We are in hook-echo
hello
We are in hookpost-echo
Prior to this patch, hook-echo above would have caused GDB to crash with a
segfault.
Changelog for gdb:
2000-08-17 Steven Johnson <sbjohnson@ozemail.com.au>
* Added "hookpost-" and "hookpre-" as an expansion on the original
hooking of commands to GDB. A Hook may now be run "AFTER" execution
of command as well as before.
* command.h - Changed cmd_list_element elements hook and hookee to
hook_pre and hookee_pre respectively. Added hook_post and
hookee_post to cmd_list_element for the post hook command
operation. Added hook_in to command so that an executing hook can
be flagged to prevent recursion.
* command.c - Changed initilisation of cmd_list_element of hook and
hookee to hook_pre and hookee_pre respectively. Added hook_post and
hookee_post to be initialised as hook_pre and hokee_pre. Added
ability to remove hook_post, where hooks where originally being
handled. Changed any reference to hook/hookee to hook_pre/hookee_pre
respectively. Initialise hook_in to state of hook not running.
* infrun.c - Carried through structure changes of cmd_list_element of
hook/hookee to hook_pre/hookee_pre respectively.
* top.c - Carried through structure changes of cmd_list_element of
hook/hookee to hook_pre/hookee_pre respectively. Added ability to
call post hook after command executes. Added ability for define
command to detect and properly set up post hook declerations and
prevent clashes in pre hook declerations between hook- and hookpre-.
Checks hook_in and only runs a hook when not set. Appropriately sets
and clears hook_in when hooks execute.
Changelog for gdb/doc
2000-08-17 Steven Johnson <sbjohnson@ozemail.com.au>
* gdb.texinfo - Documented new post hook ability of GDB.
<<<----- PATCH STARTS HERE ----->>>
diff -C2 -r -b ../insight-5.0/gdb/command.c src/gdb/command.c
*** ../insight-5.0/gdb/command.c Fri Mar 24 09:43:19 2000
--- src/gdb/command.c Thu Aug 17 11:15:00 2000
***************
*** 115,119 ****
c->flags = 0;
c->replacement = NULL;
! c->hook = NULL;
c->prefixlist = NULL;
c->prefixname = NULL;
--- 115,121 ----
c->flags = 0;
c->replacement = NULL;
! c->hook_pre = NULL;
! c->hook_post = NULL;
! c->hook_in = 0;
c->prefixlist = NULL;
c->prefixname = NULL;
***************
*** 126,130 ****
c->enums = NULL;
c->user_commands = NULL;
! c->hookee = NULL;
c->cmd_pointer = NULL;
--- 128,133 ----
c->enums = NULL;
c->user_commands = NULL;
! c->hookee_pre = NULL;
! c->hookee_post = NULL;
c->cmd_pointer = NULL;
***************
*** 382,387 ****
while (*list && STREQ ((*list)->name, name))
{
! if ((*list)->hookee)
! (*list)->hookee->hook = 0; /* Hook slips out of its mouth */
p = (*list)->next;
free ((PTR) * list);
--- 385,392 ----
while (*list && STREQ ((*list)->name, name))
{
! if ((*list)->hookee_pre)
! (*list)->hookee_pre->hook_pre = 0; /* Hook slips out of its mouth */
! if ((*list)->hookee_post)
! (*list)->hookee_post->hook_post = 0; /* Hook slips out of its butt */
p = (*list)->next;
free ((PTR) * list);
***************
*** 394,399 ****
if (STREQ (c->next->name, name))
{
! if (c->next->hookee)
! c->next->hookee->hook = 0; /* hooked cmd gets away. */
p = c->next->next;
free ((PTR) c->next);
--- 399,407 ----
if (STREQ (c->next->name, name))
{
! if (c->next->hookee_pre)
! c->next->hookee_pre->hook_pre = 0; /* hooked cmd gets away. */
! if (c->next->hookee_post)
! c->next->hookee_post->hook_post = 0; /* remove post hook */
! /* (sorry, no fishing metaphore) */
p = c->next->next;
free ((PTR) c->next);
***************
*** 543,549 ****
help_list (cmdlist, "", c->class, stream);
! if (c->hook)
! fprintf_filtered (stream, "\nThis command has a hook defined: %s\n",
! c->hook->name);
}
--- 551,562 ----
help_list (cmdlist, "", c->class, stream);
! if (c->hook_pre)
! fprintf_filtered (stream,
! "\nThis command is run after : %s (pre hook)\n",
! c->hook_pre->name);
! if (c->hook_post)
! fprintf_filtered (stream,
! "\nThis command is run before : %s (post hook)\n",
! c->hook_post->name);
}
diff -C2 -r -b ../insight-5.0/gdb/command.h src/gdb/command.h
*** ../insight-5.0/gdb/command.h Wed Apr 12 04:28:57 2000
--- src/gdb/command.h Tue Aug 15 13:17:49 2000
***************
*** 151,155 ****
/* Hook for another command to be executed before this command. */
! struct cmd_list_element *hook;
/* Nonzero identifies a prefix command. For them, the address
--- 151,162 ----
/* Hook for another command to be executed before this command. */
! struct cmd_list_element *hook_pre;
!
! /* Hook for another command to be executed after this command. */
! struct cmd_list_element *hook_post;
!
! /* Flag that specifies if this command is already running it's hook. */
! /* Prevents the possibility of hook recursion. */
! int hook_in;
/* Nonzero identifies a prefix command. For them, the address
***************
*** 206,212 ****
struct command_line *user_commands;
! /* Pointer to command that is hooked by this one,
so the hook can be removed when this one is deleted. */
! struct cmd_list_element *hookee;
/* Pointer to command that is aliased by this one, so the
--- 213,223 ----
struct command_line *user_commands;
! /* Pointer to command that is hooked by this one, (by hook_pre)
! so the hook can be removed when this one is deleted. */
! struct cmd_list_element *hookee_pre;
!
! /* Pointer to command that is hooked by this one, (by hook_post)
so the hook can be removed when this one is deleted. */
! struct cmd_list_element *hookee_post;
/* Pointer to command that is aliased by this one, so the
diff -C2 -r -b ../insight-5.0/gdb/doc/gdb.texinfo src/gdb/doc/gdb.texinfo
*** ../insight-5.0/gdb/doc/gdb.texinfo Fri May 12 20:30:39 2000
--- src/gdb/doc/gdb.texinfo Tue Aug 15 11:59:01 2000
***************
*** 11867,11870 ****
--- 11867,11881 ----
before that command.
+ A @emph{hook} may also be defined which is run after the command you
+ executed. Whenever you run the command @samp{foo}, if the user-defined
+ command @samp{hookpost-foo} exists, it is executed (with no arguments)
+ after that command. Post execution hooks may exist simultaneously with
+ Pre execution hooks, on the same command. To aid in script readability,
+ @samp{hookpre-foo} is also valid and performs the same operation as
+ @samp{hook-foo} documented above.
+
+ @c It would be nice if hookpost could be passed a parameter indicating
+ @c if the command it hooks executed properly or not.
+
@kindex stop@r{, a pseudo-command}
In addition, a pseudo-command, @samp{stop} exists. Defining
diff -C2 -r -b ../insight-5.0/gdb/infrun.c src/gdb/infrun.c
*** ../insight-5.0/gdb/infrun.c Thu Apr 20 21:00:29 2000
--- src/gdb/infrun.c Tue Aug 15 11:18:07 2000
***************
*** 3431,3437 ****
/* Look up the hook_stop and run it if it exists. */
! if (stop_command && stop_command->hook)
{
! catch_errors (hook_stop_stub, stop_command->hook,
"Error while running hook_stop:\n", RETURN_MASK_ALL);
}
--- 3431,3437 ----
/* Look up the hook_stop and run it if it exists. */
! if (stop_command && stop_command->hook_pre)
{
! catch_errors (hook_stop_stub, stop_command->hook_pre,
"Error while running hook_stop:\n", RETURN_MASK_ALL);
}
diff -C2 -r -b ../insight-5.0/gdb/top.c src/gdb/top.c
*** ../insight-5.0/gdb/top.c Thu Apr 13 02:46:03 2000
--- src/gdb/top.c Thu Aug 17 11:17:13 2000
***************
*** 1528,1534 ****
}
! /* If this command has been hooked, run the hook first. */
! if (c->hook)
! execute_user_command (c->hook, (char *) 0);
if (c->flags & DEPRECATED_WARN_USER)
--- 1528,1538 ----
}
! /* If this command has been pre-hooked, run the hook first. */
! if ((c->hook_pre) && (!c->hook_in))
! {
! c->hook_in = 1; /* Prevent recursive hooking */
! execute_user_command (c->hook_pre, (char *) 0);
! c->hook_in = 0; /* Allow hook to work again once it is complete */
! }
if (c->flags & DEPRECATED_WARN_USER)
***************
*** 1545,1548 ****
--- 1549,1561 ----
else
(*c->function.cfunc) (arg, from_tty & caution);
+
+ /* If this command has been post-hooked, run the hook last. */
+ if ((c->hook_post) && (!c->hook_in))
+ {
+ c->hook_in = 1; /* Prevent recursive hooking */
+ execute_user_command (c->hook_post, (char *) 0);
+ c->hook_in = 0; /* allow hook to work again once it is complete */
+ }
+
}
***************
*** 3063,3072 ****
int from_tty;
{
register struct command_line *cmds;
! register struct cmd_list_element *c, *newc, *hookc = 0;
char *tem = comname;
! char tmpbuf[128];
#define HOOK_STRING "hook-"
#define HOOK_LEN 5
validate_comname (comname);
--- 3076,3098 ----
int from_tty;
{
+ #define MAX_TMPBUF 128
register struct command_line *cmds;
! register struct cmd_list_element *c, *newc, *oldc, *hookc = 0;
char *tem = comname;
! char *tem2;
! char tmpbuf[MAX_TMPBUF];
! int hook_type = 0; /* 0 = Not Hooked. 1 = Pre Hook, 2 = Post Hook */
! int hook_name_size = 0;
!
! #define NO_HOOK 0
! #define PRE_HOOK 1
! #define POST_HOOK 2
!
#define HOOK_STRING "hook-"
#define HOOK_LEN 5
+ #define HOOK_PRE_STRING "hookpre-"
+ #define HOOK_PRE_LEN 8
+ #define HOOK_POST_STRING "hookpost-"
+ #define HOOK_POST_LEN 9
validate_comname (comname);
***************
*** 3093,3100 ****
if (!strncmp (comname, HOOK_STRING, HOOK_LEN))
{
/* Look up cmd it hooks, and verify that we got an exact match. */
! tem = comname + HOOK_LEN;
hookc = lookup_cmd (&tem, cmdlist, "", -1, 0);
! if (hookc && !STREQ (comname + HOOK_LEN, hookc->name))
hookc = 0;
if (!hookc)
--- 3119,3173 ----
if (!strncmp (comname, HOOK_STRING, HOOK_LEN))
{
+ strncpy(tmpbuf,HOOK_PRE_STRING,MAX_TMPBUF);
+ strncat(tmpbuf,comname+HOOK_LEN,MAX_TMPBUF-HOOK_PRE_LEN);
+
+ tem2 = &tmpbuf[0];
+
+ oldc = lookup_cmd (&tem2, cmdlist, "", -1, 1);
+
+ if (oldc && STREQ (tmpbuf, oldc->name))
+ {
+ error ("Can not define \"%s\"! \"%s\" has already been defined.",
+ comname, oldc->name);
+ }
+ else
+ {
+ hook_type = PRE_HOOK;
+ hook_name_size = HOOK_LEN;
+ }
+
+ }
+ else if (!strncmp (comname, HOOK_PRE_STRING, HOOK_PRE_LEN))
+ {
+ strncpy(tmpbuf,HOOK_STRING,MAX_TMPBUF);
+ strncat(tmpbuf,comname+HOOK_PRE_LEN,MAX_TMPBUF-HOOK_LEN);
+
+ tem2 = &tmpbuf[0];
+
+ oldc = lookup_cmd (&tem2, cmdlist, "", -1, 1);
+
+ if (oldc && STREQ (tmpbuf, oldc->name))
+ {
+ error ("Can not define \"%s\"! \"%s\" has already been defined.",
+ comname, oldc->name);
+ }
+ else
+ {
+ hook_type = PRE_HOOK;
+ hook_name_size = HOOK_PRE_LEN;
+ }
+ }
+ else if (!strncmp (comname, HOOK_POST_STRING, HOOK_POST_LEN))
+ {
+ hook_type = POST_HOOK;
+ hook_name_size = HOOK_POST_LEN;
+ }
+
+ if (hook_type != NO_HOOK)
+ {
/* Look up cmd it hooks, and verify that we got an exact match. */
! tem = comname + hook_name_size;
hookc = lookup_cmd (&tem, cmdlist, "", -1, 0);
! if (hookc && !STREQ (comname + hook_name_size, hookc->name))
hookc = 0;
if (!hookc)
***************
*** 3130,3135 ****
if (hookc)
{
! hookc->hook = newc; /* Target gets hooked. */
! newc->hookee = hookc; /* We are marked as hooking target cmd. */
}
}
--- 3203,3219 ----
if (hookc)
{
! if (hook_type == PRE_HOOK)
! {
! hookc->hook_pre = newc; /* Target gets hooked. */
! hookc->hook_in = 0; /* Not in the hook yet. */
! newc->hookee_pre = hookc; /* We are marked as hooking target cmd.*/
! }
! else /* Must be a post hook, otherwise hookc would be 0. */
! {
! hookc->hook_post = newc; /* Target gets hooked */
! hookc->hook_in = 0; /* Not in the hook yet. */
! newc->hookee_post = hookc;/* We are marked as hooking target cmd. */
! }
!
}
}