summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bootstrap.conf4
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/README1
-rw-r--r--lib/glcontainers.h11
-rw-r--r--lib/hashtable.c232
-rw-r--r--lib/hashtable.h61
-rw-r--r--lib/orderfiles.c25
-rw-r--r--libdb/db_btree.c26
-rw-r--r--libdb/db_gdbm.c177
-rw-r--r--src/check_mandirs.c37
-rw-r--r--src/globbing.c39
-rw-r--r--src/man.c49
-rw-r--r--src/mandb.c46
-rw-r--r--src/whatis.c14
14 files changed, 220 insertions, 504 deletions
diff --git a/bootstrap.conf b/bootstrap.conf
index 27747b55..a86cb762 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -38,7 +38,9 @@ gnulib_modules="
gitlog-to-changelog
glob
gnupload
+ hash-map
hash-pjw-bare
+ hash-set
idpriv-drop
idpriv-droptemp
lchown
@@ -74,6 +76,8 @@ gnulib_modules="
xalloc
xgetcwd
xlist
+ xmap
+ xset
xstdopen
xstrndup
xvasprintf
diff --git a/lib/Makefile.am b/lib/Makefile.am
index d8be3716..731bd331 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -43,8 +43,6 @@ libman_la_SOURCES = \
encodings.h \
glcontainers.c \
glcontainers.h \
- hashtable.c \
- hashtable.h \
linelength.c \
linelength.h \
lower.c \
diff --git a/lib/README b/lib/README
index ba2c691c..9f32f237 100644
--- a/lib/README
+++ b/lib/README
@@ -10,7 +10,6 @@ cleanup.* author - Markus Armbruster, Colin Watson
debug.c author - Colin Watson
decompress.* author - Colin Watson
encodings.* author - Colin Watson
-hashtable.* author - Wilf., Colin Watson
linelength.* author - Martin Schulze, Jon Tombs, Colin Watson
lower.* author - Wilf., Colin Watson
pathsearch.* author - Colin Watson
diff --git a/lib/glcontainers.h b/lib/glcontainers.h
index 482a99d3..3e2917fa 100644
--- a/lib/glcontainers.h
+++ b/lib/glcontainers.h
@@ -44,4 +44,15 @@ void plain_free (const void *s);
gl_list_iterator_free (&list##_iter); \
} while (0)
+#define GL_MAP_FOREACH_START(map, key, value) \
+ do { \
+ gl_map_iterator_t map##_iter = gl_map_iterator (map); \
+ while (gl_map_iterator_next (&map##_iter, \
+ (const void **) &key, \
+ (const void **) &value))
+
+#define GL_MAP_FOREACH_END(map) \
+ gl_map_iterator_free (&map##_iter); \
+ } while (0)
+
#endif /* MAN_GLCONTAINERS_H */
diff --git a/lib/hashtable.c b/lib/hashtable.c
deleted file mode 100644
index 85fbb04d..00000000
--- a/lib/hashtable.c
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * hashtable.c: in core hash table routines.
- *
- * Copyright (C) 1994, 1995 Graeme W. Wilford. (Wilf.)
- * Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009 Colin Watson.
- *
- * This file is part of man-db.
- *
- * man-db 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 2 of the License, or
- * (at your option) any later version.
- *
- * man-db 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 man-db; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * All of these routines except hashtable_free() can be found in K&R II.
- *
- * Sat Aug 20 15:01:02 BST 1994 Wilf. (G.Wilford@ee.surrey.ac.uk)
- */
-
-/* which hash function do we want ? */
-/* #define PROLOGUE */
-#define KRII
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif /* HAVE_CONFIG_H */
-
-#include <string.h>
-#include <stdlib.h>
-
-#include "manconfig.h"
-#include "hashtable.h"
-
-#if defined(PROLOGUE)
-#define HASHSIZE 2048
-#elif defined(KRII)
-#define HASHSIZE 2001
-#else
-#error hash function not defined
-#endif
-
-/* Return hash value for string. */
-static unsigned int hash (const char *s, size_t len)
-{
- unsigned int hashval = 0;
- size_t i;
-
- for (i = 0; i < len && s[i]; ++i)
-#if defined(KRII)
- hashval = s[i] + 31 * hashval;
- return hashval % HASHSIZE;
-#elif defined(PROLOGUE)
- hashval = (hashval << 1) + s[i];
- return hashval & (HASHSIZE - 1);
-#endif
-}
-
-void null_hashtable_free (void *defn ATTRIBUTE_UNUSED)
-{
-}
-
-/* Create a hashtable. */
-struct hashtable *hashtable_create (hashtable_free_ptr free_defn)
-{
- struct hashtable *ht = XMALLOC (struct hashtable);
- ht->hashtab = XCALLOC (HASHSIZE, struct nlist *);
- ht->unique = 0;
- ht->identical = 0;
- ht->free_defn = free_defn;
- return ht;
-}
-
-/* Return pointer to hash entry structure containing s, or NULL if it
- * doesn't exist.
- */
-struct nlist *hashtable_lookup_structure (const struct hashtable *ht,
- const char *s, size_t len)
-{
- struct nlist *np;
-
- for (np = ht->hashtab[hash (s, len)]; np; np = np->next) {
- if (strncmp (s, np->name, len) == 0)
- return np;
- }
- return NULL;
-}
-
-/* Return pointer to definition of s, or NULL if it doesn't exist. */
-void *hashtable_lookup (const struct hashtable *ht, const char *s, size_t len)
-{
- struct nlist *np = hashtable_lookup_structure (ht, s, len);
- if (np)
- return np->defn;
- else
- return NULL;
-}
-
-/* Return structure containing definition (never NULL). */
-struct nlist *hashtable_install (struct hashtable *ht,
- const char *name, size_t len, void *defn)
-{
- struct nlist *np;
-
- np = hashtable_lookup_structure (ht, name, len);
- if (np) {
- if (np->defn)
- ht->free_defn (np->defn);
- } else {
- unsigned int hashval;
-
- np = XMALLOC (struct nlist);
- np->name = xstrndup (name, len);
- hashval = hash (name, len);
-
- /* record uniqueness if debugging */
- if (debug_level) {
- if (ht->hashtab[hashval])
- ht->identical++;
- else
- ht->unique++;
- }
-
- /* point to last entry with this hash */
- np->next = ht->hashtab[hashval];
-
- /* attach to hashtab array */
- ht->hashtab[hashval] = np;
- }
-
- np->defn = defn;
-
- return np;
-}
-
-/* Remove structure containing name from the hash tree. */
-void hashtable_remove (struct hashtable *ht, const char *name, size_t len)
-{
- struct nlist *np, *prev;
- unsigned int hashval = hash (name, len);
-
- for (np = ht->hashtab[hashval], prev = NULL; np;
- prev = np, np = np->next) {
- if (strncmp (name, np->name, len) == 0) {
- if (prev)
- prev->next = np->next;
- else
- ht->hashtab[hashval] = np->next;
- if (np->defn)
- ht->free_defn (np->defn);
- free (np->name);
- free (np);
- return;
- }
- }
-}
-
-struct hashtable_iter {
- struct nlist **bucket;
- struct nlist *np;
-};
-
-/* Iterate over hash. Do not modify hash while iterating. */
-struct nlist *hashtable_iterate (const struct hashtable *ht,
- struct hashtable_iter **iterp)
-{
- struct hashtable_iter *iter = *iterp;
-
- if (!iter)
- *iterp = iter = XZALLOC (struct hashtable_iter);
-
- if (iter->np && iter->np->next)
- return iter->np = iter->np->next;
-
- if (iter->bucket)
- ++iter->bucket;
- else
- iter->bucket = ht->hashtab;
-
- while (iter->bucket < ht->hashtab + HASHSIZE) {
- if (*iter->bucket)
- return iter->np = *iter->bucket;
- ++iter->bucket;
- }
-
- free (iter);
- *iterp = NULL;
- return NULL;
-}
-
-/* Free up the hash tree (garbage collection). Also call the free_defn()
- * hook to free up values if necessary.
- */
-void hashtable_free (struct hashtable *ht)
-{
- int i;
-
- if (!ht)
- return;
-
- debug ("hashtable_free: %d entries, %d (%d%%) unique\n",
- ht->unique + ht->identical,
- ht->unique,
- ht->unique ? (ht->unique * 100) / (ht->unique + ht->identical)
- : 0);
-
- for (i = 0; i < HASHSIZE; i++) {
- struct nlist *np;
-
- np = ht->hashtab[i];
- while (np) {
- struct nlist *next;
-
- if (np->defn)
- ht->free_defn (np->defn);
- free (np->name);
- next = np->next;
- free (np);
- np = next;
- }
- }
-
- free (ht->hashtab);
- free (ht);
-}
diff --git a/lib/hashtable.h b/lib/hashtable.h
deleted file mode 100644
index 3924518c..00000000
--- a/lib/hashtable.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * hashtable.h: contains struct nlist
- *
- * Copyright (C) 1994, 1995 Graeme W. Wilford. (Wilf.)
- * Copyright (C) 2002, 2003, 2004, 2005, 2007, 2009 Colin Watson.
- *
- * This file is part of man-db.
- *
- * man-db 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 2 of the License, or
- * (at your option) any later version.
- *
- * man-db 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 man-db; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Sat Aug 20 15:01:02 BST 1994 Wilf. (G.Wilford@ee.surrey.ac.uk)
- */
-
-#ifndef _HASHTABLE_H
-#define _HASHTABLE_H
-
-typedef void (*hashtable_free_ptr) (void *defn);
-
-struct hashtable {
- struct nlist **hashtab; /* the storage array */
- int unique; /* unique hash values */
- int identical; /* identical hash values */
- hashtable_free_ptr free_defn; /* function to free a hash entry */
-};
-
-struct nlist {
- struct nlist *next; /* next in the chain */
- char *name; /* the _name_ */
- void *defn; /* the _definition_ */
-};
-
-struct hashtable_iter;
-
-extern void null_hashtable_free (void *defn);
-
-extern struct hashtable *hashtable_create (hashtable_free_ptr free_defn);
-extern struct nlist *hashtable_lookup_structure (const struct hashtable *ht,
- const char *s, size_t len);
-extern void *hashtable_lookup (const struct hashtable *ht,
- const char *s, size_t len);
-extern struct nlist *hashtable_install (struct hashtable *ht,
- const char *name, size_t len,
- void *defn);
-extern struct nlist *hashtable_iterate (const struct hashtable *ht,
- struct hashtable_iter **iterp);
-extern void hashtable_remove (struct hashtable *ht, const char *s, size_t len);
-extern void hashtable_free (struct hashtable *ht);
-
-#endif /* _HASHTABLE_H */
diff --git a/lib/orderfiles.c b/lib/orderfiles.c
index a7c84ac5..e51a1dca 100644
--- a/lib/orderfiles.c
+++ b/lib/orderfiles.c
@@ -44,25 +44,24 @@
#include <string.h>
#include <unistd.h>
+#include "gl_hash_map.h"
#include "gl_rbtree_list.h"
#include "gl_xlist.h"
+#include "gl_xmap.h"
#include "manconfig.h"
#include "glcontainers.h"
-#include "hashtable.h"
-
-struct hashtable *physical_offsets = NULL;
#if defined(HAVE_LINUX_FIEMAP_H)
+gl_map_t physical_offsets = NULL;
+
int compare_physical_offsets (const void *a, const void *b)
{
const char *left = (const char *) a;
const char *right = (const char *) b;
- uint64_t *left_offset_p = hashtable_lookup (physical_offsets,
- left, strlen (left));
- uint64_t *right_offset_p = hashtable_lookup (physical_offsets,
- right, strlen (right));
+ const uint64_t *left_offset_p = gl_map_get (physical_offsets, left);
+ const uint64_t *right_offset_p = gl_map_get (physical_offsets, right);
uint64_t left_offset = left_offset_p ? *left_offset_p : UINT64_MAX;
uint64_t right_offset = right_offset_p ? *right_offset_p : UINT64_MAX;
@@ -101,7 +100,8 @@ void order_files (const char *dir, gl_list_t *basenamesp)
* a small number of contiguous blocks, which seems a reasonable
* assumption for manual pages.
*/
- physical_offsets = hashtable_create (&free);
+ physical_offsets = gl_map_create_empty (GL_HASH_MAP, string_equals,
+ string_hash, NULL, plain_free);
sorted_basenames = gl_list_create_empty (GL_RBTREE_LIST,
string_equals, string_hash,
plain_free, false);
@@ -125,15 +125,18 @@ void order_files (const char *dir, gl_list_t *basenamesp)
if (ioctl (fd, FS_IOC_FIEMAP, (unsigned long) &fm) == 0) {
uint64_t *offset = XMALLOC (uint64_t);
*offset = fm.fiemap.fm_extents[0].fe_physical;
- hashtable_install (physical_offsets, name,
- strlen (name), offset);
+ /* Borrow the key from basenames; since
+ * physical_offsets has a shorter lifetime, we don't
+ * need to duplicate it.
+ */
+ gl_map_put (physical_offsets, name, offset);
}
close (fd);
gl_sortedlist_add (sorted_basenames, compare_physical_offsets,
xstrdup (name));
} GL_LIST_FOREACH_END (basenames);
- hashtable_free (physical_offsets);
+ gl_map_free (physical_offsets);
physical_offsets = NULL;
close (dir_fd);
gl_list_free (basenames);
diff --git a/libdb/db_btree.c b/libdb/db_btree.c
index f1de4078..c72c7b4d 100644
--- a/libdb/db_btree.c
+++ b/libdb/db_btree.c
@@ -39,18 +39,20 @@
#include <sys/types.h> /* for open() */
#include <sys/stat.h>
+#include "gl_hash_set.h"
+#include "gl_xset.h"
#include "stat-time.h"
#include "timespec.h"
#include "manconfig.h"
#include "error.h"
-#include "hashtable.h"
+#include "glcontainers.h"
#include "mydbm.h"
#include "db_storage.h"
-struct hashtable *loop_check_hash;
+gl_set_t loop_check;
/* the Berkeley database libraries do nothing to arbitrate between concurrent
database accesses, so we do a simple flock(). If the db is opened in
@@ -178,26 +180,28 @@ int btree_exists (DB *db, datum key)
static datum btree_findkey (DB *db, u_int flags)
{
datum key, data;
+ char *loop_check_key;
memset (&key, 0, sizeof key);
memset (&data, 0, sizeof data);
if (flags == R_FIRST) {
- if (loop_check_hash) {
- hashtable_free (loop_check_hash);
- loop_check_hash = NULL;
+ if (loop_check) {
+ gl_set_free (loop_check);
+ loop_check = NULL;
}
}
- if (!loop_check_hash)
- loop_check_hash = hashtable_create (&free);
+ if (!loop_check)
+ loop_check = gl_set_create_empty (GL_HASH_SET, string_equals,
+ string_hash, plain_free);
if (((db->seq) (db, (DBT *) &key, (DBT *) &data, flags))) {
memset (&key, 0, sizeof key);
return key;
}
- if (hashtable_lookup (loop_check_hash,
- MYDBM_DPTR (key), MYDBM_DSIZE (key))) {
+ loop_check_key = xstrndup (MYDBM_DPTR (key), MYDBM_DSIZE (key));
+ if (gl_set_search (loop_check, loop_check_key)) {
/* We've seen this key already, which is broken. Return NULL
* so the caller doesn't go round in circles.
*/
@@ -205,11 +209,11 @@ static datum btree_findkey (DB *db, u_int flags)
"Attempting to recover ...\n",
(int) MYDBM_DSIZE (key), MYDBM_DPTR (key));
memset (&key, 0, sizeof key);
+ free (loop_check_key);
return key;
}
- hashtable_install (loop_check_hash,
- MYDBM_DPTR (key), MYDBM_DSIZE (key), NULL);
+ gl_set_add (loop_check, loop_check_key);
return copy_datum (key);
}
diff --git a/libdb/db_gdbm.c b/libdb/db_gdbm.c
index f3aaa94e..650f16f4 100644
--- a/libdb/db_gdbm.c
+++ b/libdb/db_gdbm.c
@@ -34,22 +34,22 @@
#include <sys/stat.h>
#include <unistd.h>
+#include "gl_hash_map.h"
+#include "gl_rbtree_list.h"
+#include "gl_xlist.h"
+#include "gl_xmap.h"
+#include "hash-pjw-bare.h"
#include "stat-time.h"
#include "timespec.h"
#include "manconfig.h"
-#include "hashtable.h"
#include "cleanup.h"
+#include "glcontainers.h"
#include "mydbm.h"
-static struct hashtable *parent_sortkey_hash;
-
-struct sortkey {
- datum key;
- struct sortkey *next;
-};
+static gl_map_t parent_keys;
/* setjmp/longjmp handling to defend against _gdbm_fatal exiting under our
* feet. Not thread-safe, but there is no plan for man-db to ever use
@@ -103,129 +103,112 @@ man_gdbm_wrapper man_gdbm_open_wrapper (const char *name, int flags)
return wrap;
}
-static void parent_sortkey_hashtable_free (void *defn)
-{
- /* Automatically free child hashtables on removal. */
- hashtable_free ((struct hashtable *) defn);
-}
-
-static void sortkey_hashtable_free (void *defn)
+static int datum_compare (const void *a, const void *b)
{
- struct sortkey *key = (struct sortkey *) defn;
- MYDBM_FREE_DPTR (key->key);
- free (key);
-}
-
-static int sortkey_compare (const void *a, const void *b)
-{
- const struct sortkey **left = (const struct sortkey **) a;
- const struct sortkey **right = (const struct sortkey **) b;
+ const datum *left = (const datum *) a;
+ const datum *right = (const datum *) b;
int cmp;
size_t minsize;
/* Sentinel NULL elements sort to the end. */
- if (!MYDBM_DPTR ((*left)->key))
+ if (!MYDBM_DPTR (*left))
return 1;
- else if (!MYDBM_DPTR ((*right)->key))
+ else if (!MYDBM_DPTR (*right))
return -1;
- if (MYDBM_DSIZE ((*left)->key) < MYDBM_DSIZE ((*right)->key))
- minsize = MYDBM_DSIZE ((*left)->key);
+ if (MYDBM_DSIZE (*left) < MYDBM_DSIZE (*right))
+ minsize = MYDBM_DSIZE (*left);
else
- minsize = MYDBM_DSIZE ((*right)->key);
- cmp = strncmp (MYDBM_DPTR ((*left)->key), MYDBM_DPTR ((*right)->key),
- minsize);
+ minsize = MYDBM_DSIZE (*right);
+ cmp = strncmp (MYDBM_DPTR (*left), MYDBM_DPTR (*right), minsize);
if (cmp)
return cmp;
- else if (MYDBM_DSIZE ((*left)->key) < MYDBM_DSIZE ((*right)->key))
+ else if (MYDBM_DSIZE (*left) < MYDBM_DSIZE (*right))
return 1;
- else if (MYDBM_DSIZE ((*left)->key) > MYDBM_DSIZE ((*right)->key))
+ else if (MYDBM_DSIZE (*left) > MYDBM_DSIZE (*right))
return -1;
else
return 0;
}
+static bool datum_equals (const void *a, const void *b)
+{
+ return datum_compare (a, b) == 0;
+}
+
+static size_t datum_hash (const void *value)
+{
+ const datum *d = value;
+ return hash_pjw_bare (MYDBM_DPTR (*d), MYDBM_DSIZE (*d));
+}
+
+static void datum_free (const void *value)
+{
+ MYDBM_FREE_DPTR (*(datum *) value);
+}
+
static datum empty_datum = { NULL, 0 };
-/* We keep a hashtable of filenames to sorted lists of keys. Each list is
- * stored both with links from each element to the next and in a hashtable,
- * so that both sequential access and random access are quick. This is
- * necessary for a reasonable ordered implementation of nextkey.
+/* We keep a map of filenames to sorted lists of keys. Each list is stored
+ * using a hash-based implementation that allows lookup by name and
+ * traversal to the next item in O(log n) time, which is necessary for a
+ * reasonable ordered implementation of nextkey.
*/
datum man_gdbm_firstkey (man_gdbm_wrapper wrap)
{
- struct hashtable *sortkey_hash;
- struct sortkey **keys, *firstkey;
- int numkeys = 0, maxkeys = 256;
- int i;
-
- /* Build the raw list of keys and sort it. */
- keys = xnmalloc (maxkeys, sizeof *keys);
- keys[0] = xmalloc (sizeof **keys);
- keys[0]->key = gdbm_firstkey (wrap->file);
- while (MYDBM_DPTR (keys[numkeys]->key)) {
- if (++numkeys >= maxkeys) {
- maxkeys *= 2;
- keys = xnrealloc (keys, maxkeys, sizeof *keys);
- }
- keys[numkeys] = xmalloc (sizeof **keys);
- keys[numkeys]->key =
- gdbm_nextkey (wrap->file, keys[numkeys - 1]->key);
+ gl_list_t keys;
+ datum *key;
+
+ /* Build the raw sorted list of keys. */
+ keys = gl_list_create_empty (GL_RBTREE_LIST, datum_equals, datum_hash,
+ datum_free, false);
+ key = XMALLOC (datum);
+ *key = gdbm_firstkey (wrap->file);
+ while (MYDBM_DPTR (*key)) {
+ datum *next;
+
+ gl_sortedlist_add (keys, datum_compare, key);
+ next = XMALLOC (datum);
+ *next = gdbm_nextkey (wrap->file, *key);
+ key = next;
}
- free (keys[numkeys]);
- keys[numkeys] = NULL; /* simplifies the empty case */
- qsort (keys, numkeys, sizeof *keys, &sortkey_compare);
-
- /* Link the elements together and insert them into a hash. */
- sortkey_hash = hashtable_create (&sortkey_hashtable_free);
- for (i = 0; i < numkeys; ++i) {
- if (i < numkeys - 1)
- keys[i]->next = keys[i + 1];
- else
- keys[i]->next = NULL;
- hashtable_install (sortkey_hash,
- MYDBM_DPTR (keys[i]->key),
- MYDBM_DSIZE (keys[i]->key),
- keys[i]);
- }
- firstkey = keys[0];
- free (keys); /* element memory now owned by hashtable */
-
- if (!parent_sortkey_hash) {
- parent_sortkey_hash = hashtable_create
- (&parent_sortkey_hashtable_free);
- push_cleanup ((cleanup_fun) hashtable_free,
- parent_sortkey_hash, 0);
+
+ if (!parent_keys) {
+ parent_keys = gl_map_create_empty (GL_HASH_MAP, string_equals,
+ string_hash, plain_free,
+ (gl_listelement_dispose_fn)
+ gl_list_free);
+ push_cleanup ((cleanup_fun) gl_map_free, parent_keys, 0);
}
/* Remember this structure for use by nextkey. */
- hashtable_install (parent_sortkey_hash,
- wrap->name, strlen (wrap->name), sortkey_hash);
+ gl_map_put (parent_keys, xstrdup (wrap->name), keys);
- if (firstkey)
- return copy_datum (firstkey->key);
+ if (gl_list_size (keys))
+ return copy_datum (*(datum *) gl_list_get_at (keys, 0));
else
- return empty_datum; /* dptr is NULL, so no copy needed */
+ return empty_datum;
}
datum man_gdbm_nextkey (man_gdbm_wrapper wrap, datum key)
{
- struct hashtable *sortkey_hash;
- struct sortkey *sortkey;
+ gl_list_t keys;
+ gl_list_node_t node, next_node;
- if (!parent_sortkey_hash)
+ if (!parent_keys)
return empty_datum;
- sortkey_hash = hashtable_lookup (parent_sortkey_hash,
- wrap->name, strlen (wrap->name));
- if (!sortkey_hash)
+ keys = (gl_list_t) gl_map_get (parent_keys, wrap->name);
+ if (!keys)
return empty_datum;
- sortkey = hashtable_lookup (sortkey_hash,
- MYDBM_DPTR (key), MYDBM_DSIZE (key));
- if (!sortkey || !sortkey->next)
+ node = gl_sortedlist_search (keys, datum_compare, &key);
+ if (!node)
+ return empty_datum;
+ next_node = gl_list_next_node (keys, node);
+ if (!next_node)
return empty_datum;
- return copy_datum (sortkey->next->key);
+ return copy_datum (*(datum *) gl_list_node_value (keys, next_node));
}
struct timespec man_gdbm_get_time (man_gdbm_wrapper wrap)
@@ -255,14 +238,8 @@ void man_gdbm_close (man_gdbm_wrapper wrap)
if (!wrap)
return;
- if (parent_sortkey_hash) {
- struct hashtable *sortkey_hash =
- hashtable_lookup (parent_sortkey_hash,
- wrap->name, strlen (wrap->name));
- if (sortkey_hash)
- hashtable_remove (parent_sortkey_hash,
- wrap->name, strlen (wrap->name));
- }
+ if (parent_keys)
+ gl_map_remove (parent_keys, wrap->name);
free (wrap->name);
gdbm_close (wrap->file);
diff --git a/src/check_mandirs.c b/src/check_mandirs.c
index 58dc64cc..7c0708b1 100644
--- a/src/check_mandirs.c
+++ b/src/check_mandirs.c
@@ -45,7 +45,9 @@
#include "dirname.h"
#include "gl_array_list.h"
+#include "gl_hash_map.h"
#include "gl_xlist.h"
+#include "gl_xmap.h"
#include "stat-time.h"
#include "timespec.h"
#include "xvasprintf.h"
@@ -57,7 +59,6 @@
#include "error.h"
#include "glcontainers.h"
-#include "hashtable.h"
#include "orderfiles.h"
#include "security.h"
@@ -75,20 +76,20 @@ int opt_test; /* don't update db */
int pages;
int force_rescan = 0;
-static struct hashtable *whatis_hash = NULL;
+gl_map_t whatis_map = NULL;
-struct whatis_hashent {
+struct whatis {
char *whatis;
gl_list_t trace;
};
-static void whatis_hashtable_free (void *defn)
+static void whatis_free (const void *value)
{
- struct whatis_hashent *hashent = defn;
+ struct whatis *whatis = (struct whatis *) value;
- free (hashent->whatis);
- gl_list_free (hashent->trace);
- free (hashent);
+ free (whatis->whatis);
+ gl_list_free (whatis->trace);
+ free (whatis);
}
static void gripe_multi_extensions (const char *path, const char *sec,
@@ -131,7 +132,7 @@ void test_manfile (MYDBM_FILE dbf, const char *file, const char *path)
struct stat buf;
size_t len;
gl_list_t ult_trace = NULL;
- struct whatis_hashent *whatis;
+ const struct whatis *whatis;
memset (&lg, 0, sizeof (struct lexgrog));
memset (&info, 0, sizeof (struct mandata));
@@ -217,10 +218,12 @@ void test_manfile (MYDBM_FILE dbf, const char *file, const char *path)
return;
}
- if (!whatis_hash)
- whatis_hash = hashtable_create (&whatis_hashtable_free);
+ if (!whatis_map)
+ whatis_map = gl_map_create_empty (GL_HASH_MAP, string_equals,
+ string_hash, plain_free,
+ whatis_free);
- whatis = hashtable_lookup (whatis_hash, ult, strlen (ult));
+ whatis = gl_map_get (whatis_map, ult);
if (!whatis) {
if (!STRNEQ (ult, file, len))
debug ("\ntest_manfile(): link not in cache:\n"
@@ -266,6 +269,7 @@ void test_manfile (MYDBM_FILE dbf, const char *file, const char *path)
else {
/* Cache miss; go and get the whatis info in its raw state. */
char *file_base = base_name (file);
+ struct whatis *new_whatis;
lg.type = MANPAGE;
drop_effective_privs ();
@@ -273,11 +277,12 @@ void test_manfile (MYDBM_FILE dbf, const char *file, const char *path)
free (file_base);
regain_effective_privs ();
- whatis = XMALLOC (struct whatis_hashent);
- whatis->whatis = lg.whatis ? xstrdup (lg.whatis) : NULL;
+ new_whatis = XMALLOC (struct whatis);
+ new_whatis->whatis = lg.whatis ? xstrdup (lg.whatis) : NULL;
/* We filled out ult_trace above. */
- whatis->trace = ult_trace;
- hashtable_install (whatis_hash, ult, strlen (ult), whatis);
+ new_whatis->trace = ult_trace;
+ gl_map_put (whatis_map, xstrdup (ult), new_whatis);
+ whatis = new_whatis;
}
debug ("\"%s\"\n", lg.whatis);
diff --git a/src/globbing.c b/src/globbing.c
index 0c9a9ced..93df7ca1 100644
--- a/src/globbing.c
+++ b/src/globbing.c
@@ -37,7 +37,9 @@
#include "fnmatch.h"
#include "gl_array_list.h"
+#include "gl_hash_map.h"
#include "gl_xlist.h"
+#include "gl_xmap.h"
#include "regex.h"
#include "xvasprintf.h"
@@ -45,7 +47,6 @@
#include "error.h"
#include "glcontainers.h"
-#include "hashtable.h"
#include "cleanup.h"
#include "xregcomp.h"
@@ -113,23 +114,23 @@ static int parse_layout (const char *layout)
}
}
-struct dirent_hashent {
+struct dirent_names {
char **names;
size_t names_len, names_max;
};
-static void dirent_hashtable_free (void *defn)
+static void dirent_names_free (const void *value)
{
- struct dirent_hashent *hashent = defn;
+ struct dirent_names *cache = (struct dirent_names *) value;
size_t i;
- for (i = 0; i < hashent->names_len; ++i)
- free (hashent->names[i]);
- free (hashent->names);
- free (hashent);
+ for (i = 0; i < cache->names_len; ++i)
+ free (cache->names[i]);
+ free (cache->names);
+ free (cache);
}
-static struct hashtable *dirent_hash = NULL;
+static gl_map_t dirent_map = NULL;
static int cache_compare (const void *a, const void *b)
{
@@ -138,17 +139,19 @@ static int cache_compare (const void *a, const void *b)
return strcasecmp (left, right);
}
-static struct dirent_hashent *update_directory_cache (const char *path)
+static struct dirent_names *update_directory_cache (const char *path)
{
- struct dirent_hashent *cache;
+ struct dirent_names *cache;
DIR *dir;
struct dirent *entry;
- if (!dirent_hash) {
- dirent_hash = hashtable_create (&dirent_hashtable_free);
- push_cleanup ((cleanup_fun) hashtable_free, dirent_hash, 0);
+ if (!dirent_map) {
+ dirent_map = gl_map_create_empty (GL_HASH_MAP, string_equals,
+ string_hash, plain_free,
+ dirent_names_free);
+ push_cleanup ((cleanup_fun) gl_map_free, dirent_map, 0);
}
- cache = hashtable_lookup (dirent_hash, path, strlen (path));
+ cache = (struct dirent_names *) gl_map_get (dirent_map, path);
/* Check whether we've got this one already. */
if (cache) {
@@ -164,7 +167,7 @@ static struct dirent_hashent *update_directory_cache (const char *path)
return NULL;
}
- cache = XMALLOC (struct dirent_hashent);
+ cache = XMALLOC (struct dirent_names);
cache->names_len = 0;
cache->names_max = 1024;
cache->names = XNMALLOC (cache->names_max, char *);
@@ -183,7 +186,7 @@ static struct dirent_hashent *update_directory_cache (const char *path)
qsort (cache->names, cache->names_len, sizeof *cache->names,
&cache_compare);
- hashtable_install (dirent_hash, path, strlen (path), cache);
+ gl_map_put (dirent_map, xstrdup (path), cache);
closedir (dir);
return cache;
@@ -204,7 +207,7 @@ static int pattern_compare (const void *a, const void *b)
static void match_in_directory (const char *path, const char *pattern,
int opts, gl_list_t matched)
{
- struct dirent_hashent *cache;
+ struct dirent_names *cache;
int flags;
regex_t preg;
struct pattern_bsearch pattern_start = { NULL, -1 };
diff --git a/src/man.c b/src/man.c
index 426239ec..66205f53 100644
--- a/src/man.c
+++ b/src/man.c
@@ -60,8 +60,10 @@
#include "argp.h"
#include "dirname.h"
#include "gl_array_list.h"
+#include "gl_hash_map.h"
#include "gl_list.h"
#include "gl_xlist.h"
+#include "gl_xmap.h"
#include "minmax.h"
#include "progname.h"
#include "regex.h"
@@ -81,7 +83,6 @@
#include "error.h"
#include "cleanup.h"
#include "glcontainers.h"
-#include "hashtable.h"
#include "pipeline.h"
#include "pathsearch.h"
#include "linelength.h"
@@ -203,7 +204,7 @@ static char *less;
static const char *std_sections[] = STD_SECTIONS;
static char *manp;
static const char *external;
-static struct hashtable *db_hash = NULL;
+static gl_map_t db_map = NULL;
static int troff;
static const char *roff_device = NULL;
@@ -3314,11 +3315,6 @@ static int display_database_check (struct candidate *candp)
return exists;
}
-static void db_hashtable_free (void *defn)
-{
- free_mandata_struct (defn);
-}
-
#ifdef MAN_DB_UPDATES
static int maybe_update_file (const char *manpath, const char *name,
struct mandata *info)
@@ -3399,11 +3395,14 @@ static int try_db (const char *manpath, const char *sec, const char *name,
} else
database = mkdbname (manpath);
- if (!db_hash)
- db_hash = hashtable_create (&db_hashtable_free);
+ if (!db_map)
+ db_map = gl_map_create_empty (GL_HASH_MAP, string_equals,
+ string_hash, plain_free,
+ (gl_mapvalue_dispose_fn)
+ free_mandata_struct);
/* Have we looked here already? */
- data = hashtable_lookup (db_hash, manpath, strlen (manpath));
+ data = (struct mandata *) gl_map_get (db_map, manpath);
if (!data) {
MYDBM_FILE dbf;
@@ -3425,8 +3424,7 @@ static int try_db (const char *manpath, const char *sec, const char *name,
else
data = dblookup_all (dbf, name, section,
match_case);
- hashtable_install (db_hash, manpath, strlen (manpath),
- data);
+ gl_map_put (db_map, xstrdup (manpath), data);
MYDBM_CLOSE (dbf);
dbf = NULL;
#ifdef MAN_DB_CREATES
@@ -3437,9 +3435,7 @@ static int try_db (const char *manpath, const char *sec, const char *name,
data = infoalloc ();
data->next = NULL;
data->addr = NULL;
- hashtable_install (db_hash,
- manpath, strlen (manpath),
- data);
+ gl_map_put (db_map, xstrdup (manpath), data);
return TRY_DATABASE_OPEN_FAILED;
}
return TRY_DATABASE_CREATED;
@@ -3449,8 +3445,7 @@ static int try_db (const char *manpath, const char *sec, const char *name,
data = infoalloc ();
data->next = (struct mandata *) NULL;
data->addr = NULL;
- hashtable_install (db_hash, manpath, strlen (manpath),
- data);
+ gl_map_put (db_map, xstrdup (manpath), data);
return TRY_DATABASE_OPEN_FAILED;
}
}
@@ -3475,7 +3470,7 @@ static int try_db (const char *manpath, const char *sec, const char *name,
found_stale = 1;
if (found_stale) {
- hashtable_remove (db_hash, manpath, strlen (manpath));
+ gl_map_remove (db_map, manpath);
return TRY_DATABASE_UPDATED;
}
#endif /* MAN_DB_UPDATES */
@@ -4274,8 +4269,10 @@ int main (int argc, char *argv[])
}
/* clean out the cache of database lookups for each man page */
- hashtable_free (db_hash);
- db_hash = NULL;
+ if (db_map) {
+ gl_map_free (db_map);
+ db_map = NULL;
+ }
if (section && maybe_section) {
if (status != OK && !catman) {
@@ -4299,8 +4296,10 @@ int main (int argc, char *argv[])
}
if (!found_subpage)
status = man (tmp, &found);
- hashtable_free (db_hash);
- db_hash = NULL;
+ if (db_map) {
+ gl_map_free (db_map);
+ db_map = NULL;
+ }
/* ... but don't gripe about it if it doesn't
* work!
*/
@@ -4345,8 +4344,10 @@ int main (int argc, char *argv[])
chkr_garbage_detector ();
}
- hashtable_free (db_hash);
- db_hash = NULL;
+ if (db_map) {
+ gl_map_free (db_map);
+ db_map = NULL;
+ }
drop_effective_privs ();
diff --git a/src/mandb.c b/src/mandb.c
index f4fc0652..a256ebae 100644
--- a/src/mandb.c
+++ b/src/mandb.c
@@ -49,7 +49,9 @@
#include "argp.h"
#include "dirname.h"
+#include "gl_hash_map.h"
#include "gl_list.h"
+#include "gl_xmap.h"
#include "progname.h"
#include "stat-time.h"
#include "timespec.h"
@@ -66,7 +68,6 @@
#include "error.h"
#include "cleanup.h"
#include "glcontainers.h"
-#include "hashtable.h"
#include "pipeline.h"
#include "sandbox.h"
#include "security.h"
@@ -556,7 +557,7 @@ static int mandb (struct dbpaths *dbpaths,
}
static int process_manpath (const char *manpath, bool global_manpath,
- struct hashtable *tried_catdirs)
+ gl_map_t tried_catdirs)
{
char *catpath;
struct tried_catdirs_entry *tried;
@@ -576,7 +577,7 @@ static int process_manpath (const char *manpath, bool global_manpath,
tried = XMALLOC (struct tried_catdirs_entry);
tried->manpath = xstrdup (manpath);
tried->seen = 0;
- hashtable_install (tried_catdirs, catpath, strlen (catpath), tried);
+ gl_map_put (tried_catdirs, xstrdup (catpath), tried);
if (stat (manpath, &st) < 0 || !S_ISDIR (st.st_mode))
goto out;
@@ -652,21 +653,21 @@ static int is_lang_dir (const char *base)
(!base[2] || base[2] < 'a' || base[2] > 'z');
}
-static void tried_catdirs_free (void *defn)
+static void tried_catdirs_free (const void *value)
{
- struct tried_catdirs_entry *tried = defn;
+ struct tried_catdirs_entry *tried =
+ (struct tried_catdirs_entry *) value;
free (tried->manpath);
free (tried);
}
-static void purge_catdir (const struct hashtable *tried_catdirs,
- const char *path)
+static void purge_catdir (gl_map_t tried_catdirs, const char *path)
{
struct stat st;
if (stat (path, &st) == 0 && S_ISDIR (st.st_mode) &&
- !hashtable_lookup (tried_catdirs, path, strlen (path))) {
+ !gl_map_get (tried_catdirs, path)) {
if (!quiet)
printf (_("Removing obsolete cat directory %s...\n"),
path);
@@ -718,14 +719,12 @@ static void purge_catsubdirs (const char *manpath, const char *catpath)
* the usual NLS pattern (two lower-case letters followed by nothing or a
* non-letter).
*/
-static void purge_catdirs (const struct hashtable *tried_catdirs)
+static void purge_catdirs (gl_map_t tried_catdirs)
{
- struct hashtable_iter *iter = NULL;
- const struct nlist *elt;
+ const char *path;
+ struct tried_catdirs_entry *tried;
- while ((elt = hashtable_iterate (tried_catdirs, &iter)) != NULL) {
- const char *path = elt->name;
- struct tried_catdirs_entry *tried = elt->defn;
+ GL_MAP_FOREACH_START (tried_catdirs, path, tried) {
char *base;
DIR *dir;
struct dirent *subdirent;
@@ -745,6 +744,7 @@ static void purge_catdirs (const struct hashtable *tried_catdirs)
continue;
while ((subdirent = readdir (dir)) != NULL) {
char *subdirpath;
+ const struct tried_catdirs_entry *subtried;
if (STREQ (subdirent->d_name, ".") ||
STREQ (subdirent->d_name, ".."))
@@ -757,22 +757,22 @@ static void purge_catdirs (const struct hashtable *tried_catdirs)
subdirpath = xasprintf ("%s/%s", path,
subdirent->d_name);
- tried = hashtable_lookup (tried_catdirs, subdirpath,
- strlen (subdirpath));
- if (tried && tried->seen) {
+ subtried = gl_map_get (tried_catdirs, subdirpath);
+ if (subtried && subtried->seen) {
debug ("Seen mandir for %s; not deleting\n",
subdirpath);
/* However, we may still need to purge cat*
* subdirectories.
*/
- purge_catsubdirs (tried->manpath, subdirpath);
+ purge_catsubdirs (subtried->manpath,
+ subdirpath);
} else
purge_catdir (tried_catdirs, subdirpath);
free (subdirpath);
}
closedir (dir);
- }
+ } GL_MAP_FOREACH_END (tried_catdirs);
}
int main (int argc, char *argv[])
@@ -780,7 +780,7 @@ int main (int argc, char *argv[])
char *sys_manp;
int amount = 0;
char *mp;
- struct hashtable *tried_catdirs;
+ gl_map_t tried_catdirs;
#ifdef SIGPIPE
struct sigaction sa;
#endif /* SIGPIPE */
@@ -858,7 +858,9 @@ int main (int argc, char *argv[])
/* finished manpath processing, regain privs */
regain_effective_privs ();
- tried_catdirs = hashtable_create (tried_catdirs_free);
+ tried_catdirs = gl_map_create_empty (GL_HASH_MAP, string_equals,
+ string_hash, plain_free,
+ tried_catdirs_free);
GL_LIST_FOREACH_START (manpathlist, mp) {
bool global_manpath = is_global_mandir (mp);
@@ -914,7 +916,7 @@ next_manpath:
} GL_LIST_FOREACH_END (manpathlist);
purge_catdirs (tried_catdirs);
- hashtable_free (tried_catdirs);
+ gl_map_free (tried_catdirs);
if (!quiet) {
printf (ngettext ("%d man subdirectory contained newer "
diff --git a/src/whatis.c b/src/whatis.c
index 7c3bfb61..5d45ae46 100644
--- a/src/whatis.c
+++ b/src/whatis.c
@@ -57,7 +57,9 @@
#include "argp.h"
#include "dirname.h"
+#include "gl_hash_set.h"
#include "gl_list.h"
+#include "gl_xset.h"
#include "fnmatch.h"
#include "progname.h"
#include "xvasprintf.h"
@@ -70,7 +72,6 @@
#include "pipeline.h"
#include "pathsearch.h"
#include "linelength.h"
-#include "hashtable.h"
#include "lower.h"
#include "wordfnmatch.h"
#include "xregcomp.h"
@@ -114,7 +115,7 @@ static const char *alt_systems = "";
static const char *locale = NULL;
static char *multiple_locale = NULL, *internal_locale;
-static struct hashtable *display_seen = NULL;
+static gl_set_t display_seen = NULL;
const char *argp_program_version; /* initialised in main */
const char *argp_program_bug_address = PACKAGE_BUGREPORT;
@@ -454,9 +455,9 @@ static void display (MYDBM_FILE dbf, struct mandata *info, const char *page)
page_name = page;
key = xasprintf ("%s (%s)", page_name, newinfo->ext);
- if (hashtable_lookup_structure (display_seen, key, strlen (key)))
+ if (gl_set_search (display_seen, key))
goto out;
- hashtable_install (display_seen, key, strlen (key), NULL);
+ gl_set_add (display_seen, xstrdup (key));
line_len = get_line_length ();
@@ -968,7 +969,8 @@ int main (int argc, char *argv[])
manpathlist = create_pathlist (manp);
- display_seen = hashtable_create (&null_hashtable_free);
+ display_seen = gl_set_create_empty (GL_HASH_SET, string_equals,
+ string_hash, plain_free);
#ifdef HAVE_ICONV
locale_charset = xasprintf ("%s//IGNORE", get_locale_charset ());
@@ -998,7 +1000,7 @@ int main (int argc, char *argv[])
if (conv_to_locale != (iconv_t) -1)
iconv_close (conv_to_locale);
#endif /* HAVE_ICONV */
- hashtable_free (display_seen);
+ gl_set_free (display_seen);
free_pathlist (manpathlist);
free (manp);
free (internal_locale);