diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2016-08-25 16:19:58 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2016-08-25 22:29:47 +0300 |
commit | e02fe00e6d2e83bc61764932f703831535105e5b (patch) | |
tree | bc1f6fc1856db2bcbe9effb10796f05a40bb5027 | |
parent | fd6ad25b5769d1497c991b9c1fec4632232cb80c (diff) | |
download | direvent-e02fe00e6d2e83bc61764932f703831535105e5b.tar.gz direvent-e02fe00e6d2e83bc61764932f703831535105e5b.tar.bz2 |
Get rid of hashtab.c, use symtab from grecs instead.
* grecs: Pull new version.
* src/hashtab.c: Remove.
* po/POTFILES.in: Remove src/hashtab.c
* src/Makefile.am (direvent_SOURCES): Remove hashtab.c
* src/config.c (grecs_parser_options): Set GRECS_OPTION_QUOTED_STRING_CONCAT.
* src/direvent.h: Remove hashtab prototypes.
* src/event.c: Use grecs_symtab.
* src/watcher.c: Likewise.
m--------- | grecs | 0 | ||||
-rw-r--r-- | po/POTFILES.in | 1 | ||||
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/config.c | 1 | ||||
-rw-r--r-- | src/direvent.h | 28 | ||||
-rw-r--r-- | src/event.c | 16 | ||||
-rw-r--r-- | src/hashtab.c | 466 | ||||
-rw-r--r-- | src/watcher.c | 36 |
8 files changed, 27 insertions, 522 deletions
diff --git a/grecs b/grecs -Subproject 6201e61fb932dbe6153f92ede836e07247d04b7 +Subproject c2f02c56a38a3e6d50b8ca2081db9d2de658b8e diff --git a/po/POTFILES.in b/po/POTFILES.in index 393b83d..c08d11b 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,13 +1,12 @@ # List of source files which contain translatable strings. src/cmdline.h src/config.c src/direvent.c src/environ.c -src/hashtab.c src/progman.c src/watcher.c grecs/src/format.c grecs/src/opthelp.c grecs/src/path-parser.c diff --git a/src/Makefile.am b/src/Makefile.am index bc13509..df09967 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -21,13 +21,12 @@ direvent_SOURCES=\ cmdline.h\ config.c\ environ.c\ event.c\ fnpat.c\ handler.c\ - hashtab.c\ watcher.c\ progman.c\ sigv.c if DIREVENT_INOTIFY direvent_SOURCES += ev_inotify.c detach-std.c diff --git a/src/config.c b/src/config.c index 6ad3016..3bbe36b 100644 --- a/src/config.c +++ b/src/config.c @@ -654,12 +654,13 @@ config_init(void) void config_parse(char const *conffile) { struct grecs_node *tree; + grecs_parser_options = GRECS_OPTION_QUOTED_STRING_CONCAT; tree = grecs_parse(conffile); if (!tree) exit(1); if (grecs_tree_process(tree, direvent_kw)) exit(1); diff --git a/src/direvent.h b/src/direvent.h index 2bb25dc..0bdfac5 100644 --- a/src/direvent.h +++ b/src/direvent.h @@ -22,12 +22,13 @@ #include <errno.h> #include <string.h> #include <unistd.h> #include <signal.h> #include <regex.h> #include <grecs/list.h> +#include <grecs/symtab.h> #include "gettext.h" #define _(s) gettext(s) #define N_(s) s /* Generic (system-independent) event codes */ @@ -194,39 +195,12 @@ extern struct transtab genev_transtab[]; extern struct transtab sysev_transtab[]; int trans_strtotok(struct transtab *tab, const char *str, int *ret); char *trans_toktostr(struct transtab *tab, int tok); char *trans_tokfirst(struct transtab *tab, int tok, int *next); char *trans_toknext(struct transtab *tab, int tok, int *next); - - -struct hashtab; -struct hashent { - int used; -}; -int hashtab_replace(struct hashtab *st, void *ent, void **old_ent); -const char *hashtab_strerror(int rc); -int hashtab_remove(struct hashtab *st, void *elt); -int hashtab_get_index(unsigned *idx, struct hashtab *st, void *key, - int *install); -void *hashtab_lookup_or_install(struct hashtab *st, void *key, int *install); -void hashtab_clear(struct hashtab *st); -struct hashtab *hashtab_create(size_t elsize, - unsigned (*hash_fun)(void *, unsigned long), - int (*cmp_fun)(const void *, const void *), - int (*copy_fun)(void *, void *), - void *(*alloc_fun)(size_t), - void (*free_fun)(void *)); -void hashtab_free(struct hashtab *st); - -typedef int (*hashtab_enumerator_t) (struct hashent *, void *); -int hashtab_foreach(struct hashtab *st, hashtab_enumerator_t fun, - void *data); -size_t hashtab_count(struct hashtab *st); - -unsigned hash_string(const char *name, unsigned long hashsize); struct pathent { long depth; size_t len; char path[1]; }; diff --git a/src/event.c b/src/event.c index 225cd4a..e977f0f 100644 --- a/src/event.c +++ b/src/event.c @@ -15,19 +15,18 @@ with direvent. If not, see <http://www.gnu.org/licenses/>. */ #include "direvent.h" struct symevt { - int used; char *name; event_mask mask; int line; }; -struct hashtab *evtab; +struct grecs_symtab *evtab; unsigned hash_string(const char *name, unsigned long hashsize) { unsigned i; @@ -57,13 +56,12 @@ symevt_cmp(const void *a, const void *b) static int symevt_copy(void *a, void *b) { struct symevt *syma = a; struct symevt *symb = b; - syma->used = 1; syma->name = estrdup(symb->name); return 0; } static void symevt_free(void *p) @@ -78,24 +76,24 @@ int defevt(const char *name, event_mask *mask, int line) { struct symevt key, *evp; int install = 1; if (!evtab) { - evtab = hashtab_create(sizeof(struct symevt), - symevt_hash, symevt_cmp, - symevt_copy, - NULL, symevt_free); + evtab = grecs_symtab_create(sizeof(struct symevt), + symevt_hash, symevt_cmp, + symevt_copy, + NULL, symevt_free); if (!evtab) { diag(LOG_CRIT, "not enough memory"); exit(1); } } key.name = (char *) name; - evp = hashtab_lookup_or_install(evtab, &key, &install); + evp = grecs_symtab_lookup_or_install(evtab, &key, &install); if (!install) return evp->line; evp->mask = *mask; evp->line = line; return 0; } @@ -103,13 +101,13 @@ defevt(const char *name, event_mask *mask, int line) int getevt(const char *name, event_mask *mask) { if (evtab) { struct symevt key, *evp; key.name = (char *) name; - evp = hashtab_lookup_or_install(evtab, &key, NULL); + evp = grecs_symtab_lookup_or_install(evtab, &key, NULL); if (evp) { *mask = evp->mask; return 0; } } if (trans_strtotok(sysev_transtab, name, &mask->sys_mask)) diff --git a/src/hashtab.c b/src/hashtab.c deleted file mode 100644 index e9f0295..0000000 --- a/src/hashtab.c +++ /dev/null @@ -1,466 +0,0 @@ -/* This file is part of Direvent. - Copyright (C) 2012-2016 Sergey Poznyakoff. - - Direvent is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - Direvent is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Direvent. If not, see <http://www.gnu.org/licenses/>. */ - -#include "direvent.h" - -/* |hash_size| defines a sequence of symbol table sizes. These are prime - numbers, each of which is approximately twice its predecessor. */ - -static unsigned int hash_size[] = { - 7, 17, 37, 101, 229, 487, 1009, 2039, 4091, 8191, 16411, - 32831, 65647, 131231, 262469, 524921, 1049849, 2099707 -}; - -/* |max_rehash| keeps the number of entries in |hash_size| table. */ -static unsigned int max_rehash = sizeof(hash_size) / sizeof(hash_size[0]); - -struct hashent_list_entry { - struct hashent_list_entry *prev, *next; - struct hashent *ent; -}; - -struct hashent_list { - struct hashent_list_entry *head, *tail; -}; - -struct hashtab { - unsigned int hash_num; /* Index to hash_size table */ - size_t elsize; /* Size of an element */ - size_t elcount; /* Number of elements in use */ - struct hashent **tab; - unsigned (*hash_fun)(void *, unsigned long hash_num); - int (*cmp_fun)(const void *, const void *); - int (*copy_fun)(void *, void *); - void *(*hashent_alloc_fun)(size_t size); - void (*hashent_free_fun) (void *); - - unsigned int itr_level; - struct hashent_list list_new, list_del; -}; - -static void -hashent_list_init(struct hashent_list *list) -{ - list->head = NULL; - list->tail = NULL; -} - -static int -hashent_list_append(struct hashent_list *list, struct hashent *ent) -{ - struct hashent_list_entry *hent = malloc(sizeof(*hent)); - if (!hent) - return -1; - hent->ent = ent; - hent->next = NULL; - hent->prev = list->tail; - if (list->tail) - list->tail->next = hent; - else - list->head = hent; - list->tail = hent; - return 0; -} - -static void -hashent_list_remove(struct hashent_list *list, struct hashent_list_entry *hent) -{ - struct hashent_list_entry *p; - if ((p = hent->prev)) - p->next = hent->next; - else - list->head = hent->next; - if ((p = hent->next)) - p->prev = hent->prev; - else - list->tail = hent->prev; - free(hent); -} - -static struct hashent_list_entry * -hashent_list_lookup(struct hashtab *st, struct hashent_list *list, - struct hashent *ent) -{ - struct hashent_list_entry *p; - for (p = list->head; p; p = p->next) { - if (st->cmp_fun(p->ent, ent) == 0) - return p; - } - return NULL; -} - -static void -hashent_free(struct hashtab *st, void *ptr) -{ - if (st->hashent_free_fun) - st->hashent_free_fun(ptr); - else - free(ptr); -} - -static struct hashent * -hashent_alloc(struct hashtab *st, void *key) -{ - struct hashent *ent; - - ent = st->hashent_alloc_fun ? - st->hashent_alloc_fun(st->elsize) : malloc(st->elsize); - if (ent) { - memset(ent, 0, st->elsize); - if (st->copy_fun(ent, key)) { - int ec = errno; - hashent_free(st, ent); - errno = ec; - return NULL; - } - } - return ent; -} - - -static unsigned -hashtab_insert_pos(struct hashtab *st, void *elt) -{ - unsigned i; - unsigned pos = st->hash_fun(elt, hash_size[st->hash_num]); - - for (i = pos; st->tab[i];) { - if (++i >= hash_size[st->hash_num]) - i = 0; - if (i == pos) - /* FIXME: Error message? */ - abort(); - } - return i; -} - -int -hashtab_replace(struct hashtab *st, void *ent, void **old_ent) -{ - struct hashent *entry; - unsigned i, pos = st->hash_fun(ent, hash_size[st->hash_num]); - for (i = pos; entry = st->tab[i];) { - if (st->cmp_fun(entry, ent) == 0) - break; - if (++i >= hash_size[st->hash_num]) - i = 0; - if (i == pos) - return ENOENT; - } - if (old_ent) - *old_ent = entry; - st->tab[i] = ent; - return 0; -} - -static int -hashtab_rehash(struct hashtab *st) -{ - struct hashent **old_tab = st->tab; - struct hashent **new_tab; - unsigned int i; - unsigned int hash_num = st->hash_num + 1; - - if (hash_num >= max_rehash) - return E2BIG; - - new_tab = calloc(hash_size[hash_num], sizeof(*new_tab)); - if (!new_tab) - return ENOMEM; - st->tab = new_tab; - if (old_tab) { - st->hash_num = hash_num; - for (i = 0; i < hash_size[hash_num-1]; i++) { - struct hashent *elt = old_tab[i]; - if (elt->used) { - unsigned n = hashtab_insert_pos(st, elt); - new_tab[n] = elt; - } - } - free(old_tab); - } - return 0; -} - -const char * -hashtab_strerror(int rc) -{ - switch (rc) { - case ENOENT: - return _("element not found in table"); - case E2BIG: - return _("symbol table is full"); - case ENOMEM: - return _("out of memory"); - } - return strerror(rc); -} - -int -hashtab_remove(struct hashtab *st, void *elt) -{ - unsigned int pos, i, j, r; - struct hashent *entry; - - if (st->itr_level) { - struct hashent_list_entry *hent; - hent = hashent_list_lookup(st, &st->list_new, elt); - if (hent) { - entry = hent->ent; - hashent_list_remove(&st->list_new, hent); - hashent_free(st, entry); - return 0; - } - } - - pos = st->hash_fun(elt, hash_size[st->hash_num]); - for (i = pos; entry = st->tab[i];) { - if (st->cmp_fun(entry, elt) == 0) - break; - if (++i >= hash_size[st->hash_num]) - i = 0; - if (i == pos) - return ENOENT; - } - - if (!entry) - return ENOENT; - - if (st->itr_level) { - if (hashent_list_append(&st->list_del, entry)) - return ENOMEM; - entry->used = 0; - return 0; - } - - hashent_free(st, entry); - st->elcount--; - - for (;;) { - st->tab[i] = NULL; - j = i; - - do { - if (++i >= hash_size[st->hash_num]) - i = 0; - if (!st->tab[i]) - return 0; - r = st->hash_fun(st->tab[i], hash_size[st->hash_num]); - } while ((j < r && r <= i) - || (i < j && j < r) || (r <= i && i < j)); - st->tab[j] = st->tab[i]; - } - - return 0; -} - -int -hashtab_get_index(unsigned *idx, struct hashtab *st, void *key, int *install) -{ - int rc; - unsigned i, pos; - struct hashent *elem; - - if (!st->tab) { - if (install) { - rc = hashtab_rehash(st); - if (rc) - return rc; - } else - return ENOENT; - } - - pos = st->hash_fun(key, hash_size[st->hash_num]); - - for (i = pos; elem = st->tab[i];) { - if (st->cmp_fun(elem, key) == 0) { - if (install) - *install = 0; - *idx = i; - return 0; - } - - if (++i >= hash_size[st->hash_num]) - i = 0; - if (i == pos) - break; - } - - if (!install) - return ENOENT; - - if (!elem) { - *install = 1; - *idx = i; - return 0; - } - - if ((rc = hashtab_rehash(st)) != 0) - return rc; - - return hashtab_get_index(idx, st, key, install); -} - -void * -hashtab_lookup_or_install(struct hashtab *st, void *key, int *install) -{ - unsigned i; - int rc = hashtab_get_index(&i, st, key, install); - if (rc == 0) { - if (install && *install == 1) { - struct hashent *ent = hashent_alloc(st, key); - if (!ent) { - errno = ENOMEM; - return NULL; - } - if (st->itr_level) { - if (hashent_list_append(&st->list_new, ent)) { - int ec = errno; - hashent_free(st, ent); - errno = ec; - return NULL; - } - return ent; - } - st->tab[i] = ent; - st->elcount++; - return ent; - } else - return st->tab[i]; - } else if (rc == ENOENT && st->itr_level) { - struct hashent_list_entry *hent; - hent = hashent_list_lookup(st, &st->list_new, key); - if (hent) - return hent->ent; - rc = ENOENT; - } - errno = rc; - return NULL; -} - -void -hashtab_clear(struct hashtab *st) -{ - unsigned i, hs; - - if (!st || !st->tab) - return; - - hs = hash_size[st->hash_num]; - for (i = 0; i < hs; i++) { - struct hashent *elem = st->tab[i]; - if (elem) { - hashent_free(st, elem); - st->tab[i] = NULL; - } - } - st->elcount = 0; -} - -struct hashtab * -hashtab_create(size_t elsize, - unsigned (*hash_fun)(void *, unsigned long), - int (*cmp_fun)(const void *, const void *), - int (*copy_fun)(void *, void *), - void *(*alloc_fun)(size_t), void (*free_fun)(void *)) -{ - struct hashtab *st = malloc(sizeof(*st)); - if (st) { - memset(st, 0, sizeof(*st)); - st->elsize = elsize; - st->elcount = 0; - st->hash_fun = hash_fun; - st->cmp_fun = cmp_fun; - st->copy_fun = copy_fun; - st->hashent_alloc_fun = alloc_fun; - st->hashent_free_fun = free_fun; - st->tab = calloc(hash_size[st->hash_num], sizeof(*st->tab)); - if (!st->tab) { - free(st); - st = NULL; - } - } - return st; -} - -void -hashtab_free(struct hashtab *st) -{ - if (st) { - hashtab_clear(st); - free(st->tab); - free(st); - } -} - -int -hashtab_foreach(struct hashtab *st, hashtab_enumerator_t fun, void *data) -{ - unsigned i; - int rc = 0; - - if (!st) - return 0; - - if (st->itr_level++ == 0) { - hashent_list_init(&st->list_new); - hashent_list_init(&st->list_del); - } - - for (i = 0; i < hash_size[st->hash_num]; i++) { - struct hashent *ep = st->tab[i]; - if (ep) { - rc = fun(ep, data); - if (rc) - break; - } - } - - if (--st->itr_level == 0) { - while (st->list_del.head) { - struct hashent *ent = st->list_del.head->ent; - hashent_list_remove(&st->list_del, st->list_del.head); - hashtab_remove(st, ent); - } - - while (st->list_new.head) { - struct hashent *ent = st->list_new.head->ent; - unsigned i; - int install = 1; - if (hashtab_get_index(&i, st, ent, &install) == 0) { - st->tab[i] = ent; - st->elcount++; - } - hashent_list_remove(&st->list_new, st->list_new.head); - } - } - - return rc; -} - -size_t -hashtab_count(struct hashtab *st) -{ - return st ? st->elcount : 0; -} - - - - - - - - diff --git a/src/watcher.c b/src/watcher.c index c964022..c16b0e6 100644 --- a/src/watcher.c +++ b/src/watcher.c @@ -41,13 +41,13 @@ struct wpref { }; static unsigned wpref_hash(void *data, unsigned long hashsize) { struct wpref *sym = data; - return hash_string(sym->wpt->dirname, hashsize); + return grecs_hash_string(sym->wpt->dirname, hashsize); } static int wpref_cmp(const void *a, const void *b) { struct wpref const *syma = a; @@ -72,35 +72,35 @@ wpref_free(void *p) { struct wpref *wpref = p; watchpoint_unref(wpref->wpt); free(wpref); } -struct hashtab *nametab; +struct grecs_symtab *nametab; struct watchpoint * watchpoint_install(const char *path, int *pnew) { struct watchpoint wpkey; struct wpref key; struct wpref *ent; int install = 1; if (!nametab) { - nametab = hashtab_create(sizeof(struct wpref), - wpref_hash, wpref_cmp, wpref_copy, - NULL, wpref_free); + nametab = grecs_symtab_create(sizeof(struct wpref), + wpref_hash, wpref_cmp, wpref_copy, + NULL, wpref_free); if (!nametab) { diag(LOG_CRIT, _("not enough memory")); exit(1); } } wpkey.dirname = (char*) path; key.wpt = &wpkey; - ent = hashtab_lookup_or_install(nametab, &key, &install); + ent = grecs_symtab_lookup_or_install(nametab, &key, &install); if (install) { struct watchpoint *wpt = ecalloc(1, sizeof(*wpt)); wpt->dirname = estrdup(path); wpt->wd = -1; wpt->handler_list = handler_list_create(); wpt->refcnt = 0; @@ -118,13 +118,13 @@ struct watchpoint * watchpoint_install_ptr(struct watchpoint *wpt) { struct wpref key; int install = 1; key.wpt = wpt; - if (!hashtab_lookup_or_install(nametab, &key, &install)) { + if (!grecs_symtab_lookup_or_install(nametab, &key, &install)) { diag(LOG_CRIT, _("not enough memory")); exit(1); } watchpoint_ref(wpt); return wpt; } @@ -156,13 +156,13 @@ watchpoint_lookup(const char *dirname) if (!nametab) return NULL; wpkey.dirname = (char*) dirname; key.wpt = &wpkey; - ent = hashtab_lookup_or_install(nametab, &key, NULL); + ent = grecs_symtab_lookup_or_install(nametab, &key, NULL); return ent ? ent->wpt : NULL; } static void watchpoint_remove(const char *dirname) { @@ -171,13 +171,13 @@ watchpoint_remove(const char *dirname) if (!nametab) return; wpkey.dirname = (char*) dirname; key.wpt = &wpkey; - hashtab_remove(nametab, &key); + grecs_symtab_remove(nametab, &key); } void watchpoint_destroy(struct watchpoint *wpt) { debug(1, (_("removing watcher %s"), wpt->dirname)); @@ -188,13 +188,13 @@ watchpoint_destroy(struct watchpoint *wpt) void watchpoint_suspend(struct watchpoint *wpt) { if (!wpt->parent) /* A top-level watchpoint */ watchpoint_install_sentinel(wpt);//FIXME: error checking watchpoint_destroy(wpt); - if (hashtab_count(nametab) == 0) { + if (grecs_symtab_count(nametab) == 0) { diag(LOG_CRIT, _("no watchers left; exiting now")); stop = 1; } } struct sentinel { @@ -468,47 +468,47 @@ watch_subdirs(struct watchpoint *parent, int notify) closedir(dir); return total; } static int -setwatcher(struct hashent *ent, void *data) +setwatcher(void *ent, void *data) { struct wpref *wpref = (struct wpref *) ent; struct watchpoint *wpt = wpref->wpt; if (wpt->wd == -1 && watchpoint_init(wpt) == 0) watch_subdirs(wpt, 0); return 0; } static int -checkwatcher(struct hashent *ent, void *data) +checkwatcher(void *ent, void *data) { struct wpref *wpref = (struct wpref *) ent; struct watchpoint *wpt = wpref->wpt; return wpt->wd >= 0; } void setup_watchers(void) { sysev_init(); - if (hashtab_count(nametab) == 0) { + if (grecs_symtab_count(nametab) == 0) { diag(LOG_CRIT, _("no event handlers configured")); exit(1); } - hashtab_foreach(nametab, setwatcher, NULL); - if (!hashtab_foreach(nametab, checkwatcher, NULL)) { + grecs_symtab_foreach(nametab, setwatcher, NULL); + if (!grecs_symtab_foreach(nametab, checkwatcher, NULL)) { diag(LOG_CRIT, _("no event handlers installed")); exit(2); } } static int -stopwatcher(struct hashent *ent, void *data) +stopwatcher(void *ent, void *data) { struct wpref *wpref = (struct wpref *) ent; struct watchpoint *wpt = wpref->wpt; if (wpt->wd != -1) { debug(1, (_("removing watcher %s"), wpt->dirname)); sysev_rm_watch(wpt); @@ -516,14 +516,14 @@ stopwatcher(struct hashent *ent, void *data) return 0; } void shutdown_watchers(void) { - hashtab_foreach(nametab, stopwatcher, NULL); - hashtab_clear(nametab); + grecs_symtab_foreach(nametab, stopwatcher, NULL); + grecs_symtab_clear(nametab); } char * split_pathname(struct watchpoint *dp, char **dirname) { |