gdb
authorTom Tromey <tromey@redhat.com>
Wed, 10 Dec 2008 01:05:16 +0000 (01:05 +0000)
committerTom Tromey <tromey@redhat.com>
Wed, 10 Dec 2008 01:05:16 +0000 (01:05 +0000)
PR gdb/1815:
* cli/cli-decode.c (delete_cmd): Forward declare.
(delete_cmd): Now static.  Change return type.  Remove command
from alias chain.  Rewrite.
(add_cmd): Initialize new fields.  Update cmd_pointer on all
aliases.
(add_alias_cmd): Put command on alias chain.
* command.h (delete_cmd): Don't declare.
* cli/cli-decode.h (delete_cmd): Don't declare.
(struct cmd_list_element) <aliases, alias_chain>: New fields.
gdb/testsuite
* gdb.base/commands.exp (redefine_backtrace_test): New proc.
Call it.

gdb/ChangeLog
gdb/cli/cli-decode.c
gdb/cli/cli-decode.h
gdb/command.h
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/commands.exp

index 19a4275cd9aec35b76681e4ef70f9a78b90e541e..cb3917f1547b7bf2e6a5727685930203f90d4c16 100644 (file)
@@ -1,3 +1,16 @@
+2008-12-09  Tom Tromey  <tromey@redhat.com>
+
+       PR gdb/1815:
+       * cli/cli-decode.c (delete_cmd): Forward declare.
+       (delete_cmd): Now static.  Change return type.  Remove command
+       from alias chain.  Rewrite.
+       (add_cmd): Initialize new fields.  Update cmd_pointer on all
+       aliases.
+       (add_alias_cmd): Put command on alias chain.
+       * command.h (delete_cmd): Don't declare.
+       * cli/cli-decode.h (delete_cmd): Don't declare.
+       (struct cmd_list_element) <aliases, alias_chain>: New fields.
+
 2008-12-09  Tom Tromey  <tromey@redhat.com>
 
        * config.in, configure: Rebuild.
index 9cc52bab471cb7d1c5407d14f5cfdc3ebe8d3789..613b8d738a021f9a5a7d00c15b328314f357a06c 100644 (file)
@@ -37,6 +37,9 @@
 
 static void undef_cmd_error (char *, char *);
 
+static struct cmd_list_element *delete_cmd (char *name,
+                                           struct cmd_list_element **list);
+
 static struct cmd_list_element *find_cmd (char *command,
                                          int len,
                                          struct cmd_list_element *clist,
@@ -154,9 +157,13 @@ add_cmd (char *name, enum command_class class, void (*fun) (char *, int),
 {
   struct cmd_list_element *c
   = (struct cmd_list_element *) xmalloc (sizeof (struct cmd_list_element));
-  struct cmd_list_element *p;
+  struct cmd_list_element *p, *iter;
 
-  delete_cmd (name, list);
+  /* Turn each alias of the old command into an alias of the new
+     command.  */
+  c->aliases = delete_cmd (name, list);
+  for (iter = c->aliases; iter; iter = iter->alias_chain)
+    iter->cmd_pointer = c;
 
   if (*list == NULL || strcmp ((*list)->name, name) >= 0)
     {
@@ -198,6 +205,7 @@ add_cmd (char *name, enum command_class class, void (*fun) (char *, int),
   c->hookee_pre = NULL;
   c->hookee_post = NULL;
   c->cmd_pointer = NULL;
+  c->alias_chain = NULL;
 
   return c;
 }
@@ -239,7 +247,9 @@ add_alias_cmd (char *name, char *oldname, enum command_class class,
 
   if (old == 0)
     {
-      delete_cmd (name, list);
+      struct cmd_list_element *aliases = delete_cmd (name, list);
+      /* If this happens, it means a programmer error somewhere.  */
+      gdb_assert (!aliases);
       return 0;
     }
 
@@ -252,6 +262,8 @@ add_alias_cmd (char *name, char *oldname, enum command_class class,
   c->allow_unknown = old->allow_unknown;
   c->abbrev_flag = abbrev_flag;
   c->cmd_pointer = old;
+  c->alias_chain = old->aliases;
+  old->aliases = c;
   return c;
 }
 
@@ -614,42 +626,58 @@ add_setshow_zinteger_cmd (char *name, enum command_class class,
                        NULL, NULL);
 }
 
-/* Remove the command named NAME from the command list.  */
+/* Remove the command named NAME from the command list.  Return the
+   list commands which were aliased to the deleted command.  If the
+   command had no aliases, return NULL.  */
 
-void
+static struct cmd_list_element *
 delete_cmd (char *name, struct cmd_list_element **list)
 {
-  struct cmd_list_element *c;
-  struct cmd_list_element *p;
+  struct cmd_list_element *iter;
+  struct cmd_list_element **previous_chain_ptr;
+  struct cmd_list_element *aliases = NULL;
+
+  previous_chain_ptr = list;
 
-  while (*list && strcmp ((*list)->name, name) == 0)
+  for (iter = *previous_chain_ptr; iter; iter = *previous_chain_ptr)
     {
-      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 bottom  */
-      p = (*list)->next;
-      xfree (* list);
-      *list = p;
+      if (strcmp (iter->name, name) == 0)
+       {
+         if (iter->hookee_pre)
+           iter->hookee_pre->hook_pre = 0;
+         if (iter->hookee_post)
+           iter->hookee_post->hook_post = 0;
+
+         /* Update the link.  */
+         *previous_chain_ptr = iter->next;
+
+         aliases = iter->aliases;
+
+         /* If this command was an alias, remove it from the list of
+            aliases.  */
+         if (iter->cmd_pointer)
+           {
+             struct cmd_list_element **prevp = &iter->cmd_pointer->aliases;
+             struct cmd_list_element *a = *prevp;
+
+             while (a != iter)
+               {
+                 prevp = &a->alias_chain;
+                 a = *prevp;
+               }
+             *prevp = iter->alias_chain;
+           }
+
+         xfree (iter);
+
+         /* We won't see another command with the same name.  */
+         break;
+       }
+      else
+       previous_chain_ptr = &iter->next;
     }
 
-  if (*list)
-    for (c = *list; c->next;)
-      {
-       if (strcmp (c->next->name, name) == 0)
-         {
-          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 */
-                                               /* :( no fishing metaphore */
-           p = c->next->next;
-           xfree (c->next);
-           c->next = p;
-         }
-       else
-         c = c->next;
-      }
+  return aliases;
 }
 \f
 /* Shorthands to the commands above. */
index 4e2dbc159f6092702c99db68968ef0f99c370b5f..9d27f0f73f5385174b15c4603ccb32db786e3231 100644 (file)
@@ -197,6 +197,12 @@ struct cmd_list_element
     /* Pointer to command that is aliased by this one, so the
        aliased command can be located in case it has been hooked.  */
     struct cmd_list_element *cmd_pointer;
+
+    /* Start of a linked list of all aliases of this command.  */
+    struct cmd_list_element *aliases;
+
+    /* Link pointer for aliases on an alias list.  */
+    struct cmd_list_element *alias_chain;
   };
 
 /* API to the manipulation of command lists.  */
@@ -290,8 +296,6 @@ extern char **complete_on_cmdlist (struct cmd_list_element *, char *, char *);
 
 extern char **complete_on_enum (const char *enumlist[], char *, char *);
 
-extern void delete_cmd (char *, struct cmd_list_element **);
-
 extern void help_cmd_list (struct cmd_list_element *, enum command_class,
                           char *, int, struct ui_file *);
 
index cf09c011a331ac7b680f2cbf92ecaf8be320c280..5678c9e2ed7753ab645e5e622a25775b7a904cf6 100644 (file)
@@ -193,8 +193,6 @@ extern char **complete_on_cmdlist (struct cmd_list_element *, char *, char *);
 
 extern char **complete_on_enum (const char *enumlist[], char *, char *);
 
-extern void delete_cmd (char *, struct cmd_list_element **);
-
 extern void help_cmd (char *, struct ui_file *);
 
 extern void help_list (struct cmd_list_element *, char *,
index ab628c800d299e9cd41f2a378ccd6bfbe8d53c08..88cbff8b6bf1c50f44ad8ff1c176655c3ae631bb 100644 (file)
@@ -1,3 +1,8 @@
+2008-12-09  Tom Tromey  <tromey@redhat.com>
+
+       * gdb.base/commands.exp (redefine_backtrace_test): New proc.
+       Call it.
+
 2008-12-04  Doug Evans  <dje@google.com>
 
        * gdb.server/ext-run.exp: Relax regexp for init program.
index 301b9951d777470dfe4b91e74129b122c1a13949..f6be3ea20a2378e92a95c8fe436c8867003ac7a5 100644 (file)
@@ -692,6 +692,34 @@ proc if_commands_test {} {
     }
 }
 
+proc redefine_backtrace_test {} {
+    global gdb_prompt
+
+    gdb_test_multiple "define backtrace" "define backtrace" {
+       -re "Really redefine built-in.*$" {
+           send_gdb "y\n"
+           exp_continue
+       }
+
+       -re "End with"  {
+           pass "define backtrace in redefine_backtrace_test"
+       }
+        default {
+           fail "(timeout or eof) define backtrace in redefine_backtrace_test"
+       }
+    }
+    gdb_test "echo hibob\\n\nend" \
+           "" \
+           "enter commands in redefine_backtrace_test"
+
+    gdb_test "backtrace" \
+           "hibob" \
+           "execute backtrace command in redefine_backtrace_test"
+    gdb_test "bt" \
+           "hibob" \
+           "execute bt command in redefine_backtrace_test"
+}
+
 gdbvar_simple_if_test
 gdbvar_simple_while_test
 gdbvar_complex_if_while_test
@@ -710,3 +738,5 @@ temporary_breakpoint_commands
 stray_arg0_test
 recursive_source_test
 if_commands_test
+# This one should come last, as it redefines "backtrace".
+redefine_backtrace_test