From ba8f85b49c38af7bc2a9acdef5dcde2de008d25e Mon Sep 17 00:00:00 2001
From: peter <peter@FreeBSD.org>
Date: Sat, 12 Jul 2008 05:00:28 +0000
Subject: Flatten bind9 vendor work area

---
 lib/isccc/symtab.c | 280 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 280 insertions(+)
 create mode 100644 lib/isccc/symtab.c

(limited to 'lib/isccc/symtab.c')

diff --git a/lib/isccc/symtab.c b/lib/isccc/symtab.c
new file mode 100644
index 0000000..7ec6d55
--- /dev/null
+++ b/lib/isccc/symtab.c
@@ -0,0 +1,280 @@
+/*
+ * Portions Copyright (C) 2004, 2005, 2007  Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2001  Internet Software Consortium.
+ * Portions Copyright (C) 2001  Nominum, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NOMINUM DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: symtab.c,v 1.5.18.4 2007/09/13 23:46:26 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <stdlib.h>
+
+#include <isc/assertions.h>
+#include <isc/magic.h>
+#include <isc/string.h>
+
+#include <isccc/result.h>
+#include <isccc/symtab.h>
+#include <isccc/util.h>
+
+typedef struct elt {
+	char *				key;
+	unsigned int			type;
+	isccc_symvalue_t			value;
+	ISC_LINK(struct elt)		link;
+} elt_t;
+
+typedef ISC_LIST(elt_t)			eltlist_t;
+
+#define SYMTAB_MAGIC			ISC_MAGIC('S', 'y', 'm', 'T')
+#define VALID_SYMTAB(st)		ISC_MAGIC_VALID(st, SYMTAB_MAGIC)
+
+struct isccc_symtab {
+	unsigned int			magic;
+	unsigned int			size;
+	eltlist_t *			table;
+	isccc_symtabundefaction_t		undefine_action;
+	void *				undefine_arg;
+	isc_boolean_t			case_sensitive;
+};
+
+isc_result_t
+isccc_symtab_create(unsigned int size,
+		  isccc_symtabundefaction_t undefine_action,
+		  void *undefine_arg,
+		  isc_boolean_t case_sensitive,
+		  isccc_symtab_t **symtabp)
+{
+	isccc_symtab_t *symtab;
+	unsigned int i;
+
+	REQUIRE(symtabp != NULL && *symtabp == NULL);
+	REQUIRE(size > 0);	/* Should be prime. */
+
+	symtab = malloc(sizeof(*symtab));
+	if (symtab == NULL)
+		return (ISC_R_NOMEMORY);
+	symtab->table = malloc(size * sizeof(eltlist_t));
+	if (symtab->table == NULL) {
+		free(symtab);
+		return (ISC_R_NOMEMORY);
+	}
+	for (i = 0; i < size; i++)
+		ISC_LIST_INIT(symtab->table[i]);
+	symtab->size = size;
+	symtab->undefine_action = undefine_action;
+	symtab->undefine_arg = undefine_arg;
+	symtab->case_sensitive = case_sensitive;
+	symtab->magic = SYMTAB_MAGIC;
+
+	*symtabp = symtab;
+
+	return (ISC_R_SUCCESS);
+}
+
+static inline void
+free_elt(isccc_symtab_t *symtab, unsigned int bucket, elt_t *elt) {
+	ISC_LIST_UNLINK(symtab->table[bucket], elt, link);
+	if (symtab->undefine_action != NULL)
+		(symtab->undefine_action)(elt->key, elt->type, elt->value,
+					  symtab->undefine_arg);
+	free(elt);
+}
+
+void
+isccc_symtab_destroy(isccc_symtab_t **symtabp) {
+	isccc_symtab_t *symtab;
+	unsigned int i;
+	elt_t *elt, *nelt;
+
+	REQUIRE(symtabp != NULL);
+	symtab = *symtabp;
+	REQUIRE(VALID_SYMTAB(symtab));
+
+	for (i = 0; i < symtab->size; i++) {
+		for (elt = ISC_LIST_HEAD(symtab->table[i]);
+		     elt != NULL;
+		     elt = nelt) {
+			nelt = ISC_LIST_NEXT(elt, link);
+			free_elt(symtab, i, elt);
+		}
+	}
+	free(symtab->table);
+	symtab->magic = 0;
+	free(symtab);
+
+	*symtabp = NULL;
+}
+
+static inline unsigned int
+hash(const char *key, isc_boolean_t case_sensitive) {
+	const char *s;
+	unsigned int h = 0;
+	unsigned int g;
+	int c;
+
+	/*
+	 * P. J. Weinberger's hash function, adapted from p. 436 of
+	 * _Compilers: Principles, Techniques, and Tools_, Aho, Sethi
+	 * and Ullman, Addison-Wesley, 1986, ISBN 0-201-10088-6.
+	 */
+
+	if (case_sensitive) {
+		for (s = key; *s != '\0'; s++) {
+			h = ( h << 4 ) + *s;
+			if ((g = ( h & 0xf0000000 )) != 0) {
+				h = h ^ (g >> 24);
+				h = h ^ g;
+			}
+		}
+	} else {
+		for (s = key; *s != '\0'; s++) {
+			c = *s;
+			c = tolower((unsigned char)c);
+			h = ( h << 4 ) + c;
+			if ((g = ( h & 0xf0000000 )) != 0) {
+				h = h ^ (g >> 24);
+				h = h ^ g;
+			}
+		}
+	}
+
+	return (h);
+}
+
+#define FIND(s, k, t, b, e) \
+	b = hash((k), (s)->case_sensitive) % (s)->size; \
+	if ((s)->case_sensitive) { \
+		for (e = ISC_LIST_HEAD((s)->table[b]); \
+		     e != NULL; \
+		     e = ISC_LIST_NEXT(e, link)) { \
+			if (((t) == 0 || e->type == (t)) && \
+			    strcmp(e->key, (k)) == 0) \
+				break; \
+		} \
+	} else { \
+		for (e = ISC_LIST_HEAD((s)->table[b]); \
+		     e != NULL; \
+		     e = ISC_LIST_NEXT(e, link)) { \
+			if (((t) == 0 || e->type == (t)) && \
+			    strcasecmp(e->key, (k)) == 0) \
+				break; \
+		} \
+	}
+
+isc_result_t
+isccc_symtab_lookup(isccc_symtab_t *symtab, const char *key, unsigned int type,
+		  isccc_symvalue_t *value)
+{
+	unsigned int bucket;
+	elt_t *elt;
+
+	REQUIRE(VALID_SYMTAB(symtab));
+	REQUIRE(key != NULL);
+
+	FIND(symtab, key, type, bucket, elt);
+
+	if (elt == NULL)
+		return (ISC_R_NOTFOUND);
+
+	if (value != NULL)
+		*value = elt->value;
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isccc_symtab_define(isccc_symtab_t *symtab, char *key, unsigned int type,
+		  isccc_symvalue_t value, isccc_symexists_t exists_policy)
+{
+	unsigned int bucket;
+	elt_t *elt;
+
+	REQUIRE(VALID_SYMTAB(symtab));
+	REQUIRE(key != NULL);
+	REQUIRE(type != 0);
+
+	FIND(symtab, key, type, bucket, elt);
+
+	if (exists_policy != isccc_symexists_add && elt != NULL) {
+		if (exists_policy == isccc_symexists_reject)
+			return (ISC_R_EXISTS);
+		INSIST(exists_policy == isccc_symexists_replace);
+		ISC_LIST_UNLINK(symtab->table[bucket], elt, link);
+		if (symtab->undefine_action != NULL)
+			(symtab->undefine_action)(elt->key, elt->type,
+						  elt->value,
+						  symtab->undefine_arg);
+	} else {
+		elt = malloc(sizeof(*elt));
+		if (elt == NULL)
+			return (ISC_R_NOMEMORY);
+		ISC_LINK_INIT(elt, link);
+	}
+
+	elt->key = key;
+	elt->type = type;
+	elt->value = value;
+
+	/*
+	 * We prepend so that the most recent definition will be found.
+	 */
+	ISC_LIST_PREPEND(symtab->table[bucket], elt, link);
+
+	return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isccc_symtab_undefine(isccc_symtab_t *symtab, const char *key, unsigned int type) {
+	unsigned int bucket;
+	elt_t *elt;
+
+	REQUIRE(VALID_SYMTAB(symtab));
+	REQUIRE(key != NULL);
+
+	FIND(symtab, key, type, bucket, elt);
+
+	if (elt == NULL)
+		return (ISC_R_NOTFOUND);
+
+	free_elt(symtab, bucket, elt);
+
+	return (ISC_R_SUCCESS);
+}
+
+void
+isccc_symtab_foreach(isccc_symtab_t *symtab, isccc_symtabforeachaction_t action,
+		   void *arg)
+{
+	unsigned int i;
+	elt_t *elt, *nelt;
+
+	REQUIRE(VALID_SYMTAB(symtab));
+	REQUIRE(action != NULL);
+
+	for (i = 0; i < symtab->size; i++) {
+		for (elt = ISC_LIST_HEAD(symtab->table[i]);
+		     elt != NULL;
+		     elt = nelt) {
+			nelt = ISC_LIST_NEXT(elt, link);
+			if ((action)(elt->key, elt->type, elt->value, arg))
+				free_elt(symtab, i, elt);
+		}
+	}
+}
-- 
cgit v1.1