source@mandoc.bsd.lv
 help / color / mirror / Atom feed
* pod2mdoc: ohash compat glue
@ 2015-02-13  9:57 schwarze
  0 siblings, 0 replies; only message in thread
From: schwarze @ 2015-02-13  9:57 UTC (permalink / raw)
  To: source

Log Message:
-----------
ohash compat glue

Modified Files:
--------------
    pod2mdoc:
        Makefile
        dict.c

Added Files:
-----------
    pod2mdoc:
        compat_ohash.c
        compat_ohash.h

Revision Data
-------------
--- /dev/null
+++ compat_ohash.h
@@ -0,0 +1,68 @@
+/* $Id: compat_ohash.h,v 1.1 2015/02/13 09:56:59 schwarze Exp $ */
+/* $OpenBSD: ohash.h,v 1.2 2014/06/02 18:52:03 deraadt Exp $ */
+
+/* Copyright (c) 1999, 2004 Marc Espie <espie@openbsd.org>
+ *
+ * Permission to use, copy, modify, and 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
+ */
+
+/* Open hashing support. 
+ * Open hashing was chosen because it is much lighter than other hash
+ * techniques, and more efficient in most cases.
+ */
+
+/* user-visible data structure */
+struct ohash_info {
+	ptrdiff_t key_offset;
+	void *data;	/* user data */
+	void *(*calloc)(size_t, size_t, void *);
+	void (*free)(void *, void *);
+	void *(*alloc)(size_t, void *);
+};
+
+struct _ohash_record;
+
+/* private structure. It's there just so you can do a sizeof */
+struct ohash {
+	struct _ohash_record 	*t;
+	struct ohash_info 	info;
+	unsigned int 		size;
+	unsigned int 		total;
+	unsigned int 		deleted;
+};
+
+/* For this to be tweakable, we use small primitives, and leave part of the
+ * logic to the client application.  e.g., hashing is left to the client
+ * application.  We also provide a simple table entry lookup that yields
+ * a hashing table index (opaque) to be used in find/insert/remove.
+ * The keys are stored at a known position in the client data.
+ */
+void ohash_init(struct ohash *, unsigned, struct ohash_info *);
+void ohash_delete(struct ohash *);
+
+unsigned int ohash_lookup_interval(struct ohash *, const char *,
+	    const char *, uint32_t);
+unsigned int ohash_lookup_memory(struct ohash *, const char *,
+	    size_t, uint32_t);
+void *ohash_find(struct ohash *, unsigned int);
+void *ohash_remove(struct ohash *, unsigned int);
+void *ohash_insert(struct ohash *, unsigned int, void *);
+void *ohash_first(struct ohash *, unsigned int *);
+void *ohash_next(struct ohash *, unsigned int *);
+unsigned int ohash_entries(struct ohash *);
+
+void *ohash_create_entry(struct ohash_info *, const char *, const char **);
+uint32_t ohash_interval(const char *, const char **);
+
+unsigned int ohash_qlookupi(struct ohash *, const char *, const char **);
+unsigned int ohash_qlookup(struct ohash *, const char *);
Index: dict.c
===================================================================
RCS file: /home/cvs/mdocml/pod2mdoc/dict.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -Ldict.c -Ldict.c -u -p -r1.1 -r1.2
--- dict.c
+++ dict.c
@@ -21,7 +21,12 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+
+#if HAVE_OHASH
 #include <ohash.h>
+#else
+#include "compat_ohash.h"
+#endif
 
 #include "dict.h"
 
--- /dev/null
+++ compat_ohash.c
@@ -0,0 +1,339 @@
+/* $Id: compat_ohash.c,v 1.1 2015/02/13 09:56:59 schwarze Exp $ */
+
+#if HAVE_OHASH
+
+int dummy;
+
+#else
+
+/* $OpenBSD: ohash.c,v 1.1 2014/06/02 18:52:03 deraadt Exp $ */
+
+/* Copyright (c) 1999, 2004 Marc Espie <espie@openbsd.org>
+ *
+ * Permission to use, copy, modify, and 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
+ */
+
+#include <sys/types.h>
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include "compat_ohash.h"
+
+struct _ohash_record {
+	uint32_t	hv;
+	const char	*p;
+};
+
+#define DELETED		((const char *)h)
+#define NONE		(h->size)
+
+/* Don't bother changing the hash table if the change is small enough.  */
+#define MINSIZE		(1UL << 4)
+#define MINDELETED	4
+
+static void ohash_resize(struct ohash *);
+
+
+/* This handles the common case of variable length keys, where the
+ * key is stored at the end of the record.
+ */
+void *
+ohash_create_entry(struct ohash_info *i, const char *start, const char **end)
+{
+	char *p;
+
+	if (!*end)
+		*end = start + strlen(start);
+	p = (i->alloc)(i->key_offset + (*end - start) + 1, i->data);
+	if (p) {
+		memcpy(p+i->key_offset, start, *end-start);
+		p[i->key_offset + (*end - start)] = '\0';
+	}
+	return (void *)p;
+}
+
+/* hash_delete only frees the hash structure. Use hash_first/hash_next
+ * to free entries as well.  */
+void
+ohash_delete(struct ohash *h)
+{
+	(h->info.free)(h->t, h->info.data);
+#ifndef NDEBUG
+	h->t = NULL;
+#endif
+}
+
+static void
+ohash_resize(struct ohash *h)
+{
+	struct _ohash_record *n;
+	size_t ns;
+	unsigned int	j;
+	unsigned int	i, incr;
+
+	if (4 * h->deleted < h->total) {
+		if (h->size >= (UINT_MAX >> 1U))
+			ns = UINT_MAX;
+		else
+			ns = h->size << 1U;
+	} else if (3 * h->deleted > 2 * h->total)
+		ns = h->size >> 1U;
+	else
+		ns = h->size;
+	if (ns < MINSIZE)
+		ns = MINSIZE;
+#ifdef STATS_HASH
+	STAT_HASH_EXPAND++;
+	STAT_HASH_SIZE += ns - h->size;
+#endif
+
+	n = (h->info.calloc)(ns, sizeof(struct _ohash_record), h->info.data);
+	if (!n)
+		return;
+
+	for (j = 0; j < h->size; j++) {
+		if (h->t[j].p != NULL && h->t[j].p != DELETED) {
+			i = h->t[j].hv % ns;
+			incr = ((h->t[j].hv % (ns - 2)) & ~1) + 1;
+			while (n[i].p != NULL) {
+				i += incr;
+				if (i >= ns)
+					i -= ns;
+			}
+			n[i].hv = h->t[j].hv;
+			n[i].p = h->t[j].p;
+		}
+	}
+	(h->info.free)(h->t, h->info.data);
+	h->t = n;
+	h->size = ns;
+	h->total -= h->deleted;
+	h->deleted = 0;
+}
+
+void *
+ohash_remove(struct ohash *h, unsigned int i)
+{
+	void		*result = (void *)h->t[i].p;
+
+	if (result == NULL || result == DELETED)
+		return NULL;
+
+#ifdef STATS_HASH
+	STAT_HASH_ENTRIES--;
+#endif
+	h->t[i].p = DELETED;
+	h->deleted++;
+	if (h->deleted >= MINDELETED && 4 * h->deleted > h->total)
+		ohash_resize(h);
+	return result;
+}
+
+void *
+ohash_find(struct ohash *h, unsigned int i)
+{
+	if (h->t[i].p == DELETED)
+		return NULL;
+	else
+		return (void *)h->t[i].p;
+}
+
+void *
+ohash_insert(struct ohash *h, unsigned int i, void *p)
+{
+#ifdef STATS_HASH
+	STAT_HASH_ENTRIES++;
+#endif
+	if (h->t[i].p == DELETED) {
+		h->deleted--;
+		h->t[i].p = p;
+	} else {
+		h->t[i].p = p;
+		/* Arbitrary resize boundary.  Tweak if not efficient enough.  */
+		if (++h->total * 4 > h->size * 3)
+			ohash_resize(h);
+	}
+	return p;
+}
+
+unsigned int
+ohash_entries(struct ohash *h)
+{
+	return h->total - h->deleted;
+}
+
+void *
+ohash_first(struct ohash *h, unsigned int *pos)
+{
+	*pos = 0;
+	return ohash_next(h, pos);
+}
+
+void *
+ohash_next(struct ohash *h, unsigned int *pos)
+{
+	for (; *pos < h->size; (*pos)++)
+		if (h->t[*pos].p != DELETED && h->t[*pos].p != NULL)
+			return (void *)h->t[(*pos)++].p;
+	return NULL;
+}
+
+void
+ohash_init(struct ohash *h, unsigned int size, struct ohash_info *info)
+{
+	h->size = 1UL << size;
+	if (h->size < MINSIZE)
+		h->size = MINSIZE;
+#ifdef STATS_HASH
+	STAT_HASH_CREATION++;
+	STAT_HASH_SIZE += h->size;
+#endif
+	/* Copy info so that caller may free it.  */
+	h->info.key_offset = info->key_offset;
+	h->info.calloc = info->calloc;
+	h->info.free = info->free;
+	h->info.alloc = info->alloc;
+	h->info.data = info->data;
+	h->t = (h->info.calloc)(h->size, sizeof(struct _ohash_record),
+		    h->info.data);
+	h->total = h->deleted = 0;
+}
+
+uint32_t
+ohash_interval(const char *s, const char **e)
+{
+	uint32_t k;
+
+	if (!*e)
+		*e = s + strlen(s);
+	if (s == *e)
+		k = 0;
+	else
+		k = *s++;
+	while (s != *e)
+		k =  ((k << 2) | (k >> 30)) ^ *s++;
+	return k;
+}
+
+unsigned int
+ohash_lookup_interval(struct ohash *h, const char *start, const char *end,
+    uint32_t hv)
+{
+	unsigned int	i, incr;
+	unsigned int	empty;
+
+#ifdef STATS_HASH
+	STAT_HASH_LOOKUP++;
+#endif
+	empty = NONE;
+	i = hv % h->size;
+	incr = ((hv % (h->size-2)) & ~1) + 1;
+	while (h->t[i].p != NULL) {
+#ifdef STATS_HASH
+		STAT_HASH_LENGTH++;
+#endif
+		if (h->t[i].p == DELETED) {
+			if (empty == NONE)
+				empty = i;
+		} else if (h->t[i].hv == hv &&
+		    strncmp(h->t[i].p+h->info.key_offset, start,
+			end - start) == 0 &&
+		    (h->t[i].p+h->info.key_offset)[end-start] == '\0') {
+			if (empty != NONE) {
+				h->t[empty].hv = hv;
+				h->t[empty].p = h->t[i].p;
+				h->t[i].p = DELETED;
+				return empty;
+			} else {
+#ifdef STATS_HASH
+				STAT_HASH_POSITIVE++;
+#endif
+				return i;
+			}
+		}
+		i += incr;
+		if (i >= h->size)
+			i -= h->size;
+	}
+
+	/* Found an empty position.  */
+	if (empty != NONE)
+		i = empty;
+	h->t[i].hv = hv;
+	return i;
+}
+
+unsigned int
+ohash_lookup_memory(struct ohash *h, const char *k, size_t size, uint32_t hv)
+{
+	unsigned int	i, incr;
+	unsigned int	empty;
+
+#ifdef STATS_HASH
+	STAT_HASH_LOOKUP++;
+#endif
+	empty = NONE;
+	i = hv % h->size;
+	incr = ((hv % (h->size-2)) & ~1) + 1;
+	while (h->t[i].p != NULL) {
+#ifdef STATS_HASH
+		STAT_HASH_LENGTH++;
+#endif
+		if (h->t[i].p == DELETED) {
+			if (empty == NONE)
+				empty = i;
+		} else if (h->t[i].hv == hv &&
+		    memcmp(h->t[i].p+h->info.key_offset, k, size) == 0) {
+			if (empty != NONE) {
+				h->t[empty].hv = hv;
+				h->t[empty].p = h->t[i].p;
+				h->t[i].p = DELETED;
+				return empty;
+			} else {
+#ifdef STATS_HASH
+				STAT_HASH_POSITIVE++;
+#endif
+			}	return i;
+		}
+		i += incr;
+		if (i >= h->size)
+			i -= h->size;
+	}
+
+	/* Found an empty position.  */
+	if (empty != NONE)
+		i = empty;
+	h->t[i].hv = hv;
+	return i;
+}
+
+unsigned int
+ohash_qlookup(struct ohash *h, const char *s)
+{
+	const char *e = NULL;
+	return ohash_qlookupi(h, s, &e);
+}
+
+unsigned int
+ohash_qlookupi(struct ohash *h, const char *s, const char **e)
+{
+	uint32_t hv;
+
+	hv = ohash_interval(s, e);
+	return ohash_lookup_interval(h, s, *e, hv);
+}
+
+#endif /*!HAVE_OHASH*/
Index: Makefile
===================================================================
RCS file: /home/cvs/mdocml/pod2mdoc/Makefile,v
retrieving revision 1.13
retrieving revision 1.14
diff -LMakefile -LMakefile -u -p -r1.13 -r1.14
--- Makefile
+++ Makefile
@@ -1,24 +1,97 @@
-VERSION = 0.1
-CFLAGS += -g -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings 
-WWWPREFIX = /usr/vhosts/mdocml.bsd.lv/www/htdocs/pod2mdoc
+# $Id$
+#
+# Copyright (c) 2014 Kristaps Dzonsons <kristaps@bsd.lv>
+# Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org>
+#
+# Permission to use, copy, modify, and 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
 
-pod2mdoc: dict.o pod2mdoc.o
-	$(CC) $(LDFLAGS) -o $@ dict.o pod2mdoc.o -lutil
+VERSION =	0.1
 
-www: index.html pod2mdoc.1.html pod2mdoc-$(VERSION).tgz
+# === USER CONFIGURATION ===============================================
 
-installwww: www
-	mkdir -p $(WWWPREFIX)/snapshots
-	install -m 0444 index.html pod2mdoc.1.html $(WWWPREFIX)
-	install -m 0444 pod2mdoc-$(VERSION).tgz $(WWWPREFIX)/snapshots
-	install -m 0444 pod2mdoc-$(VERSION).tgz \
-		$(WWWPREFIX)/snapshots/pod2mdoc.tgz
+CFLAGS +=	-g
+CFLAGS +=	-W -Wall -Wstrict-prototypes
+CFLAGS +=	-Wno-unused-parameter -Wwrite-strings
+
+# Change to 0 on systems other than OpenBSD that do not provide
+# a native ohash library; compat_ohash.* will be used in that case.
+
+CFLAGS +=	-DHAVE_OHASH=0
+
+# May be needed on systems other than OpenBSD when using HAVE_OHASH=1
+# if ohash.h is not in the default header search path and/or
+# the library containing the ohash functions is not in the
+# default library search path.
+
+#CFLAGS +=	-I/usr/local/include
+#LDFLAGS +=	-L/usr/local/lib
+
+# Needed for the ohash library on OpenBSD.
+# You may have to comment this out on other systems,
+# in particular when using HAVE_OHASH=0.
+
+#LDADD +=	-lutil
+
+# === LIST OF FILES ====================================================
+
+SRCS =		compat_ohash.c \
+		dict.c \
+		pod2mdoc.c
+
+DISTFILES =	Makefile \
+		compat_ohash.h \
+		dict.h \
+		pod2mdoc.1 \
+		$(SRCS)
+
+OBJS =		compat_ohash.o \
+		dict.o \
+		pod2mdoc.o
+
+WWW_HTML =	index.html \
+		pod2mdoc.1.html
+
+# === DEPENDENCY HANDLING ==============================================
 
-dist: pod2mdoc-$(VERSION).tgz
+all: pod2mdoc
 
-pod2mdoc-$(VERSION).tgz:
+dist: $(WWW_HTML) pod2mdoc.tgz
+
+.PHONY: clean installwww
+
+# === TARGETS CONTAINING SHELL COMMANDS ================================
+
+clean:
+	rm -f pod2mdoc $(OBJS) $(WWW_HTML) pod2mdoc.tgz
+	rm -rf *.dSYM
+
+pod2mdoc: $(OBJS)
+	$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LDADD)
+
+# --- maintainer targets ---
+
+WWWPREFIX = /var/www/vhosts/mdocml.bsd.lv/htdocs/pod2mdoc
+
+installwww: dist
+	mkdir -p $(WWWPREFIX)/snapshots
+	install -m 0444 $(WWW_HTML) $(WWWPREFIX)
+	install -m 0444 pod2mdoc.tgz $(WWWPREFIX)/snapshots
+	ln -f $(WWWPREFIX)/snapshots/pod2mdoc.tgz \
+		$(WWWPREFIX)/snapshots/pod2mdoc-$(VERSION).tgz
+
+pod2mdoc.tgz: $(DISTFILES)
 	mkdir -p .dist/pod2mdoc-$(VERSION)
-	install -m 0444 pod2mdoc.c Makefile pod2mdoc.1 .dist/pod2mdoc-$(VERSION)
+	install -m 0644 $(DISTFILES) .dist/pod2mdoc-$(VERSION)
 	(cd .dist && tar zcf ../$@ pod2mdoc-$(VERSION))
 	rm -rf .dist
 
@@ -27,8 +100,3 @@ index.html: index.xml
 
 pod2mdoc.1.html: pod2mdoc.1
 	mandoc -Thtml pod2mdoc.1 >$@
-
-clean:
-	rm -f pod2mdoc dict.o pod2mdoc.o pod2mdoc-$(VERSION).tgz \
-		index.html pod2mdoc.1.html
-	rm -rf pod2mdoc.dSYM
--
 To unsubscribe send an email to source+unsubscribe@mdocml.bsd.lv

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2015-02-13  9:57 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-13  9:57 pod2mdoc: ohash compat glue schwarze

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).