We cannot do hooks_find and then hooks_remove because it might have come

from the parent (global) tree, instead make it remove by name like options.

While here, also tidy up a few bits of options and hooks handling (use
RB_FOREACH_SAFE, and a helper function for the free).
This commit is contained in:
nicm 2015-12-11 15:46:57 +00:00
parent d7e11d0af7
commit bd5918760e
4 changed files with 43 additions and 34 deletions

View File

@ -93,8 +93,7 @@ cmd_set_hook_exec(struct cmd *self, struct cmd_q *cmdq)
name); name);
return (CMD_RETURN_ERROR); return (CMD_RETURN_ERROR);
} }
if ((hook = hooks_find(hooks, name)) != NULL) hooks_remove(hooks, name);
hooks_remove(hooks, hook);
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
} }

28
hooks.c
View File

@ -32,7 +32,8 @@ static int hooks_cmp(struct hook *, struct hook *);
RB_PROTOTYPE(hooks_tree, hook, entry, hooks_cmp); RB_PROTOTYPE(hooks_tree, hook, entry, hooks_cmp);
RB_GENERATE(hooks_tree, hook, entry, hooks_cmp); RB_GENERATE(hooks_tree, hook, entry, hooks_cmp);
struct hook *hooks_find1(struct hooks *, const char *); static struct hook *hooks_find1(struct hooks *, const char *);
static void hooks_free1(struct hooks *, struct hook *);
static int static int
hooks_cmp(struct hook *hook1, struct hook *hook2) hooks_cmp(struct hook *hook1, struct hook *hook2)
@ -51,13 +52,22 @@ hooks_create(struct hooks *parent)
return (hooks); return (hooks);
} }
static void
hooks_free1(struct hooks *hooks, struct hook *hook)
{
RB_REMOVE(hooks_tree, &hooks->tree, hook);
cmd_list_free(hook->cmdlist);
free((char *)hook->name);
free(hook);
}
void void
hooks_free(struct hooks *hooks) hooks_free(struct hooks *hooks)
{ {
struct hook *hook, *hook1; struct hook *hook, *hook1;
RB_FOREACH_SAFE(hook, hooks_tree, &hooks->tree, hook1) RB_FOREACH_SAFE(hook, hooks_tree, &hooks->tree, hook1)
hooks_remove(hooks, hook); hooks_free1(hooks, hook);
free(hooks); free(hooks);
} }
@ -79,7 +89,7 @@ hooks_add(struct hooks *hooks, const char *name, struct cmd_list *cmdlist)
struct hook *hook; struct hook *hook;
if ((hook = hooks_find1(hooks, name)) != NULL) if ((hook = hooks_find1(hooks, name)) != NULL)
hooks_remove(hooks, hook); hooks_free1(hooks, hook);
hook = xcalloc(1, sizeof *hook); hook = xcalloc(1, sizeof *hook);
hook->name = xstrdup(name); hook->name = xstrdup(name);
@ -89,15 +99,15 @@ hooks_add(struct hooks *hooks, const char *name, struct cmd_list *cmdlist)
} }
void void
hooks_remove(struct hooks *hooks, struct hook *hook) hooks_remove(struct hooks *hooks, const char *name)
{ {
RB_REMOVE(hooks_tree, &hooks->tree, hook); struct hook *hook;
cmd_list_free(hook->cmdlist);
free((char *) hook->name); if ((hook = hooks_find1(hooks, name)) != NULL)
free(hook); hooks_free1(hooks, hook);
} }
struct hook * static struct hook *
hooks_find1(struct hooks *hooks, const char *name) hooks_find1(struct hooks *hooks, const char *name)
{ {
struct hook hook; struct hook hook;

View File

@ -34,11 +34,13 @@ struct options {
struct options *parent; struct options *parent;
}; };
int options_cmp(struct options_entry *, struct options_entry *); static int options_cmp(struct options_entry *, struct options_entry *);
RB_PROTOTYPE(options_tree, options_entry, entry, options_cmp); RB_PROTOTYPE(options_tree, options_entry, entry, options_cmp);
RB_GENERATE(options_tree, options_entry, entry, options_cmp); RB_GENERATE(options_tree, options_entry, entry, options_cmp);
int static void options_free1(struct options *, struct options_entry *);
static int
options_cmp(struct options_entry *o1, struct options_entry *o2) options_cmp(struct options_entry *o1, struct options_entry *o2)
{ {
return (strcmp(o1->name, o2->name)); return (strcmp(o1->name, o2->name));
@ -55,19 +57,23 @@ options_create(struct options *parent)
return (oo); return (oo);
} }
static void
options_free1(struct options *oo, struct options_entry *o)
{
RB_REMOVE(options_tree, &oo->tree, o);
free((char *)o->name);
if (o->type == OPTIONS_STRING)
free(o->str);
free(o);
}
void void
options_free(struct options *oo) options_free(struct options *oo)
{ {
struct options_entry *o; struct options_entry *o, *o1;
while (!RB_EMPTY(&oo->tree)) { RB_FOREACH_SAFE (o, options_tree, &oo->tree, o1)
o = RB_ROOT(&oo->tree); options_free1(oo, o);
RB_REMOVE(options_tree, &oo->tree, o);
free(o->name);
if (o->type == OPTIONS_STRING)
free(o->str);
free(o);
}
free(oo); free(oo);
} }
@ -88,7 +94,7 @@ options_find1(struct options *oo, const char *name)
{ {
struct options_entry p; struct options_entry p;
p.name = (char *) name; p.name = (char *)name;
return (RB_FIND(options_tree, &oo->tree, &p)); return (RB_FIND(options_tree, &oo->tree, &p));
} }
@ -97,7 +103,7 @@ options_find(struct options *oo, const char *name)
{ {
struct options_entry *o, p; struct options_entry *o, p;
p.name = (char *) name; p.name = (char *)name;
o = RB_FIND(options_tree, &oo->tree, &p); o = RB_FIND(options_tree, &oo->tree, &p);
while (o == NULL) { while (o == NULL) {
oo = oo->parent; oo = oo->parent;
@ -113,14 +119,8 @@ options_remove(struct options *oo, const char *name)
{ {
struct options_entry *o; struct options_entry *o;
if ((o = options_find1(oo, name)) == NULL) if ((o = options_find1(oo, name)) != NULL)
return; options_free1(oo, o);
RB_REMOVE(options_tree, &oo->tree, o);
free(o->name);
if (o->type == OPTIONS_STRING)
free(o->str);
free(o);
} }
struct options_entry * struct options_entry *

4
tmux.h
View File

@ -703,7 +703,7 @@ struct hook {
/* Option data structures. */ /* Option data structures. */
struct options_entry { struct options_entry {
char *name; const char *name;
enum { enum {
OPTIONS_STRING, OPTIONS_STRING,
@ -1514,7 +1514,7 @@ struct hook *hooks_first(struct hooks *);
struct hook *hooks_next(struct hook *); struct hook *hooks_next(struct hook *);
void hooks_add(struct hooks *, const char *, struct cmd_list *); void hooks_add(struct hooks *, const char *, struct cmd_list *);
void hooks_copy(struct hooks *, struct hooks *); void hooks_copy(struct hooks *, struct hooks *);
void hooks_remove(struct hooks *, struct hook *); void hooks_remove(struct hooks *, const char *);
struct hook *hooks_find(struct hooks *, const char *); struct hook *hooks_find(struct hooks *, const char *);
void hooks_run(struct hooks *, const char *, struct client *); void hooks_run(struct hooks *, const char *, struct client *);