Patch to Command Hook Handling (Again).

Steven Johnson sbjohnson@ozemail.com.au
Wed Aug 16 17:18:00 GMT 2000


Sorry,
I Noticed that netscape line wrapped my message and wrecked the Changelog
entries and Patch, so I fixed it. This one should be OK.

Attached is a patch that achieves the following:

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.hook and
          cmd_list_element.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   Tue Aug 15 13:18:14 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 suitable
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,560 ----
      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       Wed Aug 16 09:45:28 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,3171 ----
    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.  */
      }
  }
--- 3201,3217 ----
    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;
!         newc->hookee_post = hookc;    /* We are marked as hooking target cmd. */
!       }
!          
      }
  }


More information about the Gdb-patches mailing list